refactor(panels)

This commit is contained in:
JFH
2020-12-27 00:56:12 +01:00
parent c0ca1dd621
commit d2f48b95d5
5 changed files with 1301 additions and 1307 deletions

View File

@@ -0,0 +1,181 @@
/* globals $ */
import SvgCanvas from '../../svgcanvas/svgcanvas.js';
const {$id} = SvgCanvas;
/*
* register actions for left panel
*/
/**
*
*/
class BottomPanelHandlers {
/**
* @param {PlainObject} editor svgedit handler
*/
constructor (editor) {
this.editor = editor;
this.svgCanvas = editor.canvas;
}
/**
* @type {module}
*/
changeStrokeWidth (e) {
let val = e.target.value;
if (val === 0 && this.editor.selectedElement && ['line', 'polyline'].includes(this.editor.selectedElement.nodeName)) {
val = 1;
}
this.svgCanvas.setStrokeWidth(val);
}
/**
* @type {module}
*/
changeZoom (value) {
switch (value) {
case 'canvas':
case 'selection':
case 'layer':
case 'content':
this.editor.zoomChanged(window, value);
break;
default:
{
const zoomlevel = Number(value) / 100;
if (zoomlevel < 0.001) {
value = 0.1;
return;
}
const zoom = this.svgCanvas.getZoom();
const wArea = this.editor.workarea;
this.editor.zoomChanged(window, {
width: 0,
height: 0,
// center pt of scroll position
x: (wArea[0].scrollLeft + wArea.width() / 2) / zoom,
y: (wArea[0].scrollTop + wArea.height() / 2) / zoom,
zoom: zoomlevel
}, true);
}
}
}
/**
* @fires module:svgcanvas.SvgCanvas#event:ext_toolButtonStateUpdate
* @returns {void}
*/
updateToolButtonState () {
const bNoFill = (this.svgCanvas.getColor('fill') === 'none');
const bNoStroke = (this.svgCanvas.getColor('stroke') === 'none');
const buttonsNeedingStroke = ['tool_fhpath', 'tool_line'];
const buttonsNeedingFillAndStroke = [
'tools_rect', 'tools_ellipse',
'tool_text', 'tool_path'
];
if (bNoStroke) {
buttonsNeedingStroke.forEach((btn) => {
// if btn is pressed, change to select button
if ($id(btn).pressed) {
this.editor.leftPanelHandlers.clickSelect();
}
$(btn).disabled = true;
});
} else {
buttonsNeedingStroke.forEach((btn) => {
$id(btn).disabled = false;
});
}
if (bNoStroke && bNoFill) {
buttonsNeedingFillAndStroke.forEach((btn) => {
// if btn is pressed, change to select button
if ($id(btn).pressed) {
this.editor.leftPanelHandlers.clickSelect();
}
$(btn).disabled = true;
});
} else {
buttonsNeedingFillAndStroke.forEach((btn) => {
$id(btn).disabled = false;
});
}
this.svgCanvas.runExtensions(
'toolButtonStateUpdate',
/** @type {module:svgcanvas.SvgCanvas#event:ext_toolButtonStateUpdate} */ {
nofill: bNoFill,
nostroke: bNoStroke
}
);
}
/**
* @type {module}
*/
updateColorpickers (apply) {
$id('fill_color').update(this.svgCanvas, this.selectedElement, apply);
$id('stroke_color').update(this.svgCanvas, this.selectedElement, apply);
}
/**
* @type {module}
*/
handleColorPicker (type, evt) {
const {paint} = evt.detail;
this.svgCanvas.setPaint(type, paint);
this.updateToolButtonState();
}
/**
* @type {module}
*/
handleStrokeAttr (type, evt) {
this.svgCanvas.setStrokeAttr(type, evt.currentTarget.value);
}
/**
* @type {module}
*/
handleOpacity (evt) {
// if ($(this).find('div').length) { return; }
const val = Number.parseInt(evt.currentTarget.value.split('%')[0]);
this.svgCanvas.setOpacity(val / 100);
}
/**
* @type {module}
*/
handlePalette (e) {
e.preventDefault();
// shift key or right click for stroke
const {picker, color} = e.detail;
// Webkit-based browsers returned 'initial' here for no stroke
const paint = color === 'none' ? new $.jGraduate.Paint() : new $.jGraduate.Paint({alpha: 100, solidColor: color.substr(1)});
if (picker === 'fill') {
$id('fill_color').setPaint(paint);
} else {
$id('stroke_color').setPaint(paint);
}
this.svgCanvas.setColor(picker, color);
if (color !== 'none' && this.svgCanvas.getPaintOpacity(picker) !== 1) {
this.svgCanvas.setPaintOpacity(picker, 1.0);
}
this.updateToolButtonState();
}
/**
* @type {module}
*/
init () {
// register actions for bottom panel
$id('zoom').addEventListener('change', (e) => this.changeZoom(e.detail.value).bind(this));
$id('stroke_color').addEventListener('change', (evt) => this.handleColorPicker.bind(this)('stroke', evt));
$id('fill_color').addEventListener('change', (evt) => this.handleColorPicker.bind(this)('fill', evt));
$id('stroke_width').addEventListener('change', this.changeStrokeWidth.bind(this));
$id('stroke_style').addEventListener('change', (evt) => this.handleStrokeAttr.bind(this)('stroke-dasharray', evt));
$id('stroke_linejoin').addEventListener('change', (evt) => this.handleStrokeAttr.bind(this)('stroke-linejoin', evt));
$id('stroke_linecap').addEventListener('change', (evt) => this.handleStrokeAttr.bind(this)('stroke-linecap', evt));
$id('opacity_dropdown').addEventListener('change', this.handleOpacity.bind(this));
$id('palette').addEventListener('change', this.handlePalette.bind(this));
}
}
export default BottomPanelHandlers;

View File

@@ -1,29 +1,147 @@
/* eslint-disable no-alert */
/* globals $ */
import SvgCanvas from '../../svgcanvas/svgcanvas.js';
const SIDEPANEL_MAXWIDTH = 300;
const SIDEPANEL_OPENWIDTH = 150;
const {$id} = SvgCanvas;
/**
*
*/
class LayersPanel {
/**
* @param {PlainObject} svgCanvas svgCanvas
* @param {PlainObject} uiStrings uiStrings
* @param {GenericCallBack} updateContextPanel updateContextPanel
* @param {PlainObject} editor
*/
constructor (svgCanvas, uiStrings, updateContextPanel) {
this.svgCanvas = svgCanvas;
this.uiStrings = uiStrings;
this.updateContextPanel = updateContextPanel;
constructor (editor) {
this.svgCanvas = editor.canvas;
this.uiStrings = editor.uiStrings;
this.updateContextPanel = editor.topPanelHandlers.updateContextPanel;
this.sidedrag = -1;
this.sidedragging = false;
this.allowmove = false;
this.editor = editor;
}
/**
* @param {Float} delta
* @fires module:svgcanvas.SvgCanvas#event:ext_workareaResized
* @returns {void}
*/
changeSidePanelWidth (delta) {
const rulerX = $('#ruler_x');
$('#sidepanels').width('+=' + delta);
$('#layerpanel').width('+=' + delta);
rulerX.css('right', Number.parseInt(rulerX.css('right')) + delta);
this.editor.workarea.css('right', Number.parseInt(this.editor.workarea.css('right')) + delta);
this.svgCanvas.runExtensions('workareaResized');
}
/**
* @param {Event} evt
* @returns {void}
*/
resizeSidePanel (evt) {
if (!this.allowmove) { return; }
if (this.sidedrag === -1) { return; }
this.sidedragging = true;
let deltaX = this.sidedrag - evt.pageX;
const sideWidth = $('#sidepanels').width();
if (sideWidth + deltaX > SIDEPANEL_MAXWIDTH) {
deltaX = SIDEPANEL_MAXWIDTH - sideWidth;
// sideWidth = SIDEPANEL_MAXWIDTH;
} else if (sideWidth + deltaX < 2) {
deltaX = 2 - sideWidth;
// sideWidth = 2;
}
if (deltaX === 0) { return; }
this.sidedrag -= deltaX;
this.changeSidePanelWidth(deltaX);
}
/**
* If width is non-zero, then fully close it; otherwise fully open it.
* @param {boolean} close Forces the side panel closed
* @returns {void}
*/
toggleSidePanel (close) {
const dpr = window.devicePixelRatio || 1;
const w = $('#sidepanels').width();
const isOpened = (dpr < 1 ? w : w / dpr) > 2;
const zoomAdjustedSidepanelWidth = (dpr < 1 ? 1 : dpr) * SIDEPANEL_OPENWIDTH;
const deltaX = (isOpened || close ? 0 : zoomAdjustedSidepanelWidth) - w;
this.changeSidePanelWidth(deltaX);
}
/**
* @param {PlainObject} e event
* @returns {void}
*/
lmenuFunc (e) {
const action = e?.detail?.trigger;
switch (action) {
case 'dupe':
this.cloneLayer();
break;
case 'delete':
this.deleteLayer();
break;
case 'merge_down':
this.mergeLayer();
break;
case 'merge_all':
this.svgCanvas.mergeAllLayers();
this.updateContextPanel();
this.populateLayers();
break;
}
}
/**
* @returns {void}
*/
addEvents () {
init () {
// layer menu added to DOM
const menuMore = document.createElement('se-cmenu-layers');
menuMore.setAttribute('id', 'se-cmenu-layers-more');
menuMore.value = 'layer_moreopts';
menuMore.setAttribute('leftclick', true);
document.body.append(menuMore);
const menuLayerBox = document.createElement('se-cmenu-layers');
menuLayerBox.setAttribute('id', 'se-cmenu-layers-list');
menuLayerBox.value = 'layerlist';
menuLayerBox.setAttribute('leftclick', false);
document.body.append(menuLayerBox);
document.getElementById('layer_new').addEventListener('click', this.newLayer.bind(this));
document.getElementById('layer_delete').addEventListener('click', this.deleteLayer.bind(this));
document.getElementById('layer_up').addEventListener('click', () => this.moveLayer.bind(this)(-1));
document.getElementById('layer_down').addEventListener('click', () => this.moveLayer.bind(this)(1));
document.getElementById('layer_rename').addEventListener('click', this.layerRename.bind(this));
$id('se-cmenu-layers-more').addEventListener('change', this.lmenuFunc.bind(this));
$id('se-cmenu-layers-list').addEventListener('change', (e) => {
this.lmenuFunc.bind(this)(e?.detail?.trigger, e?.detail?.source);
});
$id('sidepanel_handle').addEventListener('click', this.toggleSidePanel.bind(this));
if (this.editor.curConfig.showlayers) {
this.toggleSidePanel();
}
$id('sidepanel_handle').addEventListener('mousedown', (evt) => {
this.sidedrag = evt.pageX;
window.addEventListener('mousemove', this.resizeSidePanel.bind(this));
this.allowmove = false;
// Silly hack for Chrome, which always runs mousemove right after mousedown
setTimeout(() => {
this.allowmove = true;
}, 20);
});
$id('sidepanel_handle').addEventListener('mouseup', (evt) => {
if (!this.sidedragging) { this.toggleSidePanel(); }
this.sidedrag = -1;
this.sidedragging = false;
});
window.addEventListener('mouseup', (evt) => {
this.sidedrag = -1;
this.sidedragging = false;
$id('svg_editor').removeEventListener('mousemove', this.resizeSidePanel.bind(this));
});
}
/**
* @returns {void}

View File

@@ -0,0 +1,216 @@
import SvgCanvas from '../../svgcanvas/svgcanvas.js';
const {$id, $qa} = SvgCanvas;
/*
* register actions for left panel
*/
/**
* @type {module}
*/
class LeftPanelHandlers {
/**
* @param {PlainObject} editor svgedit handler
*/
constructor (editor) {
this.editor = editor;
this.svgCanvas = editor.canvas;
}
/**
* This is a common function used when a tool has been clicked (chosen).
* It does several common things:
* - Removes the pressed button from whatever tool currently has it.
* - Adds the the pressed button to the button passed in.
* @function this.updateLeftPanel
* @param {string|Element} button The DOM element or string selector representing the toolbar button
* @returns {boolean} Whether the button was disabled or not
*/
// eslint-disable-next-line class-methods-use-this
updateLeftPanel (button) {
if (button.disabled) return false;
// remove the pressed state on other(s) button(s)
$qa('#tools_left *[pressed]').forEach((b) => { b.pressed = false; });
// pressed state for the clicked button
$id(button).pressed = true;
return true;
}
/**
* Unless the select toolbar button is disabled, sets the button
* and sets the select mode and cursor styles.
* @function module:SVGEditor.clickSelect
* @returns {void}
*/
clickSelect () {
if (this.updateLeftPanel('tool_select')) {
this.editor.workarea.css('cursor', 'auto');
this.svgCanvas.setMode('select');
}
}
/**
*
* @returns {void}
*/
clickFHPath () {
if (this.updateLeftPanel('tool_fhpath')) {
this.svgCanvas.setMode('fhpath');
}
}
/**
*
* @returns {void}
*/
clickLine () {
if (this.updateLeftPanel('tool_line')) {
this.svgCanvas.setMode('line');
}
}
/**
*
* @returns {void}
*/
clickSquare () {
if (this.updateLeftPanel('tool_square')) {
this.svgCanvas.setMode('square');
}
}
/**
*
* @returns {void}
*/
clickRect () {
if (this.updateLeftPanel('tool_rect')) {
this.svgCanvas.setMode('rect');
}
}
/**
*
* @returns {void}
*/
clickFHRect () {
if (this.updateLeftPanel('tool_fhrect')) {
this.svgCanvas.setMode('fhrect');
}
}
/**
*
* @returns {void}
*/
clickCircle () {
if (this.updateLeftPanel('tool_circle')) {
this.svgCanvas.setMode('circle');
}
}
/**
*
* @returns {void}
*/
clickEllipse () {
if (this.updateLeftPanel('tool_ellipse')) {
this.svgCanvas.setMode('ellipse');
}
}
/**
*
* @returns {void}
*/
clickFHEllipse () {
if (this.updateLeftPanel('tool_fhellipse')) {
this.svgCanvas.setMode('fhellipse');
}
}
/**
*
* @returns {void}
*/
clickImage () {
if (this.updateLeftPanel('tool_image')) {
this.svgCanvas.setMode('image');
}
}
/**
*
* @returns {void}
*/
clickZoom () {
if (this.updateLeftPanel('tool_zoom')) {
this.svgCanvas.setMode('zoom');
this.editor.workarea.css('cursor', this.editor.zoomInIcon);
}
}
/**
*
* @returns {void}
*/
dblclickZoom () {
if (this.updateLeftPanel('tool_zoom')) {
this.editor.zoomImage();
this.clickSelect();
}
}
/**
*
* @returns {void}
*/
clickText () {
if (this.updateLeftPanel('tool_text')) {
this.svgCanvas.setMode('text');
}
}
/**
*
* @returns {void}
*/
clickPath () {
if (this.updateLeftPanel('tool_path')) {
this.svgCanvas.setMode('path');
}
}
/**
* @type {module}
*/
add (id, handler) {
$id(id).addEventListener('click', () => {
if (this.updateLeftPanel(id)) {
handler();
}
});
}
/**
* @type {module}
*/
init () {
// register actions for left panel
$id('tool_select').addEventListener('click', this.clickSelect.bind(this));
$id('tool_fhpath').addEventListener('click', this.clickFHPath.bind(this));
$id('tool_text').addEventListener('click', this.clickText.bind(this));
$id('tool_image').addEventListener('click', this.clickImage.bind(this));
$id('tool_zoom').addEventListener('click', this.clickZoom.bind(this));
$id('tool_zoom').addEventListener('dblclick', this.dblclickZoom.bind(this));
$id('tool_path').addEventListener('click', this.clickPath.bind(this));
$id('tool_line').addEventListener('click', this.clickLine.bind(this));
// flyout
$id('tool_rect').addEventListener('click', this.clickRect.bind(this));
$id('tool_square').addEventListener('click', this.clickSquare.bind(this));
$id('tool_fhrect').addEventListener('click', this.clickFHRect.bind(this));
$id('tool_ellipse').addEventListener('click', this.clickEllipse.bind(this));
$id('tool_circle').addEventListener('click', this.clickCircle.bind(this));
$id('tool_fhellipse').addEventListener('click', this.clickFHEllipse.bind(this));
}
}
export default LeftPanelHandlers;

View File

@@ -0,0 +1,632 @@
/* globals $ */
import SvgCanvas from '../../svgcanvas/svgcanvas.js';
import {isValidUnit, getTypeMap, convertUnit} from '../../common/units.js';
const {$id, isNullish} = SvgCanvas;
/*
* register actions for left panel
*/
/**
*
*/
class TopPanelHandlers {
/**
* @param {PlainObject} editor svgedit handler
*/
constructor (editor) {
this.editor = editor;
this.svgCanvas = editor.canvas;
this.uiStrings = editor.uiStrings;
}
/**
* @type {module}
*/
get selectedElement () {
return this.editor.selectedElement;
}
/**
* @type {module}
*/
get multiselected () {
return this.editor.multiselected;
}
/**
* @type {module}
*/
get path () {
return this.svgCanvas.pathActions;
}
/**
* @param {PlainObject} [opts={}]
* @param {boolean} [opts.cancelDeletes=false]
* @returns {void} Resolves to `undefined`
*/
promptImgURL ({cancelDeletes = false} = {}) {
let curhref = this.svgCanvas.getHref(this.selectedElement);
curhref = curhref.startsWith('data:') ? '' : curhref;
// eslint-disable-next-line no-alert
const url = prompt(this.editor.uiStrings.notification.enterNewImgURL, curhref);
if (url) {
this.editor.setImageURL(url);
} else if (cancelDeletes) {
this.svgCanvas.deleteSelectedElements();
}
}
/**
* Updates the context panel tools based on the selected element.
* @returns {void}
*/
updateContextPanel () {
const setInputWidth = (elem) => {
const w = Math.min(Math.max(12 + elem.value.length * 6, 50), 300);
$(elem).width(w);
};
let elem = this.selectedElement;
// If element has just been deleted, consider it null
if (!isNullish(elem) && !elem.parentNode) { elem = null; }
const currentLayerName = this.svgCanvas.getCurrentDrawing().getCurrentLayerName();
const currentMode = this.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');
$('#selected_panel, #multiselected_panel, #g_panel, #rect_panel, #circle_panel,' +
'#ellipse_panel, #line_panel, #text_panel, #image_panel, #container_panel,' +
' #use_panel, #a_panel').hide();
if (!isNullish(elem)) {
const elname = elem.nodeName;
// If this is a link with no transform and one child, pretend
// its child is selected
// if (elname === 'a') { // && !$(elem).attr('transform')) {
// elem = elem.firstChild;
// }
const angle = this.svgCanvas.getRotationAngle(elem);
$('#angle').val(angle);
const blurval = this.svgCanvas.getBlur(elem) * 10;
$id('blur').value = blurval;
if (this.svgCanvas.addedNew &&
elname === 'image' &&
this.svgCanvas.getMode() === 'image' &&
!this.svgCanvas.getHref(elem).startsWith('data:')) {
/* await */ this.promptImgURL({cancelDeletes: true});
}
if (!isNode && currentMode !== 'pathedit') {
$('#selected_panel').show();
// Elements in this array already have coord fields
if (['line', 'circle', 'ellipse'].includes(elname)) {
$('#xy_panel').hide();
} else {
let x, y;
// Get BBox vals for g, polyline and path
if (['g', 'polyline', 'path'].includes(elname)) {
const bb = this.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);
}
$('#selected_x').val(x || 0);
$('#selected_y').val(y || 0);
$('#xy_panel').show();
}
// Elements in this array cannot be converted to a path
$id('tool_topath').style.display = ['image', 'text', 'path', 'g', 'use'].includes(elname) ? 'none' : 'block';
$id('tool_reorient').style.display = (elname === 'path') ? 'block' : 'none';
$id('tool_reorient').disabled = (angle === 0);
} else {
const point = this.path.getNodePoint();
$('#tool_add_subpath').pressed = false;
$('#tool_node_delete').toggleClass('disabled', !this.path.canDeleteNodes);
// Show open/close button based on selected point
// setIcon('#tool_openclose_path', path.closed_subpath ? 'open_path' : 'close_path');
if (point) {
const segType = $('#seg_type');
if (unit) {
point.x = convertUnit(point.x);
point.y = convertUnit(point.y);
}
$('#path_node_x').val(point.x);
$('#path_node_y').val(point.y);
if (point.type) {
segType.val(point.type).removeAttr('disabled');
} else {
segType.val(4).attr('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;
// if ($(elem).data('gsvg')) {
// $('#g_panel').show();
// }
let linkHref = null;
if (tagName === 'a') {
linkHref = this.svgCanvas.getHref(elem);
$('#g_panel').show();
}
if (elem.parentNode.tagName === 'a' && !$(elem).siblings().length) {
$('#a_panel').show();
linkHref = this.svgCanvas.getHref(elem.parentNode);
}
// Hide/show the make_link buttons
$('#tool_make_link, #tool_make_link_multi').toggle(!linkHref);
if (linkHref) {
$('#link_url').val(linkHref);
}
if (panels[tagName]) {
const curPanel = panels[tagName];
$('#' + tagName + '_panel').show();
curPanel.forEach((item) => {
let attrVal = elem.getAttribute(item);
if (this.editor.curConfig.baseUnit !== 'px' && elem[item]) {
const bv = elem[item].baseVal.value;
attrVal = convertUnit(bv);
}
$id(`${tagName}_${item}`).value = attrVal || 0;
});
if (tagName === 'text') {
$('#text_panel').css('display', 'inline');
$('#tool_font_size').css('display', 'inline');
$id('tool_italic').pressed = this.svgCanvas.getItalic();
$id('tool_bold').pressed = this.svgCanvas.getBold();
$('#font_family').val(elem.getAttribute('font-family'));
$('#font_size').val(elem.getAttribute('font-size'));
$('#text').val(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.svgCanvas.addedNew) {
// Timeout needed for IE9
setTimeout(() => {
$('#text').focus().select();
}, 100);
}
// text
} else if (tagName === 'image' && this.svgCanvas.getMode() === 'image') {
this.svgCanvas.setImageURL(this.svgCanvas.getHref(elem));
// image
} else if (tagName === 'g' || tagName === 'use') {
$('#container_panel').show();
const title = this.svgCanvas.getTitle();
const label = $('#g_title')[0];
label.value = title;
setInputWidth(label);
$('#g_title').prop('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) {
$('#multiselected_panel').show();
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.canvas.undoMgr.getUndoStackSize() === 0);
$id('tool_redo').disabled = (this.editor.canvas.undoMgr.getRedoStackSize() === 0);
this.svgCanvas.addedNew = false;
if ((elem && !isNode) || this.multiselected) {
// update the selected elements' layer
$('#selLayerNames').removeAttr('disabled').val(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 {
$('#selLayerNames').attr('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.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.toggleClass('wireframe');
const wfRules = $('#wireframe_rules');
if (!wfRules.length) {
/* wfRules = */ $('<style id="wireframe_rules"></style>').appendTo('head');
} else {
wfRules.empty();
}
this.editor.updateWireFrame();
}
/**
*
* @returns {void}
*/
clickUndo () {
const {undoMgr} = this.editor;
if (undoMgr.getUndoStackSize() > 0) {
undoMgr.undo();
this.editor.layersPanel.populateLayers();
}
}
/**
*
* @returns {void}
*/
clickRedo () {
const {undoMgr} = this.editor.canvas;
if (undoMgr.getRedoStackSize() > 0) {
undoMgr.redo();
this.editor.layersPanel.populateLayers();
}
}
/**
* @type {module}
*/
changeRectRadius (e) {
this.svgCanvas.setRectRadius(e.target.value);
}
/**
* @type {module}
*/
changeFontSize (e) {
this.svgCanvas.setFontSize(e.target.value);
}
/**
* @type {module}
*/
changeRotationAngle (e) {
this.svgCanvas.setRotationAngle(e.target.value);
$('#tool_reorient').toggleClass('disabled', Number.parseInt(e.target.value) === 0);
}
/**
* @param {PlainObject} e
* @returns {void}
*/
changeBlur (e) {
this.svgCanvas.setBlur(e.target.value / 10, true);
}
/**
*
* @returns {void}
*/
clickGroup () {
// group
if (this.editor.multiselected) {
this.svgCanvas.groupSelectedElements();
// ungroup
} else if (this.editor.selectedElement) {
this.svgCanvas.ungroupSelectedElement();
}
}
/**
*
* @returns {void}
*/
clickClone () {
this.svgCanvas.cloneSelectedElements(20, 20);
}
/**
* @param {string} pos indicate the alignment relative to top, bottom, middle etc..
* @returns {void}
*/
clickAlign (pos) {
this.svgCanvas.alignSelectedElements(pos, $('#align_relative_to').val());
}
/**
*
* @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.uiStrings.notification.invalidAttrValGiven);
return false;
}
if (attr !== 'id' && attr !== 'class') {
if (isNaN(val)) {
val = this.svgCanvas.convertToNum(attr, val);
} else if (this.configObj.curConfig.baseUnit !== 'px') {
// Convert unitless value to one with given unit
const unitData = getTypeMap();
if (this.selectedElement[attr] || this.svgCanvas.getMode() === 'pathedit' || attr === 'x' || attr === 'y') {
val *= unitData[this.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.selectedElement;
this.svgCanvas.clearSelection();
elem.id = val;
this.svgCanvas.addToSelection([elem], true);
} else {
this.svgCanvas.changeSelectedAttribute(attr, val);
}
return true;
}
/**
*
* @returns {void}
*/
convertToPath () {
if (!isNullish(this.selectedElement)) {
this.svgCanvas.convertToPath();
}
}
/**
*
* @returns {void}
*/
reorientPath () {
if (!isNullish(this.selectedElement)) {
this.path.reorient();
}
}
/**
*
* @returns {void} Resolves to `undefined`
*/
makeHyperlink () {
if (!isNullish(this.selectedElement) || this.multiselected) {
// eslint-disable-next-line no-alert
const url = prompt(this.uiStrings.notification.enterNewLinkURL, 'http://');
if (url) {
this.svgCanvas.makeHyperlink(url);
}
}
}
/**
*
* @returns {void}
*/
linkControlPoints () {
const linked = $id('tool_node_link').pressed;
$id('tool_node_link').pressed = !linked;
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 = $('#tool_add_subpath');
const sp = !button.hasClass('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 (!isNullish(this.selectedElement) || this.multiselected) {
this.svgCanvas.deleteSelectedElements();
}
}
/**
*
* @returns {void}
*/
moveToTopSelected () {
if (!isNullish(this.selectedElement)) {
this.svgCanvas.moveToTopSelectedElement();
}
}
/**
*
* @returns {void}
*/
moveToBottomSelected () {
if (!isNullish(this.selectedElement)) {
this.svgCanvas.moveToBottomSelectedElement();
}
}
/**
*
* @returns {false}
*/
clickBold () {
this.svgCanvas.setBold(!this.svgCanvas.getBold());
this.updateContextPanel();
return false;
}
/**
*
* @returns {false}
*/
clickItalic () {
this.svgCanvas.setItalic(!this.svgCanvas.getItalic());
this.updateContextPanel();
return false;
}
/**
*
* @param {string} value "start","end" or "middle"
* @returns {false}
*/
clickTextAnchor (value) {
this.svgCanvas.setTextAnchor(value);
this.updateContextPanel();
return false;
}
/**
* @type {module}
*/
init () {
// svg editor source dialoag added to DOM
const newSeEditorDialog = document.createElement('se-svg-source-editor-dialog');
newSeEditorDialog.setAttribute('id', 'se-svg-editor-dialog');
document.body.append(newSeEditorDialog);
// 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_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('change_image_url').addEventListener('click', this.promptImgURL.bind(this));
// 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 TopPanelHandlers;

File diff suppressed because it is too large Load Diff