refactor with Panel classes
parent
cb52db7324
commit
57e7fe316b
|
@ -34,9 +34,7 @@ describe('Basic Module', function () {
|
|||
workarea.append(svgcanvas);
|
||||
const toolsLeft = document.createElement('div');
|
||||
toolsLeft.id = 'tools_left';
|
||||
const toolsFlyout = document.createElement('div');
|
||||
toolsFlyout.id = 'tools_flyout';
|
||||
|
||||
|
||||
svgEditor.append(workarea, toolsLeft, toolsFlyout);
|
||||
document.body.append(svgEditor);
|
||||
|
||||
|
|
|
@ -6,10 +6,7 @@ module.exports = {
|
|||
"functions": 45,
|
||||
exclude: [
|
||||
'editor/jquery.min.js',
|
||||
'editor/jgraduate/**',
|
||||
'editor/svgicons/**',
|
||||
'editor/dragmove/**',
|
||||
'editor/spinbtn'
|
||||
'editor/jgraduate/**'
|
||||
],
|
||||
"reporter": [
|
||||
"json-summary",
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
"license": "(MIT AND Apache-2.0 AND ISC AND LGPL-3.0-or-later AND X11)",
|
||||
"dependencies": {
|
||||
"@babel/polyfill": "7.12.1",
|
||||
"@knadh/dragmove": "^0.1.2",
|
||||
"@web/dev-server-rollup": "0.3.2",
|
||||
"canvg": "3.0.7",
|
||||
"core-js": "3.9.1",
|
||||
|
@ -17,7 +16,7 @@
|
|||
"jspdf": "2.3.1",
|
||||
"pathseg": "1.2.0",
|
||||
"regenerator-runtime": "0.13.7",
|
||||
"rollup-plugin-polyfill-node": "^0.6.1",
|
||||
"rollup-plugin-polyfill-node": "^0.6.2",
|
||||
"svg2pdf.js": "2.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -49,7 +48,7 @@
|
|||
"cypress-multi-reporters": "1.4.0",
|
||||
"cypress-plugin-snapshots": "1.4.4",
|
||||
"deparam": "git+https://github.com/brettz9/deparam.git#updates",
|
||||
"eslint": "^7.21.0",
|
||||
"eslint": "^7.22.0",
|
||||
"eslint-config-standard": "16.0.2",
|
||||
"eslint-plugin-array-func": "3.1.7",
|
||||
"eslint-plugin-chai-expect": "2.2.0",
|
||||
|
@ -74,7 +73,7 @@
|
|||
"imageoptim-cli": "3.0.2",
|
||||
"jamilih": "0.54.0",
|
||||
"jsdoc": "3.6.6",
|
||||
"mocha": "8.3.1",
|
||||
"mocha": "8.3.2",
|
||||
"mocha-badge-generator": "0.9.0",
|
||||
"mochawesome": "6.2.2",
|
||||
"mochawesome-merge": "4.2.0",
|
||||
|
@ -90,7 +89,7 @@
|
|||
"remark-lint-ordered-list-marker-value": "2.0.1",
|
||||
"requirejs": "2.3.6",
|
||||
"rimraf": "3.0.2",
|
||||
"rollup": "2.41.0",
|
||||
"rollup": "2.41.2",
|
||||
"rollup-plugin-copy": "3.4.0",
|
||||
"rollup-plugin-filesize": "9.1.1",
|
||||
"rollup-plugin-node-polyfills": "0.2.1",
|
||||
|
@ -3245,11 +3244,6 @@
|
|||
"regenerator-runtime": "^0.13.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@knadh/dragmove": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@knadh/dragmove/-/dragmove-0.1.2.tgz",
|
||||
"integrity": "sha512-OxfFFHqrpenz9oVxi8AngzrF7+aoGZCvNOGOVlxu+6UlG0dW68hJJeNt7RvVlg3dNK6uaHsju+bH+/NXaRUMTQ=="
|
||||
},
|
||||
"node_modules/@mdn/browser-compat-data": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-2.0.7.tgz",
|
||||
|
@ -9861,9 +9855,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/eslint": {
|
||||
"version": "7.21.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.21.0.tgz",
|
||||
"integrity": "sha512-W2aJbXpMNofUp0ztQaF40fveSsJBjlSCSWpy//gzfTvwC+USs/nceBrKmlJOiM8r1bLwP2EuYkCqArn/6QTIgg==",
|
||||
"version": "7.22.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.22.0.tgz",
|
||||
"integrity": "sha512-3VawOtjSJUQiiqac8MQc+w457iGLfuNGLFn8JmF051tTKbh5/x/0vlcEj8OgDCaw7Ysa2Jn8paGshV7x2abKXg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "7.12.11",
|
||||
|
@ -9883,7 +9877,7 @@
|
|||
"file-entry-cache": "^6.0.1",
|
||||
"functional-red-black-tree": "^1.0.1",
|
||||
"glob-parent": "^5.0.0",
|
||||
"globals": "^12.1.0",
|
||||
"globals": "^13.6.0",
|
||||
"ignore": "^4.0.6",
|
||||
"import-fresh": "^3.0.0",
|
||||
"imurmurhash": "^0.1.4",
|
||||
|
@ -9891,7 +9885,7 @@
|
|||
"js-yaml": "^3.13.1",
|
||||
"json-stable-stringify-without-jsonify": "^1.0.1",
|
||||
"levn": "^0.4.1",
|
||||
"lodash": "^4.17.20",
|
||||
"lodash": "^4.17.21",
|
||||
"minimatch": "^3.0.4",
|
||||
"natural-compare": "^1.4.0",
|
||||
"optionator": "^0.9.1",
|
||||
|
@ -9909,6 +9903,9 @@
|
|||
},
|
||||
"engines": {
|
||||
"node": "^10.12.0 || >=12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-config-standard": {
|
||||
|
@ -10978,15 +10975,18 @@
|
|||
}
|
||||
},
|
||||
"node_modules/eslint/node_modules/globals": {
|
||||
"version": "12.4.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
|
||||
"integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
|
||||
"version": "13.6.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-13.6.0.tgz",
|
||||
"integrity": "sha512-YFKCX0SiPg7l5oKYCJ2zZGxcXprVXHcSnVuvzrT3oSENQonVLqM5pf9fN5dLGZGyCjhw8TN8Btwe/jKnZ0pjvQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"type-fest": "^0.8.1"
|
||||
"type-fest": "^0.20.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint/node_modules/has-flag": {
|
||||
|
@ -11149,6 +11149,18 @@
|
|||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint/node_modules/type-fest": {
|
||||
"version": "0.20.2",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
|
||||
"integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint/node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
|
@ -16045,9 +16057,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/mocha": {
|
||||
"version": "8.3.1",
|
||||
"resolved": "https://registry.npmjs.org/mocha/-/mocha-8.3.1.tgz",
|
||||
"integrity": "sha512-5SBMxANWqOv5bw3Hx+HVgaWlcWcFEQDUdaUAr1AUU+qwtx6cowhn7gEDT/DwQP7uYxnvShdUOVLbTYAHOEGfDQ==",
|
||||
"version": "8.3.2",
|
||||
"resolved": "https://registry.npmjs.org/mocha/-/mocha-8.3.2.tgz",
|
||||
"integrity": "sha512-UdmISwr/5w+uXLPKspgoV7/RXZwKRTiTjJ2/AC5ZiEztIoOYdfKb19+9jNmEInzx5pBsCyJQzarAxqIGBNYJhg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@ungap/promise-all-settled": "1.1.2",
|
||||
|
@ -19845,9 +19857,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "2.41.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.41.0.tgz",
|
||||
"integrity": "sha512-Gk76XHTggulWPH95q8V62bw6uqDH6UGvbD6LOa3QUyhuMF3eOuaeDHR7SLm1T9faitkpNrqzUAVYx47klcMnlA==",
|
||||
"version": "2.41.2",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.41.2.tgz",
|
||||
"integrity": "sha512-6u8fJJXJx6fmvKrAC9DHYZgONvSkz8S9b/VFBjoQ6dkKdHyPpPbpqiNl2Bao9XBzDHpq672X6sGZ9G1ZBqAHMg==",
|
||||
"bin": {
|
||||
"rollup": "dist/bin/rollup"
|
||||
},
|
||||
|
@ -20122,9 +20134,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/rollup-plugin-polyfill-node": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup-plugin-polyfill-node/-/rollup-plugin-polyfill-node-0.6.1.tgz",
|
||||
"integrity": "sha512-r+A3VUWVMm5tiWoQPpe9BOPycN+G+XgXQGmOyDn6REPaZNvNz16rOQ/3X9U6xE7kQAlXQCnec9L5i0fFytNYCQ==",
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/rollup-plugin-polyfill-node/-/rollup-plugin-polyfill-node-0.6.2.tgz",
|
||||
"integrity": "sha512-gMCVuR0zsKq0jdBn8pSXN1Ejsc458k2QsFFvQdbHoM0Pot5hEnck+pBP/FDwFS6uAi77pD3rDTytsaUStsOMlA==",
|
||||
"dependencies": {
|
||||
"@rollup/plugin-inject": "^4.0.0"
|
||||
}
|
||||
|
@ -26632,11 +26644,6 @@
|
|||
"regenerator-runtime": "^0.13.3"
|
||||
}
|
||||
},
|
||||
"@knadh/dragmove": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@knadh/dragmove/-/dragmove-0.1.2.tgz",
|
||||
"integrity": "sha512-OxfFFHqrpenz9oVxi8AngzrF7+aoGZCvNOGOVlxu+6UlG0dW68hJJeNt7RvVlg3dNK6uaHsju+bH+/NXaRUMTQ=="
|
||||
},
|
||||
"@mdn/browser-compat-data": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-2.0.7.tgz",
|
||||
|
@ -32351,9 +32358,9 @@
|
|||
}
|
||||
},
|
||||
"eslint": {
|
||||
"version": "7.21.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.21.0.tgz",
|
||||
"integrity": "sha512-W2aJbXpMNofUp0ztQaF40fveSsJBjlSCSWpy//gzfTvwC+USs/nceBrKmlJOiM8r1bLwP2EuYkCqArn/6QTIgg==",
|
||||
"version": "7.22.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.22.0.tgz",
|
||||
"integrity": "sha512-3VawOtjSJUQiiqac8MQc+w457iGLfuNGLFn8JmF051tTKbh5/x/0vlcEj8OgDCaw7Ysa2Jn8paGshV7x2abKXg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "7.12.11",
|
||||
|
@ -32373,7 +32380,7 @@
|
|||
"file-entry-cache": "^6.0.1",
|
||||
"functional-red-black-tree": "^1.0.1",
|
||||
"glob-parent": "^5.0.0",
|
||||
"globals": "^12.1.0",
|
||||
"globals": "^13.6.0",
|
||||
"ignore": "^4.0.6",
|
||||
"import-fresh": "^3.0.0",
|
||||
"imurmurhash": "^0.1.4",
|
||||
|
@ -32381,7 +32388,7 @@
|
|||
"js-yaml": "^3.13.1",
|
||||
"json-stable-stringify-without-jsonify": "^1.0.1",
|
||||
"levn": "^0.4.1",
|
||||
"lodash": "^4.17.20",
|
||||
"lodash": "^4.17.21",
|
||||
"minimatch": "^3.0.4",
|
||||
"natural-compare": "^1.4.0",
|
||||
"optionator": "^0.9.1",
|
||||
|
@ -32549,12 +32556,12 @@
|
|||
}
|
||||
},
|
||||
"globals": {
|
||||
"version": "12.4.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
|
||||
"integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
|
||||
"version": "13.6.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-13.6.0.tgz",
|
||||
"integrity": "sha512-YFKCX0SiPg7l5oKYCJ2zZGxcXprVXHcSnVuvzrT3oSENQonVLqM5pf9fN5dLGZGyCjhw8TN8Btwe/jKnZ0pjvQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"type-fest": "^0.8.1"
|
||||
"type-fest": "^0.20.2"
|
||||
}
|
||||
},
|
||||
"has-flag": {
|
||||
|
@ -32675,6 +32682,12 @@
|
|||
"prelude-ls": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"type-fest": {
|
||||
"version": "0.20.2",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
|
||||
"integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
|
||||
"dev": true
|
||||
},
|
||||
"yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
|
@ -37425,9 +37438,9 @@
|
|||
}
|
||||
},
|
||||
"mocha": {
|
||||
"version": "8.3.1",
|
||||
"resolved": "https://registry.npmjs.org/mocha/-/mocha-8.3.1.tgz",
|
||||
"integrity": "sha512-5SBMxANWqOv5bw3Hx+HVgaWlcWcFEQDUdaUAr1AUU+qwtx6cowhn7gEDT/DwQP7uYxnvShdUOVLbTYAHOEGfDQ==",
|
||||
"version": "8.3.2",
|
||||
"resolved": "https://registry.npmjs.org/mocha/-/mocha-8.3.2.tgz",
|
||||
"integrity": "sha512-UdmISwr/5w+uXLPKspgoV7/RXZwKRTiTjJ2/AC5ZiEztIoOYdfKb19+9jNmEInzx5pBsCyJQzarAxqIGBNYJhg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@ungap/promise-all-settled": "1.1.2",
|
||||
|
@ -40497,9 +40510,9 @@
|
|||
}
|
||||
},
|
||||
"rollup": {
|
||||
"version": "2.41.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.41.0.tgz",
|
||||
"integrity": "sha512-Gk76XHTggulWPH95q8V62bw6uqDH6UGvbD6LOa3QUyhuMF3eOuaeDHR7SLm1T9faitkpNrqzUAVYx47klcMnlA==",
|
||||
"version": "2.41.2",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.41.2.tgz",
|
||||
"integrity": "sha512-6u8fJJXJx6fmvKrAC9DHYZgONvSkz8S9b/VFBjoQ6dkKdHyPpPbpqiNl2Bao9XBzDHpq672X6sGZ9G1ZBqAHMg==",
|
||||
"requires": {
|
||||
"fsevents": "~2.3.1"
|
||||
},
|
||||
|
@ -40716,9 +40729,9 @@
|
|||
}
|
||||
},
|
||||
"rollup-plugin-polyfill-node": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup-plugin-polyfill-node/-/rollup-plugin-polyfill-node-0.6.1.tgz",
|
||||
"integrity": "sha512-r+A3VUWVMm5tiWoQPpe9BOPycN+G+XgXQGmOyDn6REPaZNvNz16rOQ/3X9U6xE7kQAlXQCnec9L5i0fFytNYCQ==",
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/rollup-plugin-polyfill-node/-/rollup-plugin-polyfill-node-0.6.2.tgz",
|
||||
"integrity": "sha512-gMCVuR0zsKq0jdBn8pSXN1Ejsc458k2QsFFvQdbHoM0Pot5hEnck+pBP/FDwFS6uAi77pD3rDTytsaUStsOMlA==",
|
||||
"requires": {
|
||||
"@rollup/plugin-inject": "^4.0.0"
|
||||
}
|
||||
|
|
|
@ -107,7 +107,6 @@
|
|||
],
|
||||
"dependencies": {
|
||||
"@babel/polyfill": "7.12.1",
|
||||
"@knadh/dragmove": "^0.1.2",
|
||||
"@web/dev-server-rollup": "0.3.2",
|
||||
"canvg": "3.0.7",
|
||||
"core-js": "3.9.1",
|
||||
|
@ -115,7 +114,7 @@
|
|||
"jspdf": "2.3.1",
|
||||
"pathseg": "1.2.0",
|
||||
"regenerator-runtime": "0.13.7",
|
||||
"rollup-plugin-polyfill-node": "^0.6.1",
|
||||
"rollup-plugin-polyfill-node": "^0.6.2",
|
||||
"svg2pdf.js": "2.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -147,7 +146,7 @@
|
|||
"cypress-multi-reporters": "1.4.0",
|
||||
"cypress-plugin-snapshots": "1.4.4",
|
||||
"deparam": "git+https://github.com/brettz9/deparam.git#updates",
|
||||
"eslint": "^7.21.0",
|
||||
"eslint": "^7.22.0",
|
||||
"eslint-config-standard": "16.0.2",
|
||||
"eslint-plugin-array-func": "3.1.7",
|
||||
"eslint-plugin-chai-expect": "2.2.0",
|
||||
|
@ -172,7 +171,7 @@
|
|||
"imageoptim-cli": "3.0.2",
|
||||
"jamilih": "0.54.0",
|
||||
"jsdoc": "3.6.6",
|
||||
"mocha": "8.3.1",
|
||||
"mocha": "8.3.2",
|
||||
"mocha-badge-generator": "0.9.0",
|
||||
"mochawesome": "6.2.2",
|
||||
"mochawesome-merge": "4.2.0",
|
||||
|
@ -188,7 +187,7 @@
|
|||
"remark-lint-ordered-list-marker-value": "2.0.1",
|
||||
"requirejs": "2.3.6",
|
||||
"rimraf": "3.0.2",
|
||||
"rollup": "2.41.0",
|
||||
"rollup": "2.41.2",
|
||||
"rollup-plugin-copy": "3.4.0",
|
||||
"rollup-plugin-filesize": "9.1.1",
|
||||
"rollup-plugin-node-polyfills": "0.2.1",
|
||||
|
|
|
@ -30,6 +30,10 @@ import {
|
|||
} from './locale.js';
|
||||
|
||||
import EditorStartup from './EditorStartup.js';
|
||||
import LeftPanel from './panels/LeftPanel.js';
|
||||
import TopPanel from './panels/TopPanel.js';
|
||||
import BottomPanel from './panels/BottomPanel.js';
|
||||
import LayersPanel from './panels/LayersPanel.js';
|
||||
|
||||
const {$id, $qa, isNullish, encode64, decode64, blankPageObjectURL} = SvgCanvas;
|
||||
|
||||
|
@ -131,6 +135,10 @@ class Editor extends EditorStartup {
|
|||
{key: modKey + 'c', fn () { curObj.copySelected(); }},
|
||||
{key: modKey + 'v', fn () { curObj.pasteInCenter(); }}
|
||||
];
|
||||
this.leftPanel = new LeftPanel(this);
|
||||
this.bottomPanel = new BottomPanel(this);
|
||||
this.topPanel = new TopPanel(this);
|
||||
this.layersPanel = new LayersPanel(this);
|
||||
}
|
||||
/**
|
||||
*
|
||||
|
@ -391,23 +399,6 @@ class Editor extends EditorStartup {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @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).addClass('current').siblings().removeClass('current');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a selected image's URL.
|
||||
* @function module:SVGthis.setImageURL
|
||||
|
@ -532,71 +523,6 @@ class Editor extends EditorStartup {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
updateToolbar () {
|
||||
let i, len;
|
||||
if (!isNullish(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;
|
||||
}
|
||||
}
|
||||
|
||||
$('#stroke_width').val(gWidth === null ? '' : gWidth);
|
||||
this.bottomPanelHandlers.updateColorpickers(true);
|
||||
break;
|
||||
} default: {
|
||||
this.bottomPanelHandlers.updateColorpickers(true);
|
||||
|
||||
$('#stroke_width').val(this.selectedElement.getAttribute('stroke-width') || 1);
|
||||
$('#stroke_style').val(this.selectedElement.getAttribute('stroke-dasharray') || 'none');
|
||||
|
||||
let attr = this.selectedElement.getAttribute('stroke-linejoin') || 'miter';
|
||||
|
||||
if ($('#linejoin_' + attr).length) {
|
||||
this.setStrokeOpt($('#linejoin_' + attr)[0]);
|
||||
}
|
||||
|
||||
attr = this.selectedElement.getAttribute('stroke-linecap') || 'butt';
|
||||
|
||||
if ($('#linecap_' + attr).length) {
|
||||
this.setStrokeOpt($('#linecap_' + attr)[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// All elements including image and group have opacity
|
||||
if (!isNullish(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') !== null) ? this.selectedElement.getAttribute('class') : '';
|
||||
}
|
||||
|
||||
this.bottomPanelHandlers.updateToolButtonState();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {void}
|
||||
|
@ -639,19 +565,19 @@ class Editor extends EditorStartup {
|
|||
selectedChanged (win, elems) {
|
||||
const mode = this.svgCanvas.getMode();
|
||||
if (mode === 'select') {
|
||||
this.leftPanelHandlers.clickSelect();
|
||||
this.leftPanel.clickSelect();
|
||||
}
|
||||
const isNode = mode === 'pathedit';
|
||||
// if this.elems[1] is present, then we have more than one element
|
||||
this.selectedElement = (elems.length === 1 || isNullish(elems[1]) ? elems[0] : null);
|
||||
this.multiselected = (elems.length >= 2 && !isNullish(elems[1]));
|
||||
if (!isNullish(this.selectedElement) && !isNode) {
|
||||
this.updateToolbar();
|
||||
this.topPanel.update();
|
||||
} // if (!isNullish(elem))
|
||||
|
||||
// Deal with pathedit mode
|
||||
this.togglePathEditMode(isNode, elems);
|
||||
this.topPanelHandlers.updateContextPanel();
|
||||
this.topPanel.updateContextPanel();
|
||||
this.svgCanvas.runExtensions('selectedChanged', /** @type {module:svgcanvas.SvgCanvas#event:ext_selectedChanged} */ {
|
||||
elems,
|
||||
selectedElement: this.selectedElement,
|
||||
|
@ -704,7 +630,7 @@ class Editor extends EditorStartup {
|
|||
elementChanged (win, elems) {
|
||||
const mode = this.svgCanvas.getMode();
|
||||
if (mode === 'select') {
|
||||
this.leftPanelHandlers.clickSelect();
|
||||
this.leftPanel.clickSelect();
|
||||
}
|
||||
|
||||
elems.forEach((elem) => {
|
||||
|
@ -732,11 +658,11 @@ class Editor extends EditorStartup {
|
|||
|
||||
// we tell it to skip focusing the text control if the
|
||||
// text element was previously in focus
|
||||
this.topPanelHandlers.updateContextPanel();
|
||||
this.topPanel.updateContextPanel();
|
||||
|
||||
// In the event a gradient was flipped:
|
||||
if (this.selectedElement && mode === 'select') {
|
||||
this.bottomPanelHandlers.updateColorpickers();
|
||||
this.bottomPanel.updateColorpickers();
|
||||
}
|
||||
|
||||
this.svgCanvas.runExtensions('elementChanged', /** @type {module:svgcanvas.SvgCanvas#event:ext_elementChanged} */ {
|
||||
|
@ -798,7 +724,7 @@ class Editor extends EditorStartup {
|
|||
|
||||
if (this.svgCanvas.getMode() === 'zoom' && bb.width) {
|
||||
// Go to select if a zoom box was drawn
|
||||
this.leftPanelHandlers.clickSelect();
|
||||
this.leftPanel.clickSelect();
|
||||
}
|
||||
|
||||
this.zoomDone();
|
||||
|
@ -832,183 +758,6 @@ class Editor extends EditorStartup {
|
|||
this.updateTitle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure the current selected paint is available to work with.
|
||||
* @returns {void}
|
||||
*/
|
||||
/* prepPaints () {
|
||||
paintBox.fill.prep();
|
||||
paintBox.stroke.prep();
|
||||
} */
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
setFlyoutPositions () {
|
||||
$('.tools_flyout').each(function () {
|
||||
const shower = $('#' + this.id + '_show');
|
||||
const {left, top} = shower.offset();
|
||||
const w = shower.outerWidth();
|
||||
this.css({left: (left + w) * editor.tool_scale, top});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
setFlyoutTitles () {
|
||||
$('.tools_flyout').each(function () {
|
||||
const shower = $('#' + this.id + '_show');
|
||||
if (shower.data('isLibrary')) {
|
||||
return;
|
||||
}
|
||||
const tooltips = this.children().map(function () {
|
||||
return this.title;
|
||||
}).get();
|
||||
shower[0].title = tooltips.join(' / ');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {PlainObject<string, module:SVGEditor.ToolButton>} holders Key is a selector
|
||||
* @returns {void}
|
||||
*/
|
||||
setupFlyouts (holders) {
|
||||
const allHolders = {};
|
||||
const currentObj = this;
|
||||
$.each(holders, function (holdSel, btnOpts) {
|
||||
if (!allHolders[holdSel]) {
|
||||
allHolders[holdSel] = [];
|
||||
}
|
||||
allHolders[holdSel].push(...btnOpts);
|
||||
|
||||
const buttons = $(holdSel).children().not('.tool_button_evt_handled');
|
||||
const showSel = holdSel + '_show';
|
||||
const shower = $(showSel);
|
||||
let def = false;
|
||||
buttons.addClass('tool_button tool_button_evt_handled')
|
||||
.unbind('click mousedown mouseup') // may not be necessary
|
||||
.each(function () {
|
||||
// Get this button's options
|
||||
const idSel = '#' + this.getAttribute('id');
|
||||
const [i, opts] = Object.entries(btnOpts).find(([_, {sel}]) => {
|
||||
return sel === idSel;
|
||||
});
|
||||
|
||||
// Remember the function that goes with this ID
|
||||
currentObj.flyoutFuncs[opts.sel] = opts.fn;
|
||||
|
||||
if (opts.isDefault) { def = i; }
|
||||
|
||||
const flyoutAction = function (ev) {
|
||||
let options = opts;
|
||||
// Find the currently selected tool if comes from keystroke
|
||||
if (ev.type === 'keydown') {
|
||||
const flyoutIsSelected = $(options.parent + '_show').hasClass('tool_button_current');
|
||||
const currentOperation = $(options.parent + '_show').attr('data-curopt');
|
||||
Object.entries(holders[opts.parent]).some(([j, tool]) => {
|
||||
if (tool.sel !== currentOperation) {
|
||||
return false;
|
||||
}
|
||||
if (!ev.shiftKey || !flyoutIsSelected) {
|
||||
options = tool;
|
||||
} else {
|
||||
// If flyout is selected, allow shift key to iterate through subitems
|
||||
j = Number.parseInt(j);
|
||||
// Use `allHolders` to include both extension `includeWith` and toolbarButtons
|
||||
options = allHolders[opts.parent][j + 1] ||
|
||||
holders[opts.parent][0];
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
if ($(this).hasClass('disabled')) { return false; }
|
||||
/* if (toolButtonClick(showSel)) {
|
||||
options.fn();
|
||||
} */
|
||||
const icon = (options.icon) ? $.getSvgIcon(options.icon, true) : $(options.sel).children().eq(0).clone();
|
||||
icon[0].setAttribute('width', shower.width());
|
||||
icon[0].setAttribute('height', shower.height());
|
||||
shower.children(':not(.flyout_arrow_horiz)').remove();
|
||||
shower.append(icon).attr('data-curopt', options.sel); // This sets the current mode
|
||||
return true;
|
||||
};
|
||||
|
||||
$(this).mouseup(flyoutAction);
|
||||
// TODO: currently not trigger here
|
||||
/* if (opts.key) {
|
||||
$(document).bind('keydown', opts.key[0] + ' shift+' + opts.key[0], flyoutAction);
|
||||
} */
|
||||
return true;
|
||||
});
|
||||
|
||||
if (def) {
|
||||
shower.attr('data-curopt', btnOpts[def].sel);
|
||||
} else if (!shower.attr('data-curopt')) {
|
||||
// Set first as default
|
||||
shower.attr('data-curopt', btnOpts[0].sel);
|
||||
}
|
||||
|
||||
let timer;
|
||||
|
||||
// Clicking the "show" icon should set the current mode
|
||||
shower.mousedown(function (evt) {
|
||||
if (shower.hasClass('disabled')) {
|
||||
return false;
|
||||
}
|
||||
const holder = $(holdSel);
|
||||
const pos = $(showSel).position();
|
||||
const l = pos.left + 34;
|
||||
const w = holder.width() * -1;
|
||||
const time = holder.data('shown_popop') ? 200 : 0;
|
||||
timer = setTimeout(function () {
|
||||
// Show corresponding menu
|
||||
if (!shower.data('isLibrary')) {
|
||||
holder.css('left', w).show().animate({
|
||||
left: l
|
||||
}, 150);
|
||||
} else {
|
||||
holder.css('left', l).show();
|
||||
}
|
||||
holder.data('shown_popop', true);
|
||||
}, time);
|
||||
evt.preventDefault();
|
||||
return true;
|
||||
}).mouseup(function (evt) {
|
||||
clearTimeout(timer);
|
||||
/* const opt = $(this).attr('data-curopt');
|
||||
// Is library and popped up, so do nothing
|
||||
if (shower.data('isLibrary') && $(showSel.replace('_show', '')).is(':visible')) {
|
||||
toolButtonClick(showSel, true);
|
||||
return;
|
||||
}
|
||||
if (toolButtonClick(showSel) && this.flyoutFuncs[opt]) {
|
||||
this.flyoutFuncs[opt]();
|
||||
} */
|
||||
});
|
||||
// $('#tools_rect').mouseleave(function () { $('#tools_rect').fadeOut(); });
|
||||
});
|
||||
this.setFlyoutTitles();
|
||||
// this.setFlyoutPositions();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} id
|
||||
* @param {external:jQuery} child
|
||||
* @returns {external:jQuery}
|
||||
*/
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
makeFlyoutHolder (id, child) {
|
||||
return $('<div>', {
|
||||
class: 'tools_flyout',
|
||||
id
|
||||
}).appendTo('#svg_editor').append(child);
|
||||
}
|
||||
|
||||
/**
|
||||
* @function module:SVGEditor.setIcon
|
||||
* @param {string|Element|external:jQuery} elem
|
||||
|
@ -1123,378 +872,12 @@ class Editor extends EditorStartup {
|
|||
const runCallback = () => {
|
||||
if (ext.callback && !cbCalled) {
|
||||
cbCalled = true;
|
||||
ext.callback.call(editor);
|
||||
ext.callback.call(this);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef {PlainObject} module:SVGthis.ContextTool
|
||||
* @property {string} panel The ID of the existing panel to which the tool is being added. Required.
|
||||
* @property {string} id The ID of the actual tool element. Required.
|
||||
* @property {PlainObject<string, external:jQuery.Function>|PlainObject<"change", external:jQuery.Function>} events DOM event names keyed to associated functions. Example: `{change () { seAlert('Option was changed') } }`. "change" event is one specifically handled for the "button-select" type. Required.
|
||||
* @property {string} title The tooltip text that will appear when the user hovers over the tool. Required.
|
||||
* @property {"tool_button"|"select"|"button-select"|"input"|string} type The type of tool being added. Expected.
|
||||
* @property {PlainObject<string, string>} [options] List of options and their labels for select tools. Example: `{1: 'One', 2: 'Two', all: 'All' }`. Required by "select" tools.
|
||||
* @property {string} [container_id] The ID to be given to the tool's container element.
|
||||
* @property {string} [defval] Default value
|
||||
* @property {string|Integer} [colnum] Added as part of the option list class.
|
||||
* @property {string} [label] Label associated with the tool, visible in the UI
|
||||
* @property {Integer} [size] Value of the "size" attribute of the tool input
|
||||
*/
|
||||
if (ext.context_tools) {
|
||||
$.each(ext.context_tools, function (i, tool) {
|
||||
// Add select tool
|
||||
const contId = tool.container_id ? (' id="' + tool.container_id + '"') : '';
|
||||
|
||||
let panel = $('#' + tool.panel);
|
||||
// create the panel if it doesn't exist
|
||||
if (!panel.length) {
|
||||
panel = $('<div>', {id: tool.panel}).appendTo('#tools_top');
|
||||
}
|
||||
|
||||
let html;
|
||||
// TODO: Allow support for other types, or adding to existing tool
|
||||
switch (tool.type) {
|
||||
case 'tool_button': {
|
||||
html = '<div class="tool_button">' + tool.id + '</div>';
|
||||
const div = $(html).appendTo(panel);
|
||||
if (tool.events) {
|
||||
$.each(tool.events, function (evt, func) {
|
||||
$(div).bind(evt, func);
|
||||
});
|
||||
}
|
||||
break;
|
||||
} case 'select': {
|
||||
html = '<label' + contId + '>' +
|
||||
'<select id="' + tool.id + '">';
|
||||
$.each(tool.options, function (val, text) {
|
||||
const sel = (val === tool.defval) ? ' selected' : '';
|
||||
html += '<option value="' + val + '"' + sel + '>' + text + '</option>';
|
||||
});
|
||||
html += '</select></label>';
|
||||
// Creates the tool, hides & adds it, returns the select element
|
||||
const sel = $(html).appendTo(panel).find('select');
|
||||
|
||||
$.each(tool.events, function (evt, func) {
|
||||
$(sel).bind(evt, func);
|
||||
});
|
||||
break;
|
||||
} case 'button-select': {
|
||||
html = '<div id="' + tool.id + '" class="dropdown toolset" title="' + tool.title + '">' +
|
||||
'<div id="cur_' + tool.id + '" class="icon_label"></div>' +
|
||||
'<button><img class="svg_icon" src="./images/arrow_down.svg" alt="icon" width="7" height="7"></button>' +
|
||||
'</div>';
|
||||
|
||||
const list = $('<ul id="' + tool.id + '_opts"></ul>').appendTo('#option_lists');
|
||||
|
||||
if (tool.colnum) {
|
||||
list.addClass('optcols' + tool.colnum);
|
||||
}
|
||||
|
||||
// Creates the tool, hides & adds it, returns the select element
|
||||
/* const dropdown = */ $(html).appendTo(panel).children();
|
||||
btnSelects.push({
|
||||
elem: ('#' + tool.id),
|
||||
list: ('#' + tool.id + '_opts'),
|
||||
title: tool.title,
|
||||
callback: tool.events.change,
|
||||
cur: ('#cur_' + tool.id)
|
||||
});
|
||||
break;
|
||||
} case 'input': {
|
||||
html = '<label' + contId + '>' +
|
||||
'<span id="' + tool.id + '_label">' +
|
||||
tool.label + ':</span>' +
|
||||
'<input id="' + tool.id + '" title="' + tool.title +
|
||||
'" size="' + (tool.size || '4') +
|
||||
'" value="' + (tool.defval || '') + '" type="text"/></label>';
|
||||
|
||||
// Creates the tool, hides & adds it, returns the select element
|
||||
|
||||
// Add to given tool.panel
|
||||
const inp = $(html).appendTo(panel).find('input');
|
||||
|
||||
if (tool.events) {
|
||||
$.each(tool.events, function (evt, func) {
|
||||
inp.bind(evt, func);
|
||||
});
|
||||
}
|
||||
break;
|
||||
} default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
const {svgicons} = ext;
|
||||
if (ext.buttons) {
|
||||
const fallbackObj = {},
|
||||
altsObj = {},
|
||||
placementObj = {},
|
||||
holders = {};
|
||||
|
||||
/**
|
||||
* @typedef {GenericArray} module:SVGEditor.KeyArray
|
||||
* @property {string} 0 The key to bind (on `keydown`)
|
||||
* @property {boolean} 1 Whether to `preventDefault` on the `keydown` event
|
||||
* @property {boolean} 2 Not apparently in use (NoDisableInInput)
|
||||
*/
|
||||
/**
|
||||
* @typedef {string|module:SVGEditor.KeyArray} module:SVGEditor.Key
|
||||
*/
|
||||
/**
|
||||
* @typedef {PlainObject} module:SVGEditor.Button
|
||||
* @property {string} id A unique identifier for this button. If SVG icons are used, this must match the ID used in the icon file. Required.
|
||||
* @property {"mode_flyout"|"mode"|"context"|"app_menu"} type Type of button. Required.
|
||||
* @property {string} title The tooltip text that will appear when the user hovers over the icon. Required.
|
||||
* @property {PlainObject<string, external:jQuery.Function>|PlainObject<"click", external:jQuery.Function>} events DOM event names with associated functions. Example: `{click () { alert('Button was clicked') } }`. Click is used with `includeWith` and `type` of "mode_flyout" (and "mode"); any events may be added if `list` is not present. Expected.
|
||||
* @property {string} panel The ID of the context panel to be included, if type is "context". Required only if type is "context".
|
||||
* @property {string} icon The file path to the raster version of the icon image source. Required only if no `svgicons` is supplied from [ExtensionInitResponse]{@link module:svgcanvas.ExtensionInitResponse}.
|
||||
* @property {string} [svgicon] If absent, will utilize the button "id"; used to set "placement" on the `svgIcons` call
|
||||
* @property {string} [list] Points to the "id" of a `context_tools` item of type "button-select" into which the button will be added as a panel list item
|
||||
* @property {Integer} [position] The numeric index for placement; defaults to last position (as of the time of extension addition) if not present. For use with {@link http://api.jquery.com/eq/}.
|
||||
* @property {boolean} [isDefault] Whether or not the button is the default. Used with `list`.
|
||||
* @property {PlainObject} [includeWith] Object with flyout menu data
|
||||
* @property {boolean} [includeWith.isDefault] Indicates whether button is default in flyout list or not.
|
||||
* @property {string} includeWith.button jQuery selector of the existing button to be joined. Example: '#tool_line'. Required if `includeWith` is used.
|
||||
* @property {"last"|Integer} [includeWith.position] Position of icon in flyout list; will be added to end if not indicated. Integer is for use with {@link http://api.jquery.com/eq/}.
|
||||
* @property {module:SVGEditor.Key} [key] The key to bind to the button
|
||||
*/
|
||||
// Add buttons given by extension
|
||||
$.each(ext.buttons, function (i, /** @type {module:SVGEditor.Button} */ btn) {
|
||||
let {id} = btn;
|
||||
let num = i;
|
||||
// Give button a unique ID
|
||||
while ($('#' + id).length) {
|
||||
id = btn.id + '_' + (++num);
|
||||
}
|
||||
|
||||
let icon;
|
||||
if (!svgicons) {
|
||||
icon = $(
|
||||
'<img src="' + self.configObj.curConfig.imgPath + btn.icon +
|
||||
(btn.title ? '" alt="' + btn.title : '') +
|
||||
'">'
|
||||
);
|
||||
} else {
|
||||
fallbackObj[id] = btn.icon;
|
||||
altsObj[id] = btn.title;
|
||||
const svgicon = btn.svgicon || btn.id;
|
||||
if (btn.type === 'app_menu') {
|
||||
placementObj['#' + id + ' > div'] = svgicon;
|
||||
} else {
|
||||
placementObj['#' + id] = svgicon;
|
||||
}
|
||||
}
|
||||
let cls, parent;
|
||||
|
||||
// Set button up according to its type
|
||||
switch (btn.type) {
|
||||
case 'mode_flyout':
|
||||
case 'mode':
|
||||
cls = 'tool_button';
|
||||
parent = '#tools_left';
|
||||
break;
|
||||
case 'context':
|
||||
cls = 'tool_button';
|
||||
parent = '#' + btn.panel;
|
||||
// create the panel if it doesn't exist
|
||||
if (!$(parent).length) {
|
||||
$('<div>', {id: btn.panel}).appendTo('#tools_top');
|
||||
}
|
||||
break;
|
||||
case 'app_menu':
|
||||
cls = '';
|
||||
parent = '#main_menu ul';
|
||||
break;
|
||||
}
|
||||
// refData
|
||||
let flyoutHolder, showBtn, refBtn;
|
||||
const button = $((btn.list || btn.type === 'app_menu') ? '<li/>' : '<div/>')
|
||||
.attr('id', id)
|
||||
.attr('title', btn.title)
|
||||
.addClass(cls);
|
||||
if (!btn.includeWith && !btn.list) {
|
||||
if ('position' in btn) {
|
||||
if ($(parent).children().eq(btn.position).length) {
|
||||
$(parent).children().eq(btn.position).before(button);
|
||||
} else {
|
||||
$(parent).children().last().after(button);
|
||||
}
|
||||
} else {
|
||||
button.appendTo(parent);
|
||||
}
|
||||
|
||||
if (btn.type === 'mode_flyout') {
|
||||
// Add to flyout menu / make flyout menu
|
||||
// const opts = btn.includeWith;
|
||||
// // opts.button, default, position
|
||||
refBtn = $(button);
|
||||
|
||||
flyoutHolder = refBtn.parent();
|
||||
// Create a flyout menu if there isn't one already
|
||||
let tlsId;
|
||||
if (!refBtn.parent().hasClass('tools_flyout')) {
|
||||
// Create flyout placeholder
|
||||
tlsId = refBtn[0].id.replace('tool_', 'tools_');
|
||||
showBtn = refBtn.clone()
|
||||
.attr('id', tlsId + '_show')
|
||||
.append($('<div>', {class: 'flyout_arrow_horiz'}));
|
||||
|
||||
refBtn.before(showBtn);
|
||||
|
||||
// Create a flyout div
|
||||
flyoutHolder = self.makeFlyoutHolder(tlsId, refBtn);
|
||||
flyoutHolder.data('isLibrary', true);
|
||||
showBtn.data('isLibrary', true);
|
||||
}
|
||||
// refData = Actions.getButtonData(opts.button);
|
||||
|
||||
placementObj['#' + tlsId + '_show'] = btn.id;
|
||||
// TODO: Find way to set the current icon using the iconloader if this is not default
|
||||
|
||||
// Include data for extension button as well as ref button
|
||||
/* curH = */ holders['#' + flyoutHolder[0].id] = [{
|
||||
sel: '#' + id,
|
||||
fn: btn.events.click,
|
||||
icon: btn.id,
|
||||
// key: btn.key,
|
||||
isDefault: true
|
||||
}]; // , refData
|
||||
//
|
||||
// // {sel:'#tool_rect', fn: clickRect, evt: 'mouseup', key: 4, parent: '#tools_rect', icon: 'rect'}
|
||||
//
|
||||
// const pos = ('position' in opts)?opts.position:'last';
|
||||
// const len = flyoutHolder.children().length;
|
||||
//
|
||||
// // Add at given position or end
|
||||
// if (!isNaN(pos) && pos >= 0 && pos < len) {
|
||||
// flyoutHolder.children().eq(pos).before(button);
|
||||
// } else {
|
||||
// flyoutHolder.append(button);
|
||||
// curH.reverse();
|
||||
// }
|
||||
} else if (btn.type === 'app_menu') {
|
||||
button.append('<div>').append(btn.title);
|
||||
}
|
||||
} else if (btn.list) {
|
||||
// Add button to list
|
||||
button.addClass('push_button');
|
||||
$('#' + btn.list + '_opts').append(button);
|
||||
if (btn.isDefault) {
|
||||
$('#cur_' + btn.list).append(button.children().clone());
|
||||
const svgicon = btn.svgicon || btn.id;
|
||||
placementObj['#cur_' + btn.list] = svgicon;
|
||||
}
|
||||
} else if (btn.includeWith) {
|
||||
// Add to flyout menu / make flyout menu
|
||||
const opts = btn.includeWith;
|
||||
// opts.button, default, position
|
||||
refBtn = $(opts.button);
|
||||
|
||||
flyoutHolder = refBtn.parent();
|
||||
// Create a flyout menu if there isn't one already
|
||||
let tlsId;
|
||||
if (!refBtn.parent().hasClass('tools_flyout')) {
|
||||
// Create flyout placeholder
|
||||
tlsId = refBtn[0].id.replace('tool_', 'tools_');
|
||||
showBtn = refBtn.clone()
|
||||
.attr('id', tlsId + '_show')
|
||||
.append($('<div>', {class: 'flyout_arrow_horiz'}));
|
||||
|
||||
refBtn.before(showBtn);
|
||||
// Create a flyout div
|
||||
flyoutHolder = self.makeFlyoutHolder(tlsId, refBtn);
|
||||
}
|
||||
|
||||
// refData = Actions.getButtonData(opts.button);
|
||||
|
||||
if (opts.isDefault) {
|
||||
placementObj['#' + tlsId + '_show'] = btn.id;
|
||||
}
|
||||
// TODO: Find way to set the current icon using the iconloader if this is not default
|
||||
|
||||
// Include data for extension button as well as ref button
|
||||
/* const curH = */ holders['#' + flyoutHolder[0].id] = [{
|
||||
sel: '#' + id,
|
||||
fn: btn.events.click,
|
||||
icon: btn.id,
|
||||
key: btn.key,
|
||||
isDefault: Boolean(btn.includeWith && btn.includeWith.isDefault)
|
||||
}]; // , refData
|
||||
// {sel:'#tool_rect', fn: clickRect, evt: 'mouseup', key: 4, parent: '#tools_rect', icon: 'rect'}
|
||||
|
||||
const pos = ('position' in opts) ? opts.position : 'last';
|
||||
const len = flyoutHolder.children().length;
|
||||
|
||||
// Add at given position or end
|
||||
if (!isNaN(pos) && pos >= 0 && pos < len) {
|
||||
flyoutHolder.children().eq(pos).before(button);
|
||||
} else {
|
||||
flyoutHolder.append(button);
|
||||
// curH.reverse();
|
||||
}
|
||||
}
|
||||
if (!svgicons) {
|
||||
button.append(icon);
|
||||
}
|
||||
if (!btn.list) {
|
||||
// Add given events to button
|
||||
$.each(btn.events, function (name, func) {
|
||||
if (name === 'click' && btn.type === 'mode') {
|
||||
// `touch.js` changes `touchstart` to `mousedown`,
|
||||
// so we must map extension click events as well
|
||||
if (isTouch() && name === 'click') {
|
||||
name = 'mousedown';
|
||||
}
|
||||
if (btn.includeWith) {
|
||||
button.bind(name, func);
|
||||
} else {
|
||||
button.bind(name, function () {
|
||||
/* if (toolButtonClick(button)) {
|
||||
func();
|
||||
} */
|
||||
});
|
||||
}
|
||||
if (btn.key) {
|
||||
// TODO: currently not trigger here
|
||||
// $(document).bind('keydown', btn.key, func);
|
||||
if (btn.title) {
|
||||
button.attr('title', btn.title + ' [' + btn.key + ']');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
button.bind(name, func);
|
||||
}
|
||||
});
|
||||
}
|
||||
self.setupFlyouts(holders);
|
||||
});
|
||||
$.each(btnSelects, function () {
|
||||
self.addAltDropDown(this.elem, this.list, this.callback, {seticon: true});
|
||||
});
|
||||
/* if (svgicons) {
|
||||
return new Promise((resolve, reject) => {
|
||||
$.svgIcons(`${this.configObj.curConfig.imgPath}${svgicons}`, {
|
||||
w: 24, h: 24,
|
||||
id_match: false,
|
||||
no_img: (!isWebkit()),
|
||||
fallback: fallbackObj,
|
||||
placement: placementObj,
|
||||
callback (icons) {
|
||||
// Non-ideal hack to make the icon match the current size
|
||||
// if (curPrefs.iconsize && curPrefs.iconsize !== 'm') {
|
||||
if (editor.pref('iconsize') !== 'm') {
|
||||
// prepResize();
|
||||
}
|
||||
runCallback();
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
} */
|
||||
}
|
||||
if (ext.events) {
|
||||
this.leftPanelHandlers.add(ext.events.id, ext.events.click);
|
||||
this.leftPanel.add(ext.events.id, ext.events.click);
|
||||
}
|
||||
return runCallback();
|
||||
}
|
||||
|
@ -1602,7 +985,7 @@ class Editor extends EditorStartup {
|
|||
if (!cw) { step *= -1; }
|
||||
const angle = Number.parseFloat($('#angle').val()) + step;
|
||||
this.svgCanvas.setRotationAngle(angle);
|
||||
this.topPanelHandlers.updateContextPanel();
|
||||
this.topPanel.updateContextPanel();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1615,13 +998,13 @@ class Editor extends EditorStartup {
|
|||
if (ok === 'Cancel') {
|
||||
return;
|
||||
}
|
||||
this.leftPanelHandlers.clickSelect();
|
||||
this.leftPanel.clickSelect();
|
||||
this.svgCanvas.clear();
|
||||
this.svgCanvas.setResolution(x, y);
|
||||
this.updateCanvas(true);
|
||||
this.zoomImage();
|
||||
this.layersPanel.populateLayers();
|
||||
this.topPanelHandlers.updateContextPanel();
|
||||
this.topPanel.updateContextPanel();
|
||||
this.svgCanvas.runExtensions('onNewDocument');
|
||||
}
|
||||
|
||||
|
@ -1803,7 +1186,7 @@ class Editor extends EditorStartup {
|
|||
return;
|
||||
}
|
||||
saveChanges();
|
||||
this.leftPanelHandlers.clickSelect();
|
||||
this.leftPanel.clickSelect();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2184,7 +1567,4 @@ class Editor extends EditorStartup {
|
|||
}
|
||||
}
|
||||
|
||||
const editor = new Editor();
|
||||
editor.init();
|
||||
|
||||
export default editor;
|
||||
export default Editor;
|
|
@ -6,10 +6,6 @@ import {
|
|||
} from './contextmenu.js';
|
||||
import editorTemplate from './templates/editorTemplate.js';
|
||||
import SvgCanvas from '../svgcanvas/svgcanvas.js';
|
||||
import LayersPanel from './panels/LayersPanel.js';
|
||||
import LeftPanelHandlers from './panels/LeftPanelHandlers.js';
|
||||
import BottomPanelHandlers from './panels/BottomPanelHandlers.js';
|
||||
import TopPanelHandlers from './panels/TopPanelHandlers.js';
|
||||
import Rulers from './Rulers.js';
|
||||
|
||||
/**
|
||||
|
@ -54,6 +50,7 @@ class EditorStartup {
|
|||
constructor () {
|
||||
this.extensionsAdded = false;
|
||||
this.messageQueue = [];
|
||||
this.$svgEditor = $id('svg_editor')
|
||||
}
|
||||
/**
|
||||
* Auto-run after a Promise microtask.
|
||||
|
@ -62,7 +59,7 @@ class EditorStartup {
|
|||
*/
|
||||
async init () {
|
||||
// allow to prepare the dom without display
|
||||
$id('svg_editor').style.visibility = 'hidden';
|
||||
this.$svgEditor.style.visibility = 'hidden';
|
||||
try {
|
||||
// add editor components to the DOM
|
||||
document.body.append(editorTemplate.content.cloneNode(true));
|
||||
|
@ -109,10 +106,10 @@ class EditorStartup {
|
|||
this.configObj.curConfig
|
||||
);
|
||||
|
||||
this.leftPanelHandlers = new LeftPanelHandlers(this);
|
||||
this.bottomPanelHandlers = new BottomPanelHandlers(this);
|
||||
this.topPanelHandlers = new TopPanelHandlers(this);
|
||||
this.layersPanel = new LayersPanel(this);
|
||||
this.leftPanel.init();
|
||||
this.bottomPanel.init();
|
||||
this.topPanel.init();
|
||||
this.layersPanel.init();
|
||||
|
||||
const {undoMgr} = this.svgCanvas;
|
||||
this.workarea = document.getElementById('workarea');
|
||||
|
@ -461,10 +458,6 @@ class EditorStartup {
|
|||
/**
|
||||
* Associate all button actions as well as non-button keyboard shortcuts.
|
||||
*/
|
||||
this.leftPanelHandlers.init();
|
||||
this.bottomPanelHandlers.init();
|
||||
this.topPanelHandlers.init();
|
||||
this.layersPanel.init();
|
||||
|
||||
$id('tool_clear').addEventListener('click', this.clickClear.bind(this));
|
||||
$id('tool_open').addEventListener('click', (e) => {
|
||||
|
@ -748,7 +741,7 @@ class EditorStartup {
|
|||
const {langParam, langData} = await this.putLocale(this.configObj.pref('lang'), this.goodLangs);
|
||||
await this.setLang(langParam, langData);
|
||||
|
||||
$id('svg_editor').style.visibility = 'visible';
|
||||
this.$svgEditor.style.visibility = 'visible';
|
||||
|
||||
try {
|
||||
// load standard extensions
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
// https://github.com/knadh/dragmove.js
|
||||
// Kailash Nadh (c) 2020.
|
||||
// MIT License.
|
||||
// can't use npm version as the dragmove is different.
|
||||
|
||||
let _loaded = false;
|
||||
let _callbacks = [];
|
||||
const _isTouch = window.ontouchstart !== undefined;
|
||||
|
||||
export const dragmove = function(target, handler, parent, onStart, onEnd, onDrag) {
|
||||
// Register a global event to capture mouse moves (once).
|
||||
if (!_loaded) {
|
||||
document.addEventListener(_isTouch ? "touchmove" : "mousemove", function(e) {
|
||||
let c = e;
|
||||
if (e.touches) {
|
||||
c = e.touches[0];
|
||||
}
|
||||
|
||||
// On mouse move, dispatch the coords to all registered callbacks.
|
||||
for (var i = 0; i < _callbacks.length; i++) {
|
||||
_callbacks[i](c.clientX, c.clientY);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_loaded = true;
|
||||
let isMoving = false, hasStarted = false;
|
||||
let startX = 0, startY = 0, lastX = 0, lastY = 0;
|
||||
|
||||
// On the first click and hold, record the offset of the pointer in relation
|
||||
// to the point of click inside the element.
|
||||
handler.addEventListener(_isTouch ? "touchstart" : "mousedown", function(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
if (target.dataset.dragEnabled === "false") {
|
||||
return;
|
||||
}
|
||||
|
||||
let c = e;
|
||||
if (e.touches) {
|
||||
c = e.touches[0];
|
||||
}
|
||||
|
||||
isMoving = true;
|
||||
startX = target.offsetLeft - c.clientX;
|
||||
startY = target.offsetTop - c.clientY;
|
||||
});
|
||||
|
||||
// On leaving click, stop moving.
|
||||
document.addEventListener(_isTouch ? "touchend" : "mouseup", function(e) {
|
||||
if (onEnd && hasStarted) {
|
||||
onEnd(target, parent, parseInt(target.style.left), parseInt(target.style.top));
|
||||
}
|
||||
|
||||
isMoving = false;
|
||||
hasStarted = false;
|
||||
});
|
||||
|
||||
// On leaving click, stop moving.
|
||||
document.addEventListener(_isTouch ? "touchmove" : "mousemove", function(e) {
|
||||
if (onDrag && hasStarted) {
|
||||
onDrag(target, parseInt(target.style.left), parseInt(target.style.top));
|
||||
}
|
||||
});
|
||||
|
||||
// Register mouse-move callback to move the element.
|
||||
_callbacks.push(function move(x, y) {
|
||||
if (!isMoving) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hasStarted) {
|
||||
hasStarted = true;
|
||||
if (onStart) {
|
||||
onStart(target, lastX, lastY);
|
||||
}
|
||||
}
|
||||
|
||||
lastX = x + startX;
|
||||
lastY = y + startY;
|
||||
|
||||
// If boundary checking is on, don't let the element cross the viewport.
|
||||
if (target.dataset.dragBoundary === "true") {
|
||||
if (lastX < 1 || lastX >= window.innerWidth - target.offsetWidth) {
|
||||
return;
|
||||
}
|
||||
if (lastY < 1 || lastY >= window.innerHeight - target.offsetHeight) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
target.style.left = lastX + "px";
|
||||
target.style.top = lastY + "px";
|
||||
});
|
||||
}
|
||||
|
||||
export { dragmove as default };
|
|
@ -6,7 +6,7 @@
|
|||
* @copyright 2013 James Sacksteder
|
||||
*
|
||||
*/
|
||||
import { dragmove } from '@knadh/dragmove';
|
||||
import { dragmove } from '../../../editor/dragmove/dragmove.js';
|
||||
export default {
|
||||
name: 'overview_window',
|
||||
init ({$, isChrome}) {
|
||||
|
@ -105,11 +105,11 @@ export default {
|
|||
document.getElementById('workarea').scrollLeft = portX;
|
||||
document.getElementById('workarea').scrollTop = portY;
|
||||
};
|
||||
const onStart = function () {
|
||||
const onStart = () => {
|
||||
overviewWindowGlobals.viewBoxDragging = true;
|
||||
updateViewPortFromViewBox();
|
||||
};
|
||||
const onEnd = function (el, parent, x, y) {
|
||||
const onEnd = (el, parent, x, y) => {
|
||||
if((el.offsetLeft + el.offsetWidth) > $(parent).attr('width')){
|
||||
el.style.left = ($(parent).attr('width') - el.offsetWidth) + 'px';
|
||||
} else if(el.offsetLeft < 0){
|
||||
|
|
|
@ -29,32 +29,6 @@
|
|||
|
||||
<body>
|
||||
<div id="svg_editor" role="main">
|
||||
<div id="sidepanels">
|
||||
<div id="layerpanel">
|
||||
<h3 id="layersLabel">Layers</h3>
|
||||
<fieldset id="layerbuttons">
|
||||
<se-button id="layer_new" title="New Layer" size="small" src="./images/new.svg"></se-button>
|
||||
<se-button id="layer_delete" title="Delete Layer" size="small" src="./images/delete.svg"></se-button>
|
||||
<se-button id="layer_rename" title="Rename Layer" size="small" src="./images/text.svg"></se-button>
|
||||
<se-button id="layer_up" title="Move Layer Up" size="small" src="./images/go_up.svg"></se-button>
|
||||
<se-button id="layer_down" title="Move Layer Down" size="small" src="./images/go_down.svg"></se-button>
|
||||
<se-button id="layer_moreopts" title="More Options" size="small" src="./images/context_menu.svg">
|
||||
</se-button>
|
||||
</fieldset>
|
||||
<table id="layerlist">
|
||||
<tr class="layer">
|
||||
<td class="layervis"></td>
|
||||
<td class="layername">Layer 1</td>
|
||||
</tr>
|
||||
</table>
|
||||
<span id="selLayerLabel">Move elements to:</span>
|
||||
<select id="selLayerNames" title="Move selected elements to a different layer" disabled="disabled">
|
||||
<option selected="selected" value="layer1">Layer 1</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="sidepanel_handle" title="Drag left/right to resize side panel [X]">L a y e r s
|
||||
</div>
|
||||
</div>
|
||||
<se-menu id="main_button" label="SVG-Edit" src="./images/logo.svg" alt="logo">
|
||||
<!-- File-like buttons: New, Save, Source -->
|
||||
<se-menu-item id="tool_clear" label="New Image" shortcut="N" src="./images/new.svg"></se-menu-item>
|
||||
|
@ -69,301 +43,8 @@
|
|||
<se-menu-item id="tool_editor_homepage" label="SVG-Edit Home Page" src="./images/logo.svg">
|
||||
</se-menu-item>
|
||||
</se-menu>
|
||||
<div id="tools_top">
|
||||
<div id="editor_panel">
|
||||
<div class="tool_sep"></div>
|
||||
<se-button id="tool_source" title="Edit Source" shortcut="U" src="./images/source.svg"></se-button>
|
||||
<se-button id="tool_wireframe" title="Wireframe Mode" shortcut="F" src="./images/wireframe.svg"></se-button>
|
||||
<se-button id="view_grid" title="Show grid" src="./images/grid.svg"></se-button>
|
||||
</div> <!-- editor_panel -->
|
||||
<div id="history_panel">
|
||||
<div class="tool_sep"></div>
|
||||
<se-button id="tool_undo" title="Undo" shortcut="Z" src="./images/undo.svg" disabled></se-button>
|
||||
<se-button id="tool_redo" title="Redo" shortcut="Y" src="./images/redo.svg" disabled></se-button>
|
||||
</div> <!-- history_panel -->
|
||||
<!-- Buttons when a single element is selected -->
|
||||
<div id="selected_panel">
|
||||
<div class="toolset">
|
||||
<div class="tool_sep"></div>
|
||||
<se-button id="tool_clone" title="Duplicate Element" shortcut="D" src="./images/clone.svg"></se-button>
|
||||
<se-button id="tool_delete" title="Delete Element" shortcut="Backspace" src="./images/delete.svg">
|
||||
</se-button>
|
||||
</div>
|
||||
<div class="toolset">
|
||||
<div class="tool_sep"></div>
|
||||
<se-button id="tool_move_top" title="Bring to Front" shortcut="Ctrl+Shift+]" src="./images/move_top.svg">
|
||||
</se-button>
|
||||
<se-button id="tool_move_bottom" title="Send to Back" shortcut="Ctrl+Shift+[" src="./images/move_bottom.svg">
|
||||
</se-button>
|
||||
</div>
|
||||
<div class="toolset">
|
||||
<se-button id="tool_topath" title="Convert to Path" src="./images/to_path.svg"></se-button>
|
||||
<se-button id="tool_reorient" title="Reorient path" src="./images/reorient.svg"></se-button>
|
||||
<se-button id="tool_make_link" title="Make (hyper)link" src="./images/globe_link.svg"></se-button>
|
||||
</div>
|
||||
<div class="toolset">
|
||||
<div class="tool_sep"></div>
|
||||
<se-input id="elem_id" data-attr="id" size="10" label="id" title="Identify the element"></se-input>
|
||||
</div>
|
||||
<div class="toolset">
|
||||
<se-input id="elem_class" data-attr="class" size="10" label="class" title="Element class"></se-input>
|
||||
</div>
|
||||
<se-spin-input size="3" id="angle" min=-180 max=180 step=5 src="./images/angle.svg"
|
||||
title="Change rotation angle"></se-spin-input>
|
||||
<se-spin-input size="2" id="blur" min=0 max=100 step=5 src="./images/blur.svg"
|
||||
title="Change gaussian blur value"></se-spin-input>
|
||||
<se-list id="tool_position" title="Align Element to Page" label="" width="22px" height="24px">
|
||||
<se-list-item id="tool_posleft" value="l">
|
||||
<img title="align left" src="./images/align_left.svg" height="22px">
|
||||
</se-list-item>
|
||||
<se-list-item id="tool_poscenter" value="c">
|
||||
<img title="align center" src="./images/align_center.svg" height="22px">
|
||||
</se-list-item>
|
||||
<se-list-item id="tool_posright" value="r">
|
||||
<img title="align right" src="./images/align_right.svg" height="22px">
|
||||
</se-list-item>
|
||||
<se-list-item id="tool_postop" value="t">
|
||||
<img title="align top" src="./images/align_top.svg" height="22px">
|
||||
</se-list-item>
|
||||
<se-list-item id="tool_posmiddle" value="m">
|
||||
<img title="align middle" src="./images/align_middle.svg" height="22px">
|
||||
</se-list-item>
|
||||
<se-list-item id="tool_posbottom" value="b">
|
||||
<img title="align bottom" src="./images/align_bottom.svg" height="22px">
|
||||
</se-list-item>
|
||||
</se-list>
|
||||
<div id="xy_panel" class="toolset">
|
||||
<se-spin-input id="selected_x" data-attr="x" size="4" type="text" label="x" title="Change X coordinate">
|
||||
</se-spin-input>
|
||||
<se-spin-input id="selected_y" data-attr="y" size="4" type="text" label="y" title="Change Y coordinate">
|
||||
</se-spin-input>
|
||||
</div>
|
||||
</div> <!-- selected_panel -->
|
||||
<!-- Buttons when multiple elements are selected -->
|
||||
<div id="multiselected_panel">
|
||||
<div class="tool_sep"></div>
|
||||
<se-button id="tool_clone_multi" title="Clone Elements" shortcut="C" src="./images/clone.svg"></se-button>
|
||||
<se-button id="tool_delete_multi" title="Delete Selected Elements" shortcut="Delete/Backspace"
|
||||
src="./images/delete.svg"></se-button>
|
||||
<div class="tool_sep"></div>
|
||||
<se-button id="tool_group_elements" title="Group Elements" shortcut="G" src="./images/group_elements.svg">
|
||||
</se-button>
|
||||
<se-button id="tool_make_link_multi" title="Make (hyper)link" src="./images/globe_link.svg"></se-button>
|
||||
<se-button id="tool_align_left" title="Align Left" src="./images/align_left.svg"></se-button>
|
||||
<se-button id="tool_align_center" title="Align Center" src="./images/align_center.svg"></se-button>
|
||||
<se-button id="tool_align_right" title="Align Right" src="./images/align_right.svg"></se-button>
|
||||
<se-button id="tool_align_top" title="Align Top" src="./images/align_top.svg"></se-button>
|
||||
<se-button id="tool_align_middle" title="Align Middle" src="./images/align_middle.svg"></se-button>
|
||||
<se-button id="tool_align_bottom" title="Align Bottom" src="./images/align_bottom.svg"></se-button>
|
||||
<se-list id="tool_align_relative" label="relative to:">
|
||||
<se-list-item id="selected_objects" value="selected">selected objects</se-list-item>
|
||||
<se-list-item id="largest_object" value="largest">largest object</se-list-item>
|
||||
<se-list-item id="smallest_object" value="smallest">smallest object</se-list-item>
|
||||
<se-list-item id="page" value="page">page</se-list-item>
|
||||
</se-list>
|
||||
<div class="tool_sep"></div>
|
||||
</div> <!-- multiselected_panel -->
|
||||
<div id="rect_panel">
|
||||
<div class="toolset">
|
||||
<se-spin-input id="rect_width" data-attr="width" size="4" label="w"
|
||||
title="Change rectangle width"></se-spin-input>
|
||||
<se-spin-input id="rect_height" data-attr="height" size="4" label="h"
|
||||
title="Change rectangle height"></se-spin-input>
|
||||
</div>
|
||||
<se-spin-input id="rect_rx" min=0 max=1000 step=1 size="3" title="Change Rectangle Corner Radius"
|
||||
data-attr="Corner Radius" src="./images/c_radius.svg"></se-spin-input>
|
||||
</div> <!-- rect_panel -->
|
||||
<div id="image_panel">
|
||||
<div class="toolset">
|
||||
<se-spin-input id="image_width" data-attr="width" size="4" type="text" label="w"
|
||||
title="Change image width"></se-spin-input>
|
||||
<se-spin-input id="image_height" data-attr="height" size="4" type="text" label="h"
|
||||
title="Change image height"></se-spin-input>
|
||||
</div>
|
||||
<div class="toolset">
|
||||
<label id="tool_image_url">url:
|
||||
<input id="image_url" type="text" title="Change URL" size="35" />
|
||||
</label>
|
||||
<label id="tool_change_image">
|
||||
<button id="change_image_url" style="display: none;">Change Image</button>
|
||||
<span id="url_notice"
|
||||
title="NOTE: This image cannot be embedded. It will depend on this path to be displayed"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div> <!-- image_panel -->
|
||||
<div id="circle_panel">
|
||||
<div class="toolset">
|
||||
<se-spin-input id="circle_cx" data-attr="cx" size="4" label="cx"></se-spin-input>
|
||||
<se-spin-input id="circle_cy" data-attr="cy" size="4" label="cy"></se-spin-input>
|
||||
</div>
|
||||
<div class="toolset">
|
||||
<se-spin-input id="circle_r" data-attr="r" size="4" label="r"></se-spin-input>
|
||||
</div>
|
||||
</div> <!-- circle_panel -->
|
||||
<div id="ellipse_panel">
|
||||
<div class="toolset">
|
||||
<se-spin-input id="ellipse_cx" data-attr="cx" size="4" title="Change ellipse's cx coordinate" label="cx">
|
||||
</se-spin-input>
|
||||
<se-spin-input id="ellipse_cy" data-attr="cy" size="4" title="Change ellipse's cy coordinate" label="cy">
|
||||
</se-spin-input>
|
||||
</div>
|
||||
<div class="toolset">
|
||||
<se-spin-input id="ellipse_rx" data-attr="rx" size="4" title="Change ellipse's x radius" label="rx">
|
||||
</se-spin-input>
|
||||
<se-spin-input id="ellipse_ry" data-attr="ry" size="4" title="Change ellipse's y radius" label="ry">
|
||||
</se-spin-input>
|
||||
</div>
|
||||
</div> <!-- ellipse_panel -->
|
||||
<div id="line_panel">
|
||||
<div class="toolset">
|
||||
<se-spin-input id="line_x1" data-attr="x1" size="4" title="Change line's starting x coordinate" label="x1">
|
||||
</se-spin-input>
|
||||
<se-spin-input id="line_y1" data-attr="y1" size="4" title="Change line's starting y coordinate" label="y1">
|
||||
</se-spin-input>
|
||||
<se-spin-input id="line_x2" data-attr="x2" size="4" title="Change line's ending x coordinate" label="x2">
|
||||
</se-spin-input>
|
||||
<se-spin-input id="line_y2" data-attr="y2" size="4" title="Change line's ending y coordinate" label="y2">
|
||||
</se-spin-input>
|
||||
</div>
|
||||
</div> <!-- line_panel -->
|
||||
<div id="text_panel">
|
||||
<div class="toolset">
|
||||
<se-button id="tool_bold" title="Bold Text [B]" src="./images/bold.svg" shortcut="B"></se-button>
|
||||
<se-button id="tool_italic" title="Italic Text [I]" src="./images/italic.svg" shortcut="I"></se-button>
|
||||
<se-button id="tool_text_anchor_start" title="Align the text from start" src="./images/anchor_start.svg">
|
||||
</se-button>
|
||||
<se-button id="tool_text_anchor_middle" title="Align the text from middle" src="./images/anchor_middle.svg">
|
||||
</se-button>
|
||||
<se-button id="tool_text_anchor_end" title="Align the text from end" src="./images/anchor_end.svg">
|
||||
</se-button>
|
||||
</div>
|
||||
<se-list id="tool_font_family" label="Font:">
|
||||
<se-list-item value="Serif" style="font-family:serif;"> Serif</se-list-item>
|
||||
<se-list-item value="Sans-serif" style="font-family:sans-serif;"> Sans-serif</se-list-item>
|
||||
<se-list-item value="Cursive" style="font-family:cursive;"> Cursive</se-list-item>
|
||||
<se-list-item value="Fantasy" style="font-family:fantasy;"> Fantasy</se-list-item>
|
||||
<se-list-item value="Monospace" style="font-family:monospace;"> Monospace</se-list-item>
|
||||
<se-list-item value="Courier" style="font-family:courier;"> Courier</se-list-item>
|
||||
<se-list-item value="Helvetica" style="font-family:helvetica;">Helvetica</se-list-item>
|
||||
<se-list-item value="Times" style="font-family:times;">Times</se-list-item>
|
||||
</se-list>
|
||||
<se-spin-input size="2" id="font_size" min=1 max=1000 step=1 title="Change Font Size"
|
||||
src="./images/fontsize.svg"></se-spin-input>
|
||||
<!-- Not visible, but still used -->
|
||||
<input id="text" type="text" size="35" />
|
||||
</div> <!-- text_panel -->
|
||||
<!-- formerly gsvg_panel -->
|
||||
<div id="container_panel">
|
||||
<div class="tool_sep"></div>
|
||||
<!-- Add viewBox field here? -->
|
||||
<label id="group_title" title="Group identification label">
|
||||
<span>label</span>
|
||||
<input id="g_title" data-attr="title" size="10" type="text" />
|
||||
</label>
|
||||
</div> <!-- container_panel -->
|
||||
<div id="use_panel">
|
||||
<se-button id="tool_unlink_use" title="Break link to reference element (make unique)" src="./images/unlink_use.svg">
|
||||
</se-button>
|
||||
</div> <!-- use_panel -->
|
||||
<div id="g_panel">
|
||||
<se-button id="tool_ungroup" title="Ungroup Elements [G]" src="./images/ungroup.svg">
|
||||
</se-button>
|
||||
</div> <!-- g_panel -->
|
||||
<!-- For anchor elements -->
|
||||
<div id="a_panel">
|
||||
<label id="tool_link_url" title="Set link URL (leave empty to remove)">
|
||||
<span id="linkLabel" class="icon_label"></span>
|
||||
<input id="link_url" type="text" size="35" />
|
||||
</label>
|
||||
</div> <!-- a_panel -->
|
||||
<div id="path_node_panel">
|
||||
<div class="tool_sep"></div>
|
||||
<se-button id="tool_node_link" title="Link Control Points" src="./images/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="Change node's x coordinate" label="x:">
|
||||
</se-spin-input>
|
||||
<se-spin-input id="path_node_y" data-attr="y" size="4" title="Change node's y coordinate" label="y:">
|
||||
</se-spin-input>
|
||||
<select id="seg_type" title="Change Segment type">
|
||||
<option id="straight_segments" selected="selected" value="4">Straight</option>
|
||||
<option id="curve_segments" value="6">Curve</option>
|
||||
</select>
|
||||
<se-button id="tool_node_clone" title="Clone Node" src="./images/tool_node_clone.svg"></se-button>
|
||||
<se-button id="tool_node_delete" title="Delete Node" src="./images/tool_node_delete.svg"></se-button>
|
||||
<se-button id="tool_openclose_path" title="Open/close sub-path" src="./images/tool_openclose_path.svg">
|
||||
</se-button>
|
||||
<se-button id="tool_add_subpath" title="Add sub-path" src="./images/tool_add_subpath.svg"></se-button>
|
||||
</div> <!-- path_node_panel -->
|
||||
<div id="cur_context_panel"></div>
|
||||
</div> <!-- tools_top -->
|
||||
<div id="tools_left">
|
||||
<se-button id="tool_select" title="Select Tool" src="./images/select.svg"></se-button>
|
||||
<se-button id="tool_zoom" title="Zoom Tool" src="./images/zoom.svg" shortcut="Z"></se-button>
|
||||
<se-button id="ext-panning" title="Panning" src="./images/panning.svg"></se-button>
|
||||
<se-button id="tool_fhpath" title="Pencil Tool" src="./images/pencil.svg" shortcut="Q"></se-button>
|
||||
<se-button id="tool_line" title="Line Tool" src="./images/pen.svg" shortcut="L"></se-button>
|
||||
<se-button id="tool_path" title="Path Tool" src="./images/path.svg" shortcut="P"></se-button>
|
||||
<se-flyingbutton id="tools_rect" title="Square/Rect Tool">
|
||||
<se-button id="tool_rect" title="Rectangle" src="./images/rect.svg" shortcut="R"></se-button>
|
||||
<se-button id="tool_square" title="Square" src="./images/square.svg"></se-button>
|
||||
<se-button id="tool_fhrect" title="Free-Hand Rectangle" src="./images/fh_rect.svg"></se-button>
|
||||
</se-flyingbutton>
|
||||
<se-flyingbutton id="tools_ellipse" title="Ellipse/Circle Tool">
|
||||
<se-button id="tool_ellipse" title="Rectangle" src="./images/ellipse.svg" shortcut="E"></se-button>
|
||||
<se-button id="tool_circle" title="Square" src="./images/circle.svg"></se-button>
|
||||
<se-button id="tool_fhellipse" title="Free-Hand Rectangle" src="./images/fh_ellipse.svg"></se-button>
|
||||
</se-flyingbutton>
|
||||
<se-flyingbutton id="tools_polygon" title="Polygone/Star Tool">
|
||||
<se-button id="tool_polygon" title="Polygon Tool" src="./images/polygon.svg"></se-button>
|
||||
<se-button id="tool_star" title="Star Tool" src="./images/star.svg"></se-button>
|
||||
</se-flyingbutton>
|
||||
<se-button id="mode_connect" title="Connect two objects" src="./images/conn.svg"></se-button>
|
||||
<se-button id="tool_text" title="Text Tool" src="./images/text.svg" shortcut="T"></se-button>
|
||||
<se-button id="tool_image" title="Image Tool" src="./images/image.svg"></se-button>
|
||||
<se-button id="tool_eyedropper" title="Eye Dropper Tool" src="./images/eye_dropper.svg" shortcut="I"></se-button>
|
||||
<se-explorerbutton id="tool_shapelib" title="Shape library" lib="./extensions/ext-shapes/shapelib/"
|
||||
src="./images/shapelib.svg"></se-explorerbutton>
|
||||
</div> <!-- tools_left -->
|
||||
<div id="tools_bottom">
|
||||
<!-- Zoom buttons -->
|
||||
<se-zoom id="zoom" src="./images/zoom.svg" title="Change zoom level" inputsize="40px">
|
||||
<div value="1000">1000</div>
|
||||
<div value="400">400</div>
|
||||
<div value="200">200</div>
|
||||
<div value="100">100</div>
|
||||
<div value="50">50</div>
|
||||
<div value="25">25</div>
|
||||
<div value="canvas">Fit to canvas</div>
|
||||
<div value="selection">Fit to selection</div>
|
||||
<div value="layer">Fit to layer content</div>
|
||||
<div value="content">Fit to all content</div>
|
||||
</se-zoom>
|
||||
<se-colorpicker id="fill_color" src="./images/fill.svg" title="Change fill color" type="fill"></se-colorpicker>
|
||||
<se-colorpicker id="stroke_color" src="./images/stroke.svg" title="Change stroke color" type="stroke"></se-colorpicker>
|
||||
<se-spin-input id="stroke_width" min=0 max=99 step=1 title="Change stroke width" label=""></se-spin-input>
|
||||
<se-list id="stroke_style" title="Change stroke dash style" label="" width="22px" height="24px">
|
||||
<se-list-item value="none">—</se-list-item>
|
||||
<se-list-item value="2,2">...</se-list-item>
|
||||
<se-list-item value="5,5">- -</se-list-item>
|
||||
<se-list-item value="5,2,2,2">- .</se-list-item>
|
||||
<se-list-item value="5,2,2,2,2,2">- ..</se-list-item>
|
||||
</se-list>
|
||||
<se-list id="stroke_linejoin" title="Linejoin: Miter" label="" width="22px" height="24px">
|
||||
<se-list-item id="linejoin_miter" value="miter"><img title="Linejoin: Miter" src="./images/linejoin_miter.svg" height="22px"></img></se-list-item>
|
||||
<se-list-item id="linejoin_round" value="round"><img title="Linejoin: Round" src="./images/linejoin_round.svg" height="22px"></img></se-list-item>
|
||||
<se-list-item id="linejoin_bevel" value="bevel"><img title="Linejoin: Bevel" src="./images/linejoin_bevel.svg" height="22px"></img></se-list-item>
|
||||
</se-list>
|
||||
<se-list id="stroke_linecap" title="Linecap: Butt" label="" width="22px" height="24px">
|
||||
<se-list-item id="linecap_butt" value="butt"><img title="Linecap: Butt" src="./images/linecap_butt.svg" height="22px"></img></se-list-item>
|
||||
<se-list-item id="linecap_square" value="square"><img title="Linecap: Square" src="./images/linecap_square.svg" height="22px"></img></se-list-item>
|
||||
<se-list-item id="linecap_round" value="round"><img title="Linecap: Round" src="./images/linecap_round.svg" height="22px"></img></se-list-item>
|
||||
</se-list>
|
||||
<se-spin-input size="3" id="opacity" min=0 max=100 step=5 title="Change selected item opacity" src="./images/opacity.svg"></se-spin-input>
|
||||
<se-palette id="palette"></se-palette>
|
||||
</div> <!-- tools_bottom -->
|
||||
<div id="option_lists" class="dropdown"></div>
|
||||
<div id="option_lists" class="dropdown"></div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
|
@ -7,7 +7,10 @@ For default config and extensions (and available options) available to
|
|||
import './jquery.min.js';
|
||||
import './components/index.js';
|
||||
import './dialogs/index.js';
|
||||
import svgEditor from './svgedit.js';
|
||||
import Editor from './Editor.js';
|
||||
|
||||
const svgEditor = new Editor();
|
||||
svgEditor.init();
|
||||
|
||||
// URL OVERRIDE CONFIG
|
||||
svgEditor.setConfig({
|
||||
|
|
|
@ -0,0 +1,244 @@
|
|||
import SvgCanvas from '../../svgcanvas/svgcanvas.js';
|
||||
import {jGraduate} from '../components/jgraduate/jQuery.jGraduate.js';
|
||||
|
||||
const {$id, $qa} = SvgCanvas;
|
||||
|
||||
/*
|
||||
* register actions for left panel
|
||||
*/
|
||||
/**
|
||||
* @type {module}
|
||||
*/
|
||||
class BottomPanel {
|
||||
/**
|
||||
* @param {PlainObject} editor svgedit handler
|
||||
*/
|
||||
constructor (editor) {
|
||||
this.editor = editor;
|
||||
}
|
||||
/**
|
||||
* @type {module}
|
||||
*/
|
||||
get selectedElement () {
|
||||
return this.editor.selectedElement;
|
||||
}
|
||||
/**
|
||||
* @type {module}
|
||||
*/
|
||||
get multiselected () {
|
||||
return this.editor.multiselected;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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.editor.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.editor.svgCanvas.getZoom();
|
||||
const wArea = this.editor.workarea;
|
||||
|
||||
this.editor.zoomChanged(window, {
|
||||
width: 0,
|
||||
height: 0,
|
||||
// center pt of scroll position
|
||||
x: (wArea.scrollLeft + parseFloat(getComputedStyle(wArea, null).width.replace("px", "")) / 2) / zoom,
|
||||
y: (wArea.scrollTop + parseFloat(getComputedStyle(wArea, null).height.replace("px", "")) / 2) / zoom,
|
||||
zoom: zoomlevel
|
||||
}, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @fires module:svgcanvas.SvgCanvas#event:ext_toolButtonStateUpdate
|
||||
* @returns {void}
|
||||
*/
|
||||
updateToolButtonState () {
|
||||
const bNoFill = (this.editor.svgCanvas.getColor('fill') === 'none');
|
||||
const bNoStroke = (this.editor.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.editor.svgCanvas.runExtensions(
|
||||
'toolButtonStateUpdate',
|
||||
/** @type {module:svgcanvas.SvgCanvas#event:ext_toolButtonStateUpdate} */ {
|
||||
nofill: bNoFill,
|
||||
nostroke: bNoStroke
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {module}
|
||||
*/
|
||||
handleColorPicker (type, evt) {
|
||||
const {paint} = evt.detail;
|
||||
this.editor.svgCanvas.setPaint(type, paint);
|
||||
this.updateToolButtonState();
|
||||
}
|
||||
/**
|
||||
* @type {module}
|
||||
*/
|
||||
handleStrokeAttr (type, evt) {
|
||||
this.editor.svgCanvas.setStrokeAttr(type, evt.detail.value);
|
||||
}
|
||||
/**
|
||||
* @type {module}
|
||||
*/
|
||||
handleOpacity (evt) {
|
||||
// if ($(this).find('div').length) { return; }
|
||||
const val = Number.parseInt(evt.currentTarget.value.split('%')[0]);
|
||||
this.editor.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.editor.svgCanvas.setColor(picker, color);
|
||||
if (color !== 'none' && this.editor.svgCanvas.getPaintOpacity(picker) !== 1) {
|
||||
this.editor.svgCanvas.setPaintOpacity(picker, 1.0);
|
||||
}
|
||||
this.updateToolButtonState();
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {module}
|
||||
*/
|
||||
init () {
|
||||
// register actions for Bottom panel
|
||||
const template = document.createElement('template');
|
||||
template.innerHTML = `
|
||||
<div id="tools_bottom">
|
||||
<!-- Zoom buttons -->
|
||||
<se-zoom id="zoom" src="./images/zoom.svg" title="Change zoom level" inputsize="40px">
|
||||
<div value="1000">1000</div>
|
||||
<div value="400">400</div>
|
||||
<div value="200">200</div>
|
||||
<div value="100">100</div>
|
||||
<div value="50">50</div>
|
||||
<div value="25">25</div>
|
||||
<div value="canvas">Fit to canvas</div>
|
||||
<div value="selection">Fit to selection</div>
|
||||
<div value="layer">Fit to layer content</div>
|
||||
<div value="content">Fit to all content</div>
|
||||
</se-zoom>
|
||||
<se-colorpicker id="fill_color" src="./images/fill.svg" title="Change fill color" type="fill"></se-colorpicker>
|
||||
<se-colorpicker id="stroke_color" src="./images/stroke.svg" title="Change stroke color" type="stroke">
|
||||
</se-colorpicker>
|
||||
<se-spin-input id="stroke_width" min=0 max=99 step=1 title="Change stroke width" label=""></se-spin-input>
|
||||
<se-list id="stroke_style" title="Change stroke dash style" label="" width="22px" height="24px">
|
||||
<se-list-item value="none">—</se-list-item>
|
||||
<se-list-item value="2,2">...</se-list-item>
|
||||
<se-list-item value="5,5">- -</se-list-item>
|
||||
<se-list-item value="5,2,2,2">- .</se-list-item>
|
||||
<se-list-item value="5,2,2,2,2,2">- ..</se-list-item>
|
||||
</se-list>
|
||||
<se-list id="stroke_linejoin" title="Linejoin: Miter" label="" width="22px" height="24px">
|
||||
<se-list-item id="linejoin_miter" value="miter"><img title="Linejoin: Miter" src="./images/linejoin_miter.svg"
|
||||
height="22px"></img></se-list-item>
|
||||
<se-list-item id="linejoin_round" value="round"><img title="Linejoin: Round" src="./images/linejoin_round.svg"
|
||||
height="22px"></img></se-list-item>
|
||||
<se-list-item id="linejoin_bevel" value="bevel"><img title="Linejoin: Bevel" src="./images/linejoin_bevel.svg"
|
||||
height="22px"></img></se-list-item>
|
||||
</se-list>
|
||||
<se-list id="stroke_linecap" title="Linecap: Butt" label="" width="22px" height="24px">
|
||||
<se-list-item id="linecap_butt" value="butt"><img title="Linecap: Butt" src="./images/linecap_butt.svg"
|
||||
height="22px"></img></se-list-item>
|
||||
<se-list-item id="linecap_square" value="square"><img title="Linecap: Square" src="./images/linecap_square.svg"
|
||||
height="22px"></img></se-list-item>
|
||||
<se-list-item id="linecap_round" value="round"><img title="Linecap: Round" src="./images/linecap_round.svg"
|
||||
height="22px"></img></se-list-item>
|
||||
</se-list>
|
||||
<se-spin-input size="3" id="opacity" min=0 max=100 step=5 title="Change selected item opacity"
|
||||
src="./images/opacity.svg"></se-spin-input>
|
||||
<se-palette id="palette"></se-palette>
|
||||
</div> <!-- tools_bottom -->
|
||||
`
|
||||
this.editor.$svgEditor.append(template.content.cloneNode(true));
|
||||
$id('palette').addEventListener('change', this.handlePalette.bind(this));
|
||||
const {curConfig} = this.editor.configObj;
|
||||
$id('fill_color').setPaint(new jGraduate.Paint({alpha: 100, solidColor: curConfig.initFill.color}));
|
||||
$id('stroke_color').setPaint(new jGraduate.Paint({alpha: 100, solidColor: curConfig.initStroke.color}));
|
||||
$id('zoom').addEventListener('change', (e) => this.changeZoom.bind(this)(e.detail.value));
|
||||
$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').addEventListener('change', this.handleOpacity.bind(this));
|
||||
}
|
||||
/**
|
||||
* @type {module}
|
||||
*/
|
||||
updateColorpickers (apply) {
|
||||
$id('fill_color').update(this.editor.svgCanvas, this.editor.selectedElement, apply);
|
||||
$id('stroke_color').update(this.editor.svgCanvas, this.editor.selectedElement, apply);
|
||||
}
|
||||
}
|
||||
|
||||
export default BottomPanel;
|
|
@ -1,197 +0,0 @@
|
|||
/* globals $ */
|
||||
import {jGraduate} from '../components/jgraduate/jQuery.jGraduate.js';
|
||||
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.svgCanvas;
|
||||
}
|
||||
/**
|
||||
* @type {module}
|
||||
*/
|
||||
get selectedElement () {
|
||||
return this.editor.selectedElement;
|
||||
}
|
||||
/**
|
||||
* @type {module}
|
||||
*/
|
||||
get multiselected () {
|
||||
return this.editor.multiselected;
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {module}
|
||||
*/
|
||||
changeStrokeWidth (e) {
|
||||
let val = e.target.value;
|
||||
if (val === 0 && this.selectedElement && ['line', 'polyline'].includes(this.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.scrollLeft + parseFloat(getComputedStyle(wArea, null).width.replace("px", "")) / 2) / zoom,
|
||||
y: (wArea.scrollTop + parseFloat(getComputedStyle(wArea, null).height.replace("px", "")) / 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.detail.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.bind(this)(e.detail.value));
|
||||
$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').addEventListener('change', this.handleOpacity.bind(this));
|
||||
$id('palette').addEventListener('change', this.handlePalette.bind(this));
|
||||
const {curConfig} = this.editor.configObj;
|
||||
$id('fill_color').setPaint(new jGraduate.Paint({alpha: 100, solidColor: curConfig.initFill.color}));
|
||||
$id('stroke_color').setPaint(new jGraduate.Paint({alpha: 100, solidColor: curConfig.initStroke.color}));
|
||||
}
|
||||
}
|
||||
|
||||
export default BottomPanelHandlers;
|
|
@ -1,11 +1,11 @@
|
|||
/* eslint-disable max-len */
|
||||
/* eslint-disable no-alert */
|
||||
/* globals $ */
|
||||
import SvgCanvas from '../../svgcanvas/svgcanvas.js';
|
||||
import SvgCanvas from "../../svgcanvas/svgcanvas.js";
|
||||
|
||||
const SIDEPANEL_MAXWIDTH = 300;
|
||||
const SIDEPANEL_OPENWIDTH = 150;
|
||||
const {$id} = SvgCanvas;
|
||||
const { $id } = SvgCanvas;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -14,10 +14,9 @@ class LayersPanel {
|
|||
/**
|
||||
* @param {PlainObject} editor
|
||||
*/
|
||||
constructor (editor) {
|
||||
this.svgCanvas = editor.svgCanvas;
|
||||
constructor(editor) {
|
||||
this.uiStrings = editor.uiStrings;
|
||||
this.updateContextPanel = editor.topPanelHandlers.updateContextPanel;
|
||||
this.updateContextPanel = editor.topPanel.updateContextPanel;
|
||||
this.sidedrag = -1;
|
||||
this.sidedragging = false;
|
||||
this.allowmove = false;
|
||||
|
@ -29,25 +28,37 @@ class LayersPanel {
|
|||
* @fires module:svgcanvas.SvgCanvas#event:ext_workareaResized
|
||||
* @returns {void}
|
||||
*/
|
||||
changeSidePanelWidth (delta) {
|
||||
const rulerX = document.querySelector('#ruler_x');
|
||||
$('#sidepanels').width('+=' + delta);
|
||||
$('#layerpanel').width('+=' + delta);
|
||||
rulerX.style.right = (parseFloat(getComputedStyle(rulerX, null).right.replace("px", "")) + delta) + "px";
|
||||
this.editor.workarea.style.right = (parseFloat(getComputedStyle(this.editor.workarea, null).right.replace("px", "")) + delta) + "px";
|
||||
this.svgCanvas.runExtensions('workareaResized');
|
||||
changeSidePanelWidth(delta) {
|
||||
const rulerX = document.querySelector("#ruler_x");
|
||||
$("#sidepanels").width("+=" + delta);
|
||||
$("#layerpanel").width("+=" + delta);
|
||||
rulerX.style.right =
|
||||
parseFloat(getComputedStyle(rulerX, null).right.replace("px", "")) +
|
||||
delta +
|
||||
"px";
|
||||
this.editor.workarea.style.right =
|
||||
parseFloat(
|
||||
getComputedStyle(this.editor.workarea, null).right.replace("px", "")
|
||||
) +
|
||||
delta +
|
||||
"px";
|
||||
this.editor.svgCanvas.runExtensions("workareaResized");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Event} evt
|
||||
* @returns {void}
|
||||
*/
|
||||
resizeSidePanel (evt) {
|
||||
if (!this.allowmove) { return; }
|
||||
if (this.sidedrag === -1) { return; }
|
||||
* @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();
|
||||
const sideWidth = $("#sidepanels").width();
|
||||
if (sideWidth + deltaX > SIDEPANEL_MAXWIDTH) {
|
||||
deltaX = SIDEPANEL_MAXWIDTH - sideWidth;
|
||||
// sideWidth = SIDEPANEL_MAXWIDTH;
|
||||
|
@ -55,7 +66,9 @@ class LayersPanel {
|
|||
deltaX = 2 - sideWidth;
|
||||
// sideWidth = 2;
|
||||
}
|
||||
if (deltaX === 0) { return; }
|
||||
if (deltaX === 0) {
|
||||
return;
|
||||
}
|
||||
this.sidedrag -= deltaX;
|
||||
this.changeSidePanelWidth(deltaX);
|
||||
}
|
||||
|
@ -65,11 +78,12 @@ class LayersPanel {
|
|||
* @param {boolean} close Forces the side panel closed
|
||||
* @returns {void}
|
||||
*/
|
||||
toggleSidePanel (close) {
|
||||
toggleSidePanel(close) {
|
||||
const dpr = window.devicePixelRatio || 1;
|
||||
const w = $('#sidepanels').width();
|
||||
const w = $("#sidepanels").width();
|
||||
const isOpened = (dpr < 1 ? w : w / dpr) > 2;
|
||||
const zoomAdjustedSidepanelWidth = (dpr < 1 ? 1 : dpr) * SIDEPANEL_OPENWIDTH;
|
||||
const zoomAdjustedSidepanelWidth =
|
||||
(dpr < 1 ? 1 : dpr) * SIDEPANEL_OPENWIDTH;
|
||||
const deltaX = (isOpened || close ? 0 : zoomAdjustedSidepanelWidth) - w;
|
||||
this.changeSidePanelWidth(deltaX);
|
||||
}
|
||||
|
@ -77,90 +91,147 @@ class LayersPanel {
|
|||
* @param {PlainObject} e event
|
||||
* @returns {void}
|
||||
*/
|
||||
lmenuFunc (e) {
|
||||
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;
|
||||
case "dupe":
|
||||
this.cloneLayer();
|
||||
break;
|
||||
case "delete":
|
||||
this.deleteLayer();
|
||||
break;
|
||||
case "merge_down":
|
||||
this.mergeLayer();
|
||||
break;
|
||||
case "merge_all":
|
||||
this.editor.svgCanvas.mergeAllLayers();
|
||||
this.updateContextPanel();
|
||||
this.populateLayers();
|
||||
break;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @returns {void}
|
||||
*/
|
||||
init () {
|
||||
init() {
|
||||
const template = document.createElement("template");
|
||||
template.innerHTML = `
|
||||
<div id="sidepanels">
|
||||
<div id="layerpanel">
|
||||
<h3 id="layersLabel">Layers</h3>
|
||||
<fieldset id="layerbuttons">
|
||||
<se-button id="layer_new" title="New Layer" size="small" src="./images/new.svg"></se-button>
|
||||
<se-button id="layer_delete" title="Delete Layer" size="small" src="./images/delete.svg"></se-button>
|
||||
<se-button id="layer_rename" title="Rename Layer" size="small" src="./images/text.svg"></se-button>
|
||||
<se-button id="layer_up" title="Move Layer Up" size="small" src="./images/go_up.svg"></se-button>
|
||||
<se-button id="layer_down" title="Move Layer Down" size="small" src="./images/go_down.svg"></se-button>
|
||||
<se-button id="layer_moreopts" title="More Options" size="small" src="./images/context_menu.svg">
|
||||
</se-button>
|
||||
</fieldset>
|
||||
<table id="layerlist">
|
||||
<tr class="layer">
|
||||
<td class="layervis"></td>
|
||||
<td class="layername">Layer 1</td>
|
||||
</tr>
|
||||
</table>
|
||||
<span id="selLayerLabel">Move elements to:</span>
|
||||
<select id="selLayerNames" title="Move selected elements to a different layer" disabled="disabled">
|
||||
<option selected="selected" value="layer1">Layer 1</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="sidepanel_handle" title="Drag left/right to resize side panel [X]">L a y e r s
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
this.editor.$svgEditor.append(template.content.cloneNode(true));
|
||||
this.editor.svgCanvas = this.editor.svgCanvas;
|
||||
// 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);
|
||||
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);
|
||||
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) => {
|
||||
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));
|
||||
$id("sidepanel_handle").addEventListener(
|
||||
"click",
|
||||
this.toggleSidePanel.bind(this)
|
||||
);
|
||||
if (this.editor.configObj.curConfig.showlayers) {
|
||||
this.toggleSidePanel();
|
||||
}
|
||||
$id('sidepanel_handle').addEventListener('mousedown', (evt) => {
|
||||
$id("sidepanel_handle").addEventListener("mousedown", evt => {
|
||||
this.sidedrag = evt.pageX;
|
||||
window.addEventListener('mousemove', this.resizeSidePanel.bind(this));
|
||||
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(); }
|
||||
$id("sidepanel_handle").addEventListener("mouseup", evt => {
|
||||
if (!this.sidedragging) {
|
||||
this.toggleSidePanel();
|
||||
}
|
||||
this.sidedrag = -1;
|
||||
this.sidedragging = false;
|
||||
});
|
||||
window.addEventListener('mouseup', (evt) => {
|
||||
window.addEventListener("mouseup", evt => {
|
||||
this.sidedrag = -1;
|
||||
this.sidedragging = false;
|
||||
$id('svg_editor').removeEventListener('mousemove', this.resizeSidePanel.bind(this));
|
||||
$id("svg_editor").removeEventListener(
|
||||
"mousemove",
|
||||
this.resizeSidePanel.bind(this)
|
||||
);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @returns {void}
|
||||
*/
|
||||
newLayer () {
|
||||
newLayer() {
|
||||
let uniqName;
|
||||
let i = this.svgCanvas.getCurrentDrawing().getNumLayers();
|
||||
let i = this.editor.svgCanvas.getCurrentDrawing().getNumLayers();
|
||||
do {
|
||||
uniqName = this.uiStrings.layers.layer + ' ' + (++i);
|
||||
} while (this.svgCanvas.getCurrentDrawing().hasLayer(uniqName));
|
||||
uniqName = this.uiStrings.layers.layer + " " + ++i;
|
||||
} while (this.editor.svgCanvas.getCurrentDrawing().hasLayer(uniqName));
|
||||
|
||||
const newName = prompt(this.uiStrings.notification.enterUniqueLayerName, uniqName);
|
||||
if (!newName) { return; }
|
||||
if (this.svgCanvas.getCurrentDrawing().hasLayer(newName)) {
|
||||
const newName = prompt(
|
||||
this.uiStrings.notification.enterUniqueLayerName,
|
||||
uniqName
|
||||
);
|
||||
if (!newName) {
|
||||
return;
|
||||
}
|
||||
if (this.editor.svgCanvas.getCurrentDrawing().hasLayer(newName)) {
|
||||
alert(this.uiStrings.notification.dupeLayerName);
|
||||
return;
|
||||
}
|
||||
this.svgCanvas.createLayer(newName);
|
||||
this.editor.svgCanvas.createLayer(newName);
|
||||
this.updateContextPanel();
|
||||
this.populateLayers();
|
||||
}
|
||||
|
@ -169,15 +240,15 @@ class LayersPanel {
|
|||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
deleteLayer () {
|
||||
if (this.svgCanvas.deleteCurrentLayer()) {
|
||||
deleteLayer() {
|
||||
if (this.editor.svgCanvas.deleteCurrentLayer()) {
|
||||
this.updateContextPanel();
|
||||
this.populateLayers();
|
||||
// This matches what this.svgCanvas does
|
||||
// This matches what this.editor.svgCanvas does
|
||||
// TODO: make this behavior less brittle (svg-editor should get which
|
||||
// layer is selected from the canvas and then select that one in the UI)
|
||||
$('#layerlist tr.layer').removeClass('layersel');
|
||||
$('#layerlist tr.layer:first').addClass('layersel');
|
||||
$("#layerlist tr.layer").removeClass("layersel");
|
||||
$("#layerlist tr.layer:first").addClass("layersel");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,16 +256,22 @@ class LayersPanel {
|
|||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
cloneLayer () {
|
||||
const name = this.svgCanvas.getCurrentDrawing().getCurrentLayerName() + ' copy';
|
||||
cloneLayer() {
|
||||
const name =
|
||||
this.editor.svgCanvas.getCurrentDrawing().getCurrentLayerName() + " copy";
|
||||
|
||||
const newName = prompt(this.uiStrings.notification.enterUniqueLayerName, name);
|
||||
if (!newName) { return; }
|
||||
if (this.svgCanvas.getCurrentDrawing().hasLayer(newName)) {
|
||||
const newName = prompt(
|
||||
this.uiStrings.notification.enterUniqueLayerName,
|
||||
name
|
||||
);
|
||||
if (!newName) {
|
||||
return;
|
||||
}
|
||||
if (this.editor.svgCanvas.getCurrentDrawing().hasLayer(newName)) {
|
||||
alert(this.uiStrings.notification.dupeLayerName);
|
||||
return;
|
||||
}
|
||||
this.svgCanvas.cloneLayer(newName);
|
||||
this.editor.svgCanvas.cloneLayer(newName);
|
||||
this.updateContextPanel();
|
||||
this.populateLayers();
|
||||
}
|
||||
|
@ -203,11 +280,14 @@ class LayersPanel {
|
|||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
mergeLayer () {
|
||||
if ($('#layerlist tr.layersel').index() === this.svgCanvas.getCurrentDrawing().getNumLayers() - 1) {
|
||||
mergeLayer() {
|
||||
if (
|
||||
$("#layerlist tr.layersel").index() ===
|
||||
this.editor.svgCanvas.getCurrentDrawing().getNumLayers() - 1
|
||||
) {
|
||||
return;
|
||||
}
|
||||
this.svgCanvas.mergeLayer();
|
||||
this.editor.svgCanvas.mergeLayer();
|
||||
this.updateContextPanel();
|
||||
this.populateLayers();
|
||||
}
|
||||
|
@ -216,13 +296,13 @@ class LayersPanel {
|
|||
* @param {Integer} pos
|
||||
* @returns {void}
|
||||
*/
|
||||
moveLayer (pos) {
|
||||
const total = this.svgCanvas.getCurrentDrawing().getNumLayers();
|
||||
moveLayer(pos) {
|
||||
const total = this.editor.svgCanvas.getCurrentDrawing().getNumLayers();
|
||||
|
||||
let curIndex = $('#layerlist tr.layersel').index();
|
||||
let curIndex = $("#layerlist tr.layersel").index();
|
||||
if (curIndex > 0 || curIndex < total - 1) {
|
||||
curIndex += pos;
|
||||
this.svgCanvas.setCurrentLayerPosition(total - curIndex - 1);
|
||||
this.editor.svgCanvas.setCurrentLayerPosition(total - curIndex - 1);
|
||||
this.populateLayers();
|
||||
}
|
||||
}
|
||||
|
@ -230,16 +310,21 @@ class LayersPanel {
|
|||
/**
|
||||
* @returns {void}
|
||||
*/
|
||||
layerRename () {
|
||||
// const curIndex = $('#layerlist tr.layersel').prevAll().length; // Currently unused
|
||||
const oldName = $('#layerlist tr.layersel td.layername').text();
|
||||
const newName = prompt(this.uiStrings.notification.enterNewLayerName, '');
|
||||
if (!newName) { return; }
|
||||
if (oldName === newName || this.svgCanvas.getCurrentDrawing().hasLayer(newName)) {
|
||||
layerRename() {
|
||||
// const curIndex = $('#layerlist tr.layersel').prevAll().length; // Currently unused
|
||||
const oldName = $("#layerlist tr.layersel td.layername").text();
|
||||
const newName = prompt(this.uiStrings.notification.enterNewLayerName, "");
|
||||
if (!newName) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
oldName === newName ||
|
||||
this.editor.svgCanvas.getCurrentDrawing().hasLayer(newName)
|
||||
) {
|
||||
alert(this.uiStrings.notification.layerHasThatName);
|
||||
return;
|
||||
}
|
||||
this.svgCanvas.renameCurrentLayer(newName);
|
||||
this.editor.svgCanvas.renameCurrentLayer(newName);
|
||||
this.populateLayers();
|
||||
}
|
||||
|
||||
|
@ -248,72 +333,86 @@ class LayersPanel {
|
|||
* If no layer is passed in, this function restores the other layers.
|
||||
* @param {string} [layerNameToHighlight]
|
||||
* @returns {void}
|
||||
*/
|
||||
toggleHighlightLayer (layerNameToHighlight) {
|
||||
*/
|
||||
toggleHighlightLayer(layerNameToHighlight) {
|
||||
let i;
|
||||
const curNames = [], numLayers = this.svgCanvas.getCurrentDrawing().getNumLayers();
|
||||
const curNames = [],
|
||||
numLayers = this.editor.svgCanvas.getCurrentDrawing().getNumLayers();
|
||||
for (i = 0; i < numLayers; i++) {
|
||||
curNames[i] = this.svgCanvas.getCurrentDrawing().getLayerName(i);
|
||||
curNames[i] = this.editor.svgCanvas.getCurrentDrawing().getLayerName(i);
|
||||
}
|
||||
|
||||
if (layerNameToHighlight) {
|
||||
curNames.forEach((curName) => {
|
||||
curNames.forEach(curName => {
|
||||
if (curName !== layerNameToHighlight) {
|
||||
this.svgCanvas.getCurrentDrawing().setLayerOpacity(curName, 0.5);
|
||||
this.editor.svgCanvas
|
||||
.getCurrentDrawing()
|
||||
.setLayerOpacity(curName, 0.5);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
curNames.forEach((curName) => {
|
||||
this.svgCanvas.getCurrentDrawing().setLayerOpacity(curName, 1.0);
|
||||
curNames.forEach(curName => {
|
||||
this.editor.svgCanvas.getCurrentDrawing().setLayerOpacity(curName, 1.0);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {void}
|
||||
*/
|
||||
populateLayers () {
|
||||
this.svgCanvas.clearSelection();
|
||||
const layerlist = $('#layerlist tbody').empty();
|
||||
const selLayerNames = $('#selLayerNames').empty();
|
||||
const drawing = this.svgCanvas.getCurrentDrawing();
|
||||
* @returns {void}
|
||||
*/
|
||||
populateLayers() {
|
||||
this.editor.svgCanvas.clearSelection();
|
||||
const layerlist = $("#layerlist tbody").empty();
|
||||
const selLayerNames = $("#selLayerNames").empty();
|
||||
const drawing = this.editor.svgCanvas.getCurrentDrawing();
|
||||
const currentLayerName = drawing.getCurrentLayerName();
|
||||
let layer = this.svgCanvas.getCurrentDrawing().getNumLayers();
|
||||
let layer = this.editor.svgCanvas.getCurrentDrawing().getNumLayers();
|
||||
// we get the layers in the reverse z-order (the layer rendered on top is listed first)
|
||||
while (layer--) {
|
||||
const name = drawing.getLayerName(layer);
|
||||
const layerTr = $('<tr class="layer">').toggleClass('layersel', name === currentLayerName);
|
||||
const layerVis = $('<td class="layervis">').toggleClass('layerinvis', !drawing.getLayerVisibility(name));
|
||||
const layerName = $('<td class="layername">' + name + '</td>');
|
||||
const layerTr = $('<tr class="layer">').toggleClass(
|
||||
"layersel",
|
||||
name === currentLayerName
|
||||
);
|
||||
const layerVis = $('<td class="layervis">').toggleClass(
|
||||
"layerinvis",
|
||||
!drawing.getLayerVisibility(name)
|
||||
);
|
||||
const layerName = $('<td class="layername">' + name + "</td>");
|
||||
layerlist.append(layerTr.append(layerVis, layerName));
|
||||
selLayerNames.append('<option value="' + name + '">' + name + '</option>');
|
||||
selLayerNames.append(
|
||||
'<option value="' + name + '">' + name + "</option>"
|
||||
);
|
||||
}
|
||||
// handle selection of layer
|
||||
$('#layerlist td.layername')
|
||||
.mouseup((evt) => {
|
||||
$('#layerlist tr.layer').removeClass('layersel');
|
||||
$(evt.currentTarget.parentNode).addClass('layersel');
|
||||
this.svgCanvas.setCurrentLayer(evt.currentTarget.textContent);
|
||||
$("#layerlist td.layername")
|
||||
.mouseup(evt => {
|
||||
$("#layerlist tr.layer").removeClass("layersel");
|
||||
$(evt.currentTarget.parentNode).addClass("layersel");
|
||||
this.editor.svgCanvas.setCurrentLayer(evt.currentTarget.textContent);
|
||||
evt.preventDefault();
|
||||
})
|
||||
.mouseover((evt) => {
|
||||
this.toggleHighlightLayer(this.svgCanvas, evt.currentTarget.textContent);
|
||||
.mouseover(evt => {
|
||||
this.toggleHighlightLayer(
|
||||
this.editor.svgCanvas,
|
||||
evt.currentTarget.textContent
|
||||
);
|
||||
})
|
||||
.mouseout(() => {
|
||||
this.toggleHighlightLayer(this.svgCanvas);
|
||||
this.toggleHighlightLayer(this.editor.svgCanvas);
|
||||
});
|
||||
$('#layerlist td.layervis').click((evt) => {
|
||||
$("#layerlist td.layervis").click(evt => {
|
||||
const row = $(evt.currentTarget.parentNode).prevAll().length;
|
||||
const name = $('#layerlist tr.layer:eq(' + row + ') td.layername').text();
|
||||
const vis = $(evt.currentTarget).hasClass('layerinvis');
|
||||
this.svgCanvas.setLayerVisibility(name, vis);
|
||||
$(evt.currentTarget).toggleClass('layerinvis');
|
||||
const name = $("#layerlist tr.layer:eq(" + row + ") td.layername").text();
|
||||
const vis = $(evt.currentTarget).hasClass("layerinvis");
|
||||
this.editor.svgCanvas.setLayerVisibility(name, vis);
|
||||
$(evt.currentTarget).toggleClass("layerinvis");
|
||||
});
|
||||
|
||||
// if there were too few rows, let's add a few to make it not so lonely
|
||||
let num = 5 - $('#layerlist tr.layer').size();
|
||||
let num = 5 - $("#layerlist tr.layer").size();
|
||||
while (num-- > 0) {
|
||||
// TODO: there must a better way to do this
|
||||
// TODO: there must a better way to do this
|
||||
layerlist.append('<tr><td style="color:white">_</td><td/></tr>');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,253 @@
|
|||
import SvgCanvas from "../../svgcanvas/svgcanvas.js";
|
||||
|
||||
const { $id, $qa } = SvgCanvas;
|
||||
|
||||
/*
|
||||
* register actions for left panel
|
||||
*/
|
||||
/**
|
||||
* @type {module}
|
||||
*/
|
||||
class LeftPanel {
|
||||
/**
|
||||
* @param {PlainObject} editor svgedit handler
|
||||
*/
|
||||
constructor(editor) {
|
||||
this.editor = editor;
|
||||
}
|
||||
/**
|
||||
* 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.style.cursor = "auto";
|
||||
this.editor.svgCanvas.setMode("select");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
clickFHPath() {
|
||||
if (this.updateLeftPanel("tool_fhpath")) {
|
||||
this.editor.svgCanvas.setMode("fhpath");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
clickLine() {
|
||||
if (this.updateLeftPanel("tool_line")) {
|
||||
this.editor.svgCanvas.setMode("line");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
clickSquare() {
|
||||
if (this.updateLeftPanel("tool_square")) {
|
||||
this.editor.svgCanvas.setMode("square");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
clickRect() {
|
||||
if (this.updateLeftPanel("tool_rect")) {
|
||||
this.editor.svgCanvas.setMode("rect");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
clickFHRect() {
|
||||
if (this.updateLeftPanel("tool_fhrect")) {
|
||||
this.editor.svgCanvas.setMode("fhrect");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
clickCircle() {
|
||||
if (this.updateLeftPanel("tool_circle")) {
|
||||
this.editor.svgCanvas.setMode("circle");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
clickEllipse() {
|
||||
if (this.updateLeftPanel("tool_ellipse")) {
|
||||
this.editor.svgCanvas.setMode("ellipse");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
clickFHEllipse() {
|
||||
if (this.updateLeftPanel("tool_fhellipse")) {
|
||||
this.editor.svgCanvas.setMode("fhellipse");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
clickImage() {
|
||||
if (this.updateLeftPanel("tool_image")) {
|
||||
this.editor.svgCanvas.setMode("image");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
clickZoom() {
|
||||
if (this.updateLeftPanel("tool_zoom")) {
|
||||
this.editor.svgCanvas.setMode("zoom");
|
||||
this.editor.workarea.style.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.editor.svgCanvas.setMode("text");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
clickPath() {
|
||||
if (this.updateLeftPanel("tool_path")) {
|
||||
this.editor.svgCanvas.setMode("path");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @type {module}
|
||||
*/
|
||||
add(id, handler) {
|
||||
$id(id).addEventListener("click", () => {
|
||||
if (this.updateLeftPanel(id)) {
|
||||
handler();
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @type {module}
|
||||
*/
|
||||
init() {
|
||||
// add Left panel
|
||||
const template = document.createElement("template");
|
||||
template.innerHTML = `
|
||||
<div id="tools_left">
|
||||
<se-button id="tool_select" title="Select Tool" src="./images/select.svg"></se-button>
|
||||
<se-button id="tool_zoom" title="Zoom Tool" src="./images/zoom.svg" shortcut="Z"></se-button>
|
||||
<se-button id="ext-panning" title="Panning" src="./images/panning.svg"></se-button>
|
||||
<se-button id="tool_fhpath" title="Pencil Tool" src="./images/pencil.svg" shortcut="Q"></se-button>
|
||||
<se-button id="tool_line" title="Line Tool" src="./images/pen.svg" shortcut="L"></se-button>
|
||||
<se-button id="tool_path" title="Path Tool" src="./images/path.svg" shortcut="P"></se-button>
|
||||
<se-flyingbutton id="tools_rect" title="Square/Rect Tool">
|
||||
<se-button id="tool_rect" title="Rectangle" src="./images/rect.svg" shortcut="R"></se-button>
|
||||
<se-button id="tool_square" title="Square" src="./images/square.svg"></se-button>
|
||||
<se-button id="tool_fhrect" title="Free-Hand Rectangle" src="./images/fh_rect.svg"></se-button>
|
||||
</se-flyingbutton>
|
||||
<se-flyingbutton id="tools_ellipse" title="Ellipse/Circle Tool">
|
||||
<se-button id="tool_ellipse" title="Rectangle" src="./images/ellipse.svg" shortcut="E"></se-button>
|
||||
<se-button id="tool_circle" title="Square" src="./images/circle.svg"></se-button>
|
||||
<se-button id="tool_fhellipse" title="Free-Hand Rectangle" src="./images/fh_ellipse.svg"></se-button>
|
||||
</se-flyingbutton>
|
||||
<se-flyingbutton id="tools_polygon" title="Polygone/Star Tool">
|
||||
<se-button id="tool_polygon" title="Polygon Tool" src="./images/polygon.svg"></se-button>
|
||||
<se-button id="tool_star" title="Star Tool" src="./images/star.svg"></se-button>
|
||||
</se-flyingbutton>
|
||||
<se-button id="mode_connect" title="Connect two objects" src="./images/conn.svg"></se-button>
|
||||
<se-button id="tool_text" title="Text Tool" src="./images/text.svg" shortcut="T"></se-button>
|
||||
<se-button id="tool_image" title="Image Tool" src="./images/image.svg"></se-button>
|
||||
<se-button id="tool_eyedropper" title="Eye Dropper Tool" src="./images/eye_dropper.svg" shortcut="I"></se-button>
|
||||
<se-explorerbutton id="tool_shapelib" title="Shape library" lib="./extensions/ext-shapes/shapelib/"
|
||||
src="./images/shapelib.svg"></se-explorerbutton>
|
||||
</div> <!-- tools_left -->
|
||||
`;
|
||||
this.editor.$svgEditor.append(template.content.cloneNode(true));
|
||||
// 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 LeftPanel;
|
|
@ -1,216 +0,0 @@
|
|||
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.svgCanvas;
|
||||
}
|
||||
/**
|
||||
* 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.style.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.style.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;
|
File diff suppressed because it is too large
Load Diff
|
@ -1,645 +0,0 @@
|
|||
/* 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.svgCanvas;
|
||||
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.configObj.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-block');
|
||||
$('#tool_font_size').css('display', 'inline');
|
||||
$id('tool_italic').pressed = this.svgCanvas.getItalic();
|
||||
$id('tool_bold').pressed = this.svgCanvas.getBold();
|
||||
$('#tool_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.svgCanvas.undoMgr.getUndoStackSize() === 0);
|
||||
$id('tool_redo').disabled = (this.svgCanvas.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.classList.toggle('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.svgCanvas;
|
||||
if (undoMgr.getUndoStackSize() > 0) {
|
||||
undoMgr.undo();
|
||||
this.editor.layersPanel.populateLayers();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
clickRedo () {
|
||||
const {undoMgr} = this.editor.svgCanvas;
|
||||
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 {PlainObject} evt
|
||||
* @returns {void}
|
||||
*/
|
||||
clickAlignEle (evt) {
|
||||
this.svgCanvas.alignSelectedElements(evt.detail.value, 'page');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} pos indicate the alignment relative to top, bottom, middle etc..
|
||||
* @returns {void}
|
||||
*/
|
||||
clickAlign (pos) {
|
||||
let value = $('#tool_align_relative').val();
|
||||
if(value === ''){
|
||||
value = 'selected';
|
||||
}
|
||||
this.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.uiStrings.notification.invalidAttrValGiven);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (attr !== 'id' && attr !== 'class') {
|
||||
if (isNaN(val)) {
|
||||
val = this.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.selectedElement[attr] || this.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.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_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('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;
|
Loading…
Reference in New Issue