1004 lines
28 KiB
JavaScript
1004 lines
28 KiB
JavaScript
/* eslint-disable max-len */
|
|
/* globals seAlert */
|
|
|
|
import SvgCanvas from '@svgedit/svgcanvas'
|
|
import topPanelHTML from './TopPanel.html'
|
|
|
|
const { $qa, $id, $click, isValidUnit, getTypeMap, convertUnit } = 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}`).forEach(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
|
|
// set title
|
|
$qa('#title_panel > p')[0].textContent = this.editor.title
|
|
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(false)
|
|
break
|
|
}
|
|
default: {
|
|
this.editor.bottomPanel.updateColorpickers(false)
|
|
|
|
$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
|
|
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'
|
|
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
|
|
!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_text_decoration_underline'
|
|
).pressed = this.editor.svgCanvas.hasTextDecoration('underline')
|
|
$id(
|
|
'tool_text_decoration_linethrough'
|
|
).pressed = this.editor.svgCanvas.hasTextDecoration('line-through')
|
|
$id(
|
|
'tool_text_decoration_overline'
|
|
).pressed = this.editor.svgCanvas.hasTextDecoration('overline')
|
|
$id('tool_font_family').value = elem.getAttribute('font-family')
|
|
$id('tool_text_anchor').setAttribute(
|
|
'value',
|
|
elem.getAttribute('text-anchor')
|
|
)
|
|
$id('font_size').value = elem.getAttribute('font-size')
|
|
$id('tool_letter_spacing').value =
|
|
elem.getAttribute('letter-spacing') ?? 0
|
|
$id('tool_word_spacing').value =
|
|
elem.getAttribute('word-spacing') ?? 0
|
|
$id('tool_text_length').value = elem.getAttribute('textLength') ?? 0
|
|
$id('tool_length_adjust').value =
|
|
elem.getAttribute('lengthAdjust') ?? 0
|
|
$id('text').value = elem.textContent
|
|
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 (elem)
|
|
} else if (this.multiselected) {
|
|
// Check if all selected elements are 'text' nodes, if yes enable text panel
|
|
const selElems = this.editor.svgCanvas.getSelectedElements()
|
|
if (selElems.every((elem) => elem.tagName === 'text')) {
|
|
this.displayTool('text_panel')
|
|
}
|
|
|
|
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)
|
|
if (Number.parseInt(e.target.value) === 0) {
|
|
$id('tool_reorient').classList.add('disabled')
|
|
} else {
|
|
$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)
|
|
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]
|
|
}
|
|
}
|
|
}
|
|
|
|
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) {
|
|
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
|
|
const linked = !!$id('tool_node_link').pressed
|
|
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
|
|
}
|
|
|
|
/**
|
|
* Handles the click on the text decoration buttons
|
|
*
|
|
* @param value The text decoration value
|
|
* @returns {boolean} false
|
|
*/
|
|
clickTextDecoration (value) {
|
|
if (this.editor.svgCanvas.hasTextDecoration(value)) {
|
|
this.editor.svgCanvas.removeTextDecoration(value)
|
|
} else {
|
|
this.editor.svgCanvas.addTextDecoration(value)
|
|
}
|
|
this.updateContextPanel()
|
|
return false
|
|
}
|
|
|
|
/**
|
|
* Sets the text anchor value
|
|
*
|
|
* @returns {false}
|
|
*/
|
|
clickTextAnchor (evt) {
|
|
this.editor.svgCanvas.setTextAnchor(evt.detail.value)
|
|
return false
|
|
}
|
|
|
|
/**
|
|
* @type {module}
|
|
*/
|
|
changeLetterSpacing (e) {
|
|
this.editor.svgCanvas.setLetterSpacing(e.target.value)
|
|
}
|
|
|
|
/**
|
|
* @type {module}
|
|
*/
|
|
changeWordSpacing (e) {
|
|
this.editor.svgCanvas.setWordSpacing(e.target.value)
|
|
}
|
|
|
|
/**
|
|
* @type {module}
|
|
*/
|
|
changeTextLength (e) {
|
|
this.editor.svgCanvas.setTextLength(e.target.value)
|
|
}
|
|
|
|
/**
|
|
* @type {module}
|
|
*/
|
|
changeLengthAdjust (evt) {
|
|
this.editor.svgCanvas.setLengthAdjust(evt.detail.value)
|
|
}
|
|
|
|
/**
|
|
* 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.getSelectedElements(),
|
|
true
|
|
)
|
|
},
|
|
error => {
|
|
console.error('error =', error)
|
|
seAlert(editor.i18next.t('tools.no_embed'))
|
|
editor.svgCanvas.deleteSelectedElements()
|
|
}
|
|
)
|
|
this.displayTool('image_url')
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
updateTitle (title) {
|
|
if (title) this.editor.title = title
|
|
const titleElement = $qa('#title_panel > p')[0]
|
|
if (titleElement) titleElement.textContent = this.editor.title
|
|
}
|
|
|
|
/**
|
|
* @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
|
|
template.innerHTML = topPanelHTML
|
|
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)
|
|
this.updateTitle()
|
|
newSeEditorDialog.init(i18next)
|
|
$id('tool_link_url').setAttribute('title', i18next.t('tools.set_link_url'))
|
|
// register action to top panel buttons
|
|
$click($id('tool_source'), this.showSourceEditor.bind(this))
|
|
$click($id('tool_wireframe'), this.clickWireframe.bind(this))
|
|
$click($id('tool_undo'), this.clickUndo.bind(this))
|
|
$click($id('tool_redo'), this.clickRedo.bind(this))
|
|
$click($id('tool_clone'), this.clickClone.bind(this))
|
|
$click($id('tool_clone_multi'), this.clickClone.bind(this))
|
|
$click($id('tool_delete'), this.deleteSelected.bind(this))
|
|
$click($id('tool_delete_multi'), this.deleteSelected.bind(this))
|
|
$click($id('tool_move_top'), this.moveToTopSelected.bind(this))
|
|
$click($id('tool_move_bottom'), this.moveToBottomSelected.bind(this))
|
|
$click($id('tool_topath'), this.convertToPath.bind(this))
|
|
$click($id('tool_make_link'), this.makeHyperlink.bind(this))
|
|
$click($id('tool_make_link_multi'), this.makeHyperlink.bind(this))
|
|
$click($id('tool_reorient'), this.reorientPath.bind(this))
|
|
$click($id('tool_group_elements'), this.clickGroup.bind(this))
|
|
$id('tool_position').addEventListener('change', (evt) => this.clickAlignEle.bind(this)(evt))
|
|
$click($id('tool_align_left'), () => this.clickAlign.bind(this)('left'))
|
|
$click($id('tool_align_right'), () => this.clickAlign.bind(this)('right'))
|
|
$click($id('tool_align_center'), () => this.clickAlign.bind(this)('center'))
|
|
$click($id('tool_align_top'), () => this.clickAlign.bind(this)('top'))
|
|
$click($id('tool_align_bottom'), () => this.clickAlign.bind(this)('bottom'))
|
|
$click($id('tool_align_middle'), () => this.clickAlign.bind(this)('middle'))
|
|
$click($id('tool_align_distrib_horiz'), () => this.clickAlign.bind(this)('distrib_horiz'))
|
|
$click($id('tool_align_distrib_verti'), () => this.clickAlign.bind(this)('distrib_verti'))
|
|
$click($id('tool_node_clone'), this.clonePathNode.bind(this))
|
|
$click($id('tool_node_delete'), this.deletePathNode.bind(this))
|
|
$click($id('tool_openclose_path'), this.opencloseSubPath.bind(this))
|
|
$click($id('tool_add_subpath'), this.addSubPath.bind(this))
|
|
$click($id('tool_node_link'), 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))
|
|
$click($id('tool_ungroup'), this.clickGroup.bind(this))
|
|
$click($id('tool_bold'), this.clickBold.bind(this))
|
|
$click($id('tool_italic'), this.clickItalic.bind(this))
|
|
$click($id('tool_text_decoration_underline'), () => this.clickTextDecoration.bind(this)('underline'))
|
|
$click($id('tool_text_decoration_linethrough'), () => this.clickTextDecoration.bind(this)('line-through'))
|
|
$click($id('tool_text_decoration_overline'), () => this.clickTextDecoration.bind(this)('overline'))
|
|
$id('tool_text_anchor').addEventListener('change', (evt) => this.clickTextAnchor.bind(this)(evt))
|
|
$id('tool_letter_spacing').addEventListener('change', this.changeLetterSpacing.bind(this))
|
|
$id('tool_word_spacing').addEventListener('change', this.changeWordSpacing.bind(this))
|
|
$id('tool_text_length').addEventListener('change', this.changeTextLength.bind(this))
|
|
$id('tool_length_adjust').addEventListener('change', (evt) => this.changeLengthAdjust.bind(this)(evt))
|
|
$click($id('tool_unlink_use'), 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_y1',
|
|
'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
|