/* eslint-disable max-len */
/* globals seAlert */
import SvgCanvas from "../../svgcanvas/svgcanvas.js";
import { isValidUnit, getTypeMap, convertUnit } from "../../common/units.js";
const { $qa, $id } = SvgCanvas;
/*
* register actions for left panel
*/
/**
*
*/
class TopPanel {
/**
* @param {PlainObject} editor svgedit handler
*/
constructor(editor) {
this.editor = editor;
}
/**
* @type {module}
*/
displayTool(className) {
// default display is 'none' so removing the property will make the panel visible
$qa(`.${className}`).map( (el) => el.style.removeProperty('display'));
}
/**
* @type {module}
*/
hideTool(className) {
$qa(`.${className}`).map( (el) => el.style.display = 'none');
}
/**
* @type {module}
*/
get selectedElement() {
return this.editor.selectedElement;
}
/**
* @type {module}
*/
get multiselected() {
return this.editor.multiselected;
}
/**
* @type {module}
*/
get path() {
return this.editor.svgCanvas.pathActions;
}
/**
*
* @param {Element} opt
* @param {boolean} changeElem
* @returns {void}
*/
setStrokeOpt(opt, changeElem) {
const { id } = opt;
const bits = id.split('_');
const [ pre, val ] = bits;
if (changeElem) {
this.svgCanvas.setStrokeAttr('stroke-' + pre, val);
}
opt.classList.add('current');
const elements = Array.prototype.filter.call(opt.parentNode.children, function (child) {
return child !== opt;
});
Array.from(elements).forEach(function (element) {
element.classList.remove('current');
});
}
/**
* Updates the toolbar (colors, opacity, etc) based on the selected element.
* This function also updates the opacity and id elements that are in the
* context panel.
* @returns {void}
*/
update() {
let i; let len;
if (this.selectedElement) {
switch (this.selectedElement.tagName) {
case "use":
case "image":
case "foreignObject":
break;
case "g":
case "a": {
// Look for common styles
const childs = this.selectedElement.getElementsByTagName("*");
let gWidth = null;
for (i = 0, len = childs.length; i < len; i++) {
const swidth = childs[i].getAttribute("stroke-width");
if (i === 0) {
gWidth = swidth;
} else if (gWidth !== swidth) {
gWidth = null;
}
}
$id("stroke_width").value = (gWidth === null ? "" : gWidth);
this.editor.bottomPanel.updateColorpickers(true);
break;
}
default: {
this.editor.bottomPanel.updateColorpickers(true);
$id("stroke_width").value = this.selectedElement.getAttribute("stroke-width") || 1;
$id("stroke_style").value = this.selectedElement.getAttribute("stroke-dasharray") || "none";
$id("stroke_style").setAttribute("value", $id("stroke_style").value);
let attr =
this.selectedElement.getAttribute("stroke-linejoin") || "miter";
if ($id("linejoin_" + attr)) {
this.setStrokeOpt($id("linejoin_" + attr));
$id("stroke_linejoin").setAttribute("value", attr);
}
attr = this.selectedElement.getAttribute("stroke-linecap") || "butt";
if ($id("linecap_" + attr)) {
this.setStrokeOpt($id("linecap_" + attr));
$id("stroke_linecap").setAttribute("value", attr);
}
}
}
}
// All elements including image and group have opacity
if (this.selectedElement) {
const opacPerc =
(this.selectedElement.getAttribute("opacity") || 1.0) * 100;
$id("opacity").value = opacPerc;
$id("elem_id").value = this.selectedElement.id;
$id("elem_class").value = this.selectedElement.getAttribute("class") ?? "";
}
this.editor.bottomPanel.updateToolButtonState();
}
/**
* @param {PlainObject} [opts={}]
* @param {boolean} [opts.cancelDeletes=false]
* @returns {void} Resolves to `undefined`
*/
promptImgURL({ cancelDeletes = false } = {}) {
let curhref = this.editor.svgCanvas.getHref(this.editor.selectedElement);
curhref = curhref.startsWith("data:") ? "" : curhref;
// eslint-disable-next-line no-alert
const url = prompt(
this.editor.i18next.t('notification.enterNewImgURL'),
curhref
);
if (url) {
this.setImageURL(url);
} else if (cancelDeletes) {
this.editor.svgCanvas.deleteSelectedElements();
}
}
/**
* Updates the context panel tools based on the selected element.
* @returns {void}
*/
updateContextPanel() {
let elem = this.editor.selectedElement;
// If element has just been deleted, consider it null
if (!elem?.parentNode) {
elem = null;
}
const currentLayerName = this.editor.svgCanvas
.getCurrentDrawing()
.getCurrentLayerName();
const currentMode = this.editor.svgCanvas.getMode();
const unit =
this.editor.configObj.curConfig.baseUnit !== "px"
? this.editor.configObj.curConfig.baseUnit
: null;
const isNode = currentMode === "pathedit"; // elem ? (elem.id && elem.id.startsWith('pathpointgrip')) : false;
const menuItems = document.getElementById("se-cmenu_canvas");
this.hideTool("selected_panel");
this.hideTool("multiselected_panel");
this.hideTool("g_panel");
this.hideTool("rect_panel");
this.hideTool("circle_panel");
this.hideTool("ellipse_panel");
this.hideTool("line_panel");
this.hideTool("text_panel");
this.hideTool("image_panel");
this.hideTool("container_panel");
this.hideTool("use_panel");
this.hideTool("a_panel");
this.hideTool("xy_panel");
if (elem) {
const elname = elem.nodeName;
const angle = this.editor.svgCanvas.getRotationAngle(elem);
$id("angle").value = angle;
const blurval = this.editor.svgCanvas.getBlur(elem) * 10;
$id("blur").value = blurval;
if (
this.editor.svgCanvas.addedNew &&
elname === "image" &&
this.editor.svgCanvas.getMode() === "image" &&
!this.editor.svgCanvas.getHref(elem).startsWith("data:")
) {
/* await */ this.promptImgURL({ cancelDeletes: true });
}
if (!isNode && currentMode !== "pathedit") {
this.displayTool("selected_panel");
// Elements in this array already have coord fields
if ([ "line", "circle", "ellipse" ].includes(elname)) {
this.hideTool("xy_panel");
} else {
let x; let y;
// Get BBox vals for g, polyline and path
if ([ "g", "polyline", "path" ].includes(elname)) {
const bb = this.editor.svgCanvas.getStrokedBBox([ elem ]);
if (bb) {
({ x, y } = bb);
}
} else {
x = elem.getAttribute("x");
y = elem.getAttribute("y");
}
if (unit) {
x = convertUnit(x);
y = convertUnit(y);
}
$id("selected_x").value = (x || 0);
$id("selected_y").value = (y || 0);
this.displayTool("xy_panel");
}
// Elements in this array cannot be converted to a path
if ([
"image",
"text",
"path",
"g",
"use"
].includes(elname)) {
this.hideTool("tool_topath");
} else {
this.displayTool("tool_topath");
}
if (elname === "path") {
this.displayTool("tool_reorient");
} else {
this.hideTool("tool_reorient");
}
$id("tool_reorient").disabled = (angle === 0);
} else {
const point = this.path.getNodePoint();
$id("tool_add_subpath").pressed = false;
// eslint-disable-next-line max-len
(!this.path.canDeleteNodes) ? $id("tool_node_delete").classList.add("disabled") : $id("tool_node_delete").classList.remove("disabled");
// Show open/close button based on selected point
// setIcon('#tool_openclose_path', path.closed_subpath ? 'open_path' : 'close_path');
if (point) {
const segType = $id("seg_type");
if (unit) {
point.x = convertUnit(point.x);
point.y = convertUnit(point.y);
}
$id("path_node_x").value = (point.x);
$id("path_node_y").value = (point.y);
if (point.type) {
segType.value = (point.type);
segType.removeAttribute("disabled");
} else {
segType.value = 4;
segType.setAttribute("disabled", "disabled");
}
}
return;
}
// update contextual tools here
const panels = {
g: [],
a: [],
rect: [ "rx", "width", "height" ],
image: [ "width", "height" ],
circle: [ "cx", "cy", "r" ],
ellipse: [ "cx", "cy", "rx", "ry" ],
line: [ "x1", "y1", "x2", "y2" ],
text: [],
use: []
};
const { tagName } = elem;
let linkHref = null;
if (tagName === "a") {
linkHref = this.editor.svgCanvas.getHref(elem);
this.displayTool("g_panel");
}
// siblings
if (elem.parentNode) {
const selements = Array.prototype.filter.call(elem.parentNode.children, function (child) {
return child !== elem;
});
if (elem.parentNode.tagName === "a" && !selements.length) {
this.displayTool("a_panel");
linkHref = this.editor.svgCanvas.getHref(elem.parentNode);
}
}
// Hide/show the make_link buttons
if (linkHref) {
this.displayTool('tool_make_link');
this.displayTool('tool_make_link_multi');
$id("link_url").value = linkHref;
} else {
this.hideTool('tool_make_link');
this.hideTool('tool_make_link_multi');
}
if (panels[tagName]) {
const curPanel = panels[tagName];
this.displayTool(tagName + "_panel");
curPanel.forEach((item) => {
let attrVal = elem.getAttribute(item);
if (this.editor.configObj.curConfig.baseUnit !== "px" && elem[item]) {
const bv = elem[item].baseVal.value;
attrVal = convertUnit(bv);
}
$id(`${tagName}_${item}`).value = attrVal || 0;
});
if (tagName === "text") {
this.displayTool("text_panel");
$id("tool_italic").pressed = this.editor.svgCanvas.getItalic();
$id("tool_bold").pressed = this.editor.svgCanvas.getBold();
$id("tool_font_family").setAttribute("value", elem.getAttribute("font-family"));
$id("font_size").value = elem.getAttribute("font-size");
$id("text").value = elem.textContent;
const textAnchorStart = $id("tool_text_anchor_start");
const textAnchorMiddle = $id("tool_text_anchor_middle");
const textAnchorEnd = $id("tool_text_anchor_end");
switch (elem.getAttribute("text-anchor")) {
case "start":
textAnchorStart.pressed = true;
textAnchorMiddle.pressed = false;
textAnchorEnd.pressed = false;
break;
case "middle":
textAnchorStart.pressed = false;
textAnchorMiddle.pressed = true;
textAnchorEnd.pressed = false;
break;
case "end":
textAnchorStart.pressed = false;
textAnchorMiddle.pressed = false;
textAnchorEnd.pressed = true;
break;
}
if (this.editor.svgCanvas.addedNew) {
// Timeout needed for IE9
setTimeout(() => {
$id("text").focus();
$id("text").select();
}, 100);
}
// text
} else if (
tagName === "image" &&
this.editor.svgCanvas.getMode() === "image"
) {
this.editor.svgCanvas.setImageURL(
this.editor.svgCanvas.getHref(elem)
);
// image
} else if (tagName === "g" || tagName === "use") {
this.displayTool("container_panel");
const title = this.editor.svgCanvas.getTitle();
const label = $id("g_title");
label.value = title;
$id("g_title").disabled = (tagName === "use");
}
}
menuItems.setAttribute(
(tagName === "g" ? "en" : "dis") + "ablemenuitems",
"#ungroup"
);
menuItems.setAttribute(
(tagName === "g" || !this.multiselected ? "dis" : "en") +
"ablemenuitems",
"#group"
);
// if (!isNullish(elem))
} else if (this.multiselected) {
this.displayTool("multiselected_panel");
menuItems.setAttribute("enablemenuitems", "#group");
menuItems.setAttribute("disablemenuitems", "#ungroup");
} else {
menuItems.setAttribute(
"disablemenuitems",
"#delete,#cut,#copy,#group,#ungroup,#move_front,#move_up,#move_down,#move_back"
);
}
// update history buttons
$id("tool_undo").disabled =
this.editor.svgCanvas.undoMgr.getUndoStackSize() === 0;
$id("tool_redo").disabled =
this.editor.svgCanvas.undoMgr.getRedoStackSize() === 0;
this.editor.svgCanvas.addedNew = false;
if ((elem && !isNode) || this.multiselected) {
// update the selected elements' layer
$id("selLayerNames").removeAttribute("disabled");
$id("selLayerNames").value = currentLayerName;
$id("selLayerNames").setAttribute("value", currentLayerName);
// Enable regular menu options
const canCMenu = document.getElementById("se-cmenu_canvas");
canCMenu.setAttribute(
"enablemenuitems",
"#delete,#cut,#copy,#move_front,#move_up,#move_down,#move_back"
);
} else {
$id("selLayerNames").setAttribute("disabled", "disabled");
}
}
/**
* @param {Event} [e] Not used.
* @param {boolean} forSaving
* @returns {void}
*/
showSourceEditor(e, forSaving) {
const $editorDialog = document.getElementById("se-svg-editor-dialog");
if ($editorDialog.getAttribute("dialog") === "open") return;
const origSource = this.editor.svgCanvas.getSvgString();
$editorDialog.setAttribute("dialog", "open");
$editorDialog.setAttribute("value", origSource);
$editorDialog.setAttribute("copysec", Boolean(forSaving));
$editorDialog.setAttribute("applysec", !forSaving);
}
/**
*
* @returns {void}
*/
clickWireframe() {
$id("tool_wireframe").pressed = !$id("tool_wireframe").pressed;
this.editor.workarea.classList.toggle("wireframe");
const wfRules = $id("wireframe_rules");
if (!wfRules) {
const fcRules = document.createElement('style');
fcRules.setAttribute('id', 'wireframe_rules');
document.getElementsByTagName("head")[0].appendChild(fcRules);
} else {
while (wfRules.firstChild)
wfRules.removeChild(wfRules.firstChild);
}
this.editor.updateWireFrame();
}
/**
*
* @returns {void}
*/
clickUndo() {
const { undoMgr, textActions } = this.editor.svgCanvas;
if (undoMgr.getUndoStackSize() > 0) {
undoMgr.undo();
this.editor.layersPanel.populateLayers();
if (this.editor.svgCanvas.getMode() === 'textedit') {
textActions.clear();
}
}
}
/**
*
* @returns {void}
*/
clickRedo() {
const { undoMgr } = this.editor.svgCanvas;
if (undoMgr.getRedoStackSize() > 0) {
undoMgr.redo();
this.editor.layersPanel.populateLayers();
}
}
/**
* @type {module}
*/
changeRectRadius(e) {
this.editor.svgCanvas.setRectRadius(e.target.value);
}
/**
* @type {module}
*/
changeFontSize(e) {
this.editor.svgCanvas.setFontSize(e.target.value);
}
/**
* @type {module}
*/
changeRotationAngle(e) {
this.editor.svgCanvas.setRotationAngle(e.target.value);
// eslint-disable-next-line max-len
(Number.parseInt(e.target.value) === 0) ? $id("tool_reorient").classList.add("disabled") : $id("tool_reorient").classList.remove("disabled");
}
/**
* @param {PlainObject} e
* @returns {void}
*/
changeBlur(e) {
this.editor.svgCanvas.setBlur(e.target.value / 10, true);
}
/**
*
* @returns {void}
*/
clickGroup() {
// group
if (this.editor.multiselected) {
this.editor.svgCanvas.groupSelectedElements();
// ungroup
} else if (this.editor.selectedElement) {
this.editor.svgCanvas.ungroupSelectedElement();
}
}
/**
*
* @returns {void}
*/
clickClone() {
this.editor.svgCanvas.cloneSelectedElements(20, 20);
}
/**
* @param {PlainObject} evt
* @returns {void}
*/
clickAlignEle(evt) {
this.editor.svgCanvas.alignSelectedElements(evt.detail.value, "page");
}
/**
* @param {string} pos indicate the alignment relative to top, bottom, middle etc..
* @returns {void}
*/
clickAlign(pos) {
let value = $id("tool_align_relative").value;
if (value === "") {
value = "selected";
}
this.editor.svgCanvas.alignSelectedElements(pos, value);
}
/**
*
* @type {module}
*/
attrChanger(e) {
const attr = e.target.getAttribute("data-attr");
let val = e.target.value;
const valid = isValidUnit(attr, val, this.selectedElement);
if (!valid) {
e.target.value = this.selectedElement.getAttribute(attr);
// eslint-disable-next-line no-alert
alert(this.editor.i18next.t('notification.invalidAttrValGiven'));
return false;
}
if (attr !== "id" && attr !== "class") {
if (isNaN(val)) {
val = this.editor.svgCanvas.convertToNum(attr, val);
} else if (this.editor.configObj.curConfig.baseUnit !== "px") {
// Convert unitless value to one with given unit
const unitData = getTypeMap();
if (
this.editor.selectedElement[attr] ||
this.editor.svgCanvas.getMode() === "pathedit" ||
attr === "x" ||
attr === "y"
) {
val *= unitData[this.editor.configObj.curConfig.baseUnit];
}
}
}
// if the user is changing the id, then de-select the element first
// change the ID, then re-select it with the new ID
if (attr === "id") {
const elem = this.editor.selectedElement;
this.editor.svgCanvas.clearSelection();
elem.id = val;
this.editor.svgCanvas.addToSelection([ elem ], true);
} else {
this.editor.svgCanvas.changeSelectedAttribute(attr, val);
}
return true;
}
/**
*
* @returns {void}
*/
convertToPath() {
if (this.editor.selectedElement) {
this.editor.svgCanvas.convertToPath();
}
}
/**
*
* @returns {void}
*/
reorientPath() {
if (this.editor.selectedElement) {
this.path.reorient();
}
}
/**
*
* @returns {void} Resolves to `undefined`
*/
makeHyperlink() {
if (this.editor.selectedElement || this.multiselected) {
// eslint-disable-next-line no-alert
const url = prompt(
this.editor.i18next.t('notification.enterNewLinkURL'),
"http://"
);
if (url) {
this.editor.svgCanvas.makeHyperlink(url);
}
}
}
/**
*
* @returns {void}
*/
linkControlPoints() {
$id("tool_node_link").pressed = ($id("tool_node_link").pressed) ? false : true;
const linked = ($id("tool_node_link").pressed) ? true : false;
this.path.linkControlPoints(linked);
}
/**
*
* @returns {void}
*/
clonePathNode() {
if (this.path.getNodePoint()) {
this.path.clonePathNode();
}
}
/**
*
* @returns {void}
*/
deletePathNode() {
if (this.path.getNodePoint()) {
this.path.deletePathNode();
}
}
/**
*
* @returns {void}
*/
addSubPath() {
const button = $id("tool_add_subpath");
const sp = !button.classList.contains("pressed");
button.pressed = sp;
// button.toggleClass('push_button_pressed tool_button');
this.path.addSubPath(sp);
}
/**
*
* @returns {void}
*/
opencloseSubPath() {
this.path.opencloseSubPath();
}
/**
* Delete is a contextual tool that only appears in the ribbon if
* an element has been selected.
* @returns {void}
*/
deleteSelected() {
if (this.editor.selectedElement || this.editor.multiselected) {
this.editor.svgCanvas.deleteSelectedElements();
}
}
/**
*
* @returns {void}
*/
moveToTopSelected() {
if (this.editor.selectedElement) {
this.editor.svgCanvas.moveToTopSelectedElement();
}
}
/**
*
* @returns {void}
*/
moveToBottomSelected() {
if (this.editor.selectedElement) {
this.editor.svgCanvas.moveToBottomSelectedElement();
}
}
/**
*
* @returns {false}
*/
clickBold() {
this.editor.svgCanvas.setBold(!this.editor.svgCanvas.getBold());
this.updateContextPanel();
return false;
}
/**
*
* @returns {false}
*/
clickItalic() {
this.editor.svgCanvas.setItalic(!this.editor.svgCanvas.getItalic());
this.updateContextPanel();
return false;
}
/**
*
* @param {string} value "start","end" or "middle"
* @returns {false}
*/
clickTextAnchor(value) {
this.editor.svgCanvas.setTextAnchor(value);
this.updateContextPanel();
return false;
}
/**
* Set a selected image's URL.
* @function module:SVGthis.setImageURL
* @param {string} url
* @returns {void}
*/
setImageURL(url) {
const { editor } = this;
if (!url) {
url = editor.defaultImageURL;
}
editor.svgCanvas.setImageURL(url);
$id("image_url").value = url;
if (url.startsWith('data:')) {
// data URI found
this.hideTool("image_url");
} else {
// regular URL
const promised = editor.svgCanvas.embedImage(url);
// eslint-disable-next-line promise/catch-or-return
promised
// eslint-disable-next-line promise/always-return
.then(() => {
// switch into "select" mode if we've clicked on an element
editor.svgCanvas.setMode('select');
editor.svgCanvas.selectOnly(editor.svgCanvas.getSelectedElems(), true);
}, (error) => {
console.error("error =", error);
seAlert(editor.i18next.t('tools.no_embed'));
editor.svgCanvas.deleteSelectedElements();
});
this.displayTool("image_url");
}
}
/**
* @param {boolean} editmode
* @param {module:svgcanvas.SvgCanvas#event:selected} elems
* @returns {void}
*/
togglePathEditMode(editMode, elems) {
if (editMode) {
this.displayTool('path_node_panel');
} else {
this.hideTool('path_node_panel');
}
if (editMode) {
// Change select icon
$id('tool_path').pressed = false;
$id('tool_select').pressed = true;
$id('tool_select').setAttribute('src', `select_node.svg`);
this.editor.multiselected = false;
if (elems.length) {
this.editor.selectedElement = elems[0];
}
} else {
setTimeout(() => {
$id('tool_select').setAttribute('src', `select.svg`);
}, 1000);
}
}
/**
* @type {module}
*/
init() {
// add Top panel
const template = document.createElement("template");
const { i18next } = this.editor;
// eslint-disable-next-line no-unsanitized/property
template.innerHTML = `
<div id="tools_top">
<div id="editor_panel">
<div class="tool_sep"></div>
<se-button id="tool_source" title="tools.tool_source" shortcut="U" src="source.svg"></se-button>
<se-button id="tool_wireframe" title="tools.wireframe_mode" shortcut="F" src="wireframe.svg"></se-button>
</div> <!-- editor_panel -->
<div id="history_panel">
<div class="tool_sep"></div>
<se-button id="tool_undo" title="tools.undo" shortcut="Z" src="undo.svg" disabled></se-button>
<se-button id="tool_redo" title="tools.redo" shortcut="Y" src="redo.svg" disabled></se-button>
</div> <!-- history_panel -->
<!-- Buttons when a single element is selected -->
<div class="selected_panel">
<div class="tool_sep"></div>
<se-button id="tool_clone" title="tools.clone" shortcut="D" src="clone.svg"></se-button>
<se-button id="tool_delete" title="tools.del" shortcut="Delete/Backspace" src="delete.svg"></se-button>
</div>
<div class="selected_panel">
<div class="tool_sep"></div>
<se-button id="tool_move_top" title="tools.move_top" shortcut="Ctrl+Shift+]" src="move_top.svg"></se-button>
<se-button id="tool_move_bottom" title="tools.move_bottom" shortcut="Ctrl+Shift+[" src="move_bottom.svg"></se-button>
</div>
<div class="selected_panel">
<se-button id="tool_topath" title="tools.to_path" src="to_path.svg"></se-button>
<se-button id="tool_reorient" title="tools.reorient_path" src="reorient.svg"></se-button>
<se-button id="tool_make_link" title="tools.make_link" src="globe_link.svg"></se-button>
</div>
<div class="selected_panel">
<div class="tool_sep"></div>
<se-input id="elem_id" data-attr="id" size="10" label="properties.id_label" title="properties.id"></se-input>
</div>
<div class="selected_panel">
<se-input id="elem_class" data-attr="class" size="10" label="properties.class_label" title="properties.class"></se-input>
<se-spin-input size="3" id="angle" min=-180 max=180 step=5 src="angle.svg" title="properties.angle"></se-spin-input>
<se-spin-input size="2" id="blur" min=0 max=100 step=5 src="blur.svg" title="properties.blur"></se-spin-input>
<se-list id="tool_position" title="tools.align_to_page" label="" width="22px" height="22px">
<se-list-item id="tool_posleft" value="l" title="tools.align_left" src="align_left.svg" img-height="22px"></se-list-item>
<se-list-item id="tool_poscenter" value="c" title="tools.align_center" src="align_center.svg" img-height="22px"></se-list-item>
<se-list-item id="tool_posright" value="r" title="tools.align_right" src="align_right.svg" img-height="22px"></se-list-item>
<se-list-item id="tool_postop" value="t" title="tools.align_top" src="align_top.svg" img-height="22px"></se-list-item>
<se-list-item id="tool_posmiddle" value="m" title="tools.align_middle" src="align_middle.svg" img-height="22px"></se-list-item>
<se-list-item id="tool_posbottom" value="b" src="align_bottom.svg" title="tools.align_bottom" img-height="22px"></se-list-item>
</se-list>
</div>
<div class="xy_panel">
<se-spin-input id="selected_x" data-attr="x" size="4" type="text" label="properties.x_label" title="properties.pos_x">
</se-spin-input>
<se-spin-input id="selected_y" data-attr="y" size="4" type="text" label="properties.y_label" title="properties.pos_y">
</se-spin-input>
</div>
<!-- Buttons when multiple elements are selected -->
<div class="multiselected_panel">
<div class="tool_sep"></div>
<se-button id="tool_clone_multi" title="tools.clone" shortcut="C" src="clone.svg"></se-button>
<se-button id="tool_delete_multi" title="tools.del" shortcut="Delete/Backspace" src="delete.svg"></se-button>
</div>
<div class="multiselected_panel">
<div class="tool_sep"></div>
<se-button id="tool_group_elements" title="tools.group_elements" shortcut="G" src="group_elements.svg">
</se-button>
<se-button id="tool_make_link_multi" title="tools.make_link" src="globe_link.svg"></se-button>
<se-button id="tool_align_left" title="tools.align_left" src="align_left.svg"></se-button>
<se-button id="tool_align_center" title="tools.align_center" src="align_center.svg"></se-button>
<se-button id="tool_align_right" title="tools.align_right" src="align_right.svg"></se-button>
<se-button id="tool_align_top" title="tools.align_top" src="align_top.svg"></se-button>
<se-button id="tool_align_middle" title="tools.align_middle" src="align_middle.svg"></se-button>
<se-button id="tool_align_bottom" title="tools.align_bottom" src="align_bottom.svg"></se-button>
<se-select id="tool_align_relative" label="tools.relativeTo"
options="tools.selected_objects,tools.largest_object,tools.smallest_object,tools.page"
values="selected::largest::smallest::page"></se-list-item>
</se-select>
</div> <!-- multiselected_panel -->
<div class="rect_panel">
<se-spin-input id="rect_width" data-attr="width" size="4" label="properties.w_label" title="properties.rect_width"></se-spin-input>
<se-spin-input id="rect_height" data-attr="height" size="4" label="properties.h_label" title="properties.rect_height"></se-spin-input>
<se-spin-input id="rect_rx" min=0 max=1000 step=1 size="3" title="properties.corner_radius" data-attr="Corner Radius" src="c_radius.svg"></se-spin-input>
</div> <!-- rect_panel -->
<div class="image_panel">
<se-spin-input id="image_width" data-attr="width" size="4" type="text" label="properties.w_label" title="properties.image_width"></se-spin-input>
<se-spin-input id="image_height" data-attr="height" size="4" type="text" label="properties.h_label" title="properties.image_height"></se-spin-input>
</div>
<div class="image_panel">
<se-input id="image_url" data-attr="image_url" size="15" label="properties.image_url"></se-input>
</div>
<div class="circle_panel">
<se-spin-input id="circle_cx" data-attr="cx" size="4" label="properties.cx_label"></se-spin-input>
<se-spin-input id="circle_cy" data-attr="cy" size="4" label="properties.cy_label"></se-spin-input>
</div>
<div class="circle_panel">
<se-spin-input id="circle_r" data-attr="r" size="4" label="properties.r_label"></se-spin-input>
</div>
<div class="ellipse_panel">
<se-spin-input id="ellipse_cx" data-attr="cx" size="4" title="properties.ellipse_cx" label="properties.cx_label"></se-spin-input>
<se-spin-input id="ellipse_cy" data-attr="cy" size="4" title="properties.ellipse_cy" label="properties.cy_label"></se-spin-input>
</div>
<div class="ellipse_panel">
<se-spin-input id="ellipse_rx" data-attr="rx" size="4" title="properties.ellipse_rx" label="properties.rx_label"></se-spin-input>
<se-spin-input id="ellipse_ry" data-attr="ry" size="4" title="properties.ellipse_ry" label="properties.ry_label"></se-spin-input>
</div>
<div class="line_panel">
<se-spin-input id="line_x1" data-attr="x1" size="4" title="properties.line_x1" label="properties.x1_label"></se-spin-input>
<se-spin-input id="line_y1" data-attr="y1" size="4" title="properties.line_y1" label="properties.y1_label"></se-spin-input>
<se-spin-input id="line_x2" data-attr="x2" size="4" title="properties.line_x2" label="properties.x2_label"></se-spin-input>
<se-spin-input id="line_y2" data-attr="y2" size="4" title="properties.line_y2" label="properties.y2_label"></se-spin-input>
</div>
<div class="text_panel">
<se-button id="tool_bold" title="properties.bold" src="bold.svg" shortcut="B"></se-button>
<se-button id="tool_italic" title="properties.italic" src="italic.svg" shortcut="I"></se-button>
<se-select id="tool_font_family" label="properties.font_family_label" options="properties.serif,properties.sans_serif,properties.cursive,properties.fantasy,properties.monospace,properties.courier,properties.helvetica,properties.times" values="Serif::Sans-serif::Cursive::Fantasy::Monospace::Courier::Helvetica::Times"></se-select>
<se-spin-input size="2" id="font_size" min=1 max=1000 step=1 title="properties.font_size" src="fontsize.svg"></se-spin-input>
</div>
<div class="text_panel">
<se-button id="tool_text_anchor_start" title="properties.text_anchor_start" src="anchor_start.svg"></se-button>
<se-button id="tool_text_anchor_middle" title="properties.text_anchor_middle" src="anchor_middle.svg"></se-button>
<se-button id="tool_text_anchor_end" title="properties.text_anchor_end" src="anchor_end.svg"></se-button>
</div>
<!-- Not visible, but still used -->
<input id="text" type="text" size="35" />
<div class="container_panel">
<div class="tool_sep"></div>
<se-input id="g_title" data-attr="title" size="8" label="properties.label"></se-input>
</div> <!-- container_panel -->
<div class="use_panel">
<se-button id="tool_unlink_use" title="tools.tool_unlink_use" src="unlink_use.svg"></se-button>
</div> <!-- use_panel -->
<div class="g_panel">
<se-button id="tool_ungroup" title="tools.ungroup" src="ungroup.svg"></se-button>
</div> <!-- g_panel -->
<!-- For anchor elements -->
<div class="a_panel">
<label id="tool_link_url">
<span id="linkLabel" class="icon_label"></span>
<input id="link_url" type="text" size="35" />
</label>
</div> <!-- a_panel -->
<div class="path_node_panel">
<div class="tool_sep"></div>
<se-button id="tool_node_link" title="tools.node_link" src="tool_node_link.svg" pressed></se-button>
<div class="tool_sep"></div>
<se-spin-input id="path_node_x" data-attr="x" size="4" title="properties.node_x" label="properties.x_label"></se-spin-input>
<se-spin-input id="path_node_y" data-attr="y" size="4" title="properties.node_y" label="properties.y_label"></se-spin-input>
<se-select id="seg_type" title="properties.seg_type" label="" options="properties.straight_segments,properties.curve_segments" values="4::6"></se-select>
<se-button id="tool_node_clone" title="tools.node_clone" src="tool_node_clone.svg"></se-button>
<se-button id="tool_node_delete" title="tools.node_delete" src="tool_node_delete.svg"></se-button>
<se-button id="tool_openclose_path" title="tools.openclose_path" src="tool_openclose_path.svg"></se-button>
<se-button id="tool_add_subpath" title="tools.add_subpath" src="tool_add_subpath.svg"></se-button>
</div> <!-- path_node_panel -->
<div id="cur_context_panel"></div>
</div>
`;
this.editor.$svgEditor.append(template.content.cloneNode(true));
// svg editor source dialoag added to DOM
const newSeEditorDialog = document.createElement(
"se-svg-source-editor-dialog"
);
newSeEditorDialog.setAttribute("id", "se-svg-editor-dialog");
this.editor.$container.append(newSeEditorDialog);
newSeEditorDialog.init(i18next);
$id("tool_link_url").setAttribute("title", i18next.t('tools.set_link_url'));
// register action to top panel buttons
$id("tool_source").addEventListener("click", this.showSourceEditor.bind(this));
$id("tool_wireframe").addEventListener("click", this.clickWireframe.bind(this));
$id("tool_undo").addEventListener("click", this.clickUndo.bind(this));
$id("tool_redo").addEventListener("click", this.clickRedo.bind(this));
$id("tool_clone").addEventListener("click", this.clickClone.bind(this));
$id("tool_clone_multi").addEventListener("click", this.clickClone.bind(this));
$id("tool_delete").addEventListener("click", this.deleteSelected.bind(this));
$id("tool_delete_multi").addEventListener("click", this.deleteSelected.bind(this));
$id("tool_move_top").addEventListener("click", this.moveToTopSelected.bind(this));
$id("tool_move_bottom").addEventListener("click", this.moveToBottomSelected.bind(this));
$id("tool_topath").addEventListener("click", this.convertToPath.bind(this));
$id("tool_make_link").addEventListener("click", this.makeHyperlink.bind(this));
$id("tool_make_link_multi").addEventListener("click", this.makeHyperlink.bind(this));
$id("tool_reorient").addEventListener("click", this.reorientPath.bind(this));
$id("tool_group_elements").addEventListener("click", this.clickGroup.bind(this));
$id("tool_position").addEventListener("change", (evt) => this.clickAlignEle.bind(this)(evt));
$id("tool_align_left").addEventListener("click", () => this.clickAlign.bind(this)("left"));
$id("tool_align_right").addEventListener("click", () => this.clickAlign.bind(this)("right"));
$id("tool_align_center").addEventListener("click", () => this.clickAlign.bind(this)("center"));
$id("tool_align_top").addEventListener("click", () => this.clickAlign.bind(this)("top"));
$id("tool_align_bottom").addEventListener("click", () => this.clickAlign.bind(this)("bottom"));
$id("tool_align_middle").addEventListener("click", () => this.clickAlign.bind(this)("middle"));
$id("tool_node_clone").addEventListener("click", this.clonePathNode.bind(this));
$id("tool_node_delete").addEventListener("click", this.deletePathNode.bind(this));
$id("tool_openclose_path").addEventListener("click", this.opencloseSubPath.bind(this));
$id("tool_add_subpath").addEventListener("click", this.addSubPath.bind(this));
$id("tool_node_link").addEventListener("click", this.linkControlPoints.bind(this));
$id("angle").addEventListener("change", this.changeRotationAngle.bind(this));
$id("blur").addEventListener("change", this.changeBlur.bind(this));
$id("rect_rx").addEventListener("change", this.changeRectRadius.bind(this));
$id("font_size").addEventListener("change", this.changeFontSize.bind(this));
$id("tool_ungroup").addEventListener("click", this.clickGroup.bind(this));
$id("tool_bold").addEventListener("click", this.clickBold.bind(this));
$id("tool_italic").addEventListener("click", this.clickItalic.bind(this));
$id("tool_text_anchor_start").addEventListener("click", () => this.clickTextAnchor.bind(this)("start"));
$id("tool_text_anchor_middle").addEventListener("click", () => this.clickTextAnchor.bind(this)("middle"));
$id("tool_text_anchor_end").addEventListener("click", () => this.clickTextAnchor.bind(this)("end"));
$id("tool_unlink_use").addEventListener("click", this.clickGroup.bind(this));
$id('image_url').addEventListener('change', (evt) => { this.setImageURL(evt.currentTarget.value);});
// all top panel attributes
[
"elem_id",
"elem_class",
"circle_cx",
"circle_cy",
"circle_r",
"ellipse_cx",
"ellipse_cy",
"ellipse_rx",
"ellipse_ry",
"selected_x",
"selected_y",
"rect_width",
"rect_height",
"line_x1",
"line_x2",
"line_y2",
"image_width",
"image_height",
"path_node_x",
"path_node_y"
].forEach((attrId) =>
$id(attrId).addEventListener("change", this.attrChanger.bind(this))
);
}
}
export default TopPanel;