diff --git a/cypress/integration/unit/coords.js b/cypress/integration/unit/coords.js index 42f66334..bee9e241 100644 --- a/cypress/integration/unit/coords.js +++ b/cypress/integration/unit/coords.js @@ -27,7 +27,7 @@ describe('coords', function () { * @implements {module:utilities.EditorContext} */ { - getSVGRoot: () => { return this.svg; }, + getSvgRoot: () => { return this.svg; }, getDOMDocument () { return null; }, getDOMContainer () { return null; } } diff --git a/cypress/integration/unit/draw.js b/cypress/integration/unit/draw.js index 507c67be..17fb5850 100644 --- a/cypress/integration/unit/draw.js +++ b/cypress/integration/unit/draw.js @@ -138,8 +138,8 @@ describe('draw.Drawing', function () { svgN.setAttributeNS(NS.XMLNS, 'xmlns:se', NS.SE); svgN.setAttributeNS(NS.SE, 'se:nonce', NONCE); - const svgcontent = document.createElementNS(NS.SVG, 'svg'); - currentDrawing_ = new draw.Drawing(svgcontent, idprefix); + const svgContent = document.createElementNS(NS.SVG, 'svg'); + currentDrawing_ = new draw.Drawing(svgContent, idprefix); }); it('Test draw module', function () { diff --git a/cypress/integration/unit/path.js b/cypress/integration/unit/path.js index 36572008..56ac516e 100644 --- a/cypress/integration/unit/path.js +++ b/cypress/integration/unit/path.js @@ -27,8 +27,8 @@ describe('path', function () { * @implements {module:path.EditorContext} */ { - getSVGRoot () { return svg; }, - getCurrentZoom () { return 1; } + getSvgRoot () { return svg; }, + getZoom () { return 1; } }, /** * @implements {module:utilities.EditorContext} @@ -36,7 +36,7 @@ describe('path', function () { { getDOMDocument () { return svg; }, getDOMContainer () { return svg; }, - getSVGRoot () { return svg; } + getSvgRoot () { return svg; } } ]; } diff --git a/cypress/integration/unit/recalculate.js b/cypress/integration/unit/recalculate.js index 7531e488..28290aeb 100644 --- a/cypress/integration/unit/recalculate.js +++ b/cypress/integration/unit/recalculate.js @@ -50,7 +50,7 @@ describe('recalculate', function () { * @implements {module:utilities.EditorContext} */ { - getSVGRoot() { return svg; }, + getSvgRoot() { return svg; }, getDOMDocument() { return null; }, getDOMContainer() { return null; }, getDataStorage() { return dataStorage; } @@ -75,7 +75,7 @@ describe('recalculate', function () { * @implements {module:recalculate.EditorContext} */ { - getSVGRoot() { return svg; }, + getSvgRoot() { return svg; }, getStartTransform() { return ''; }, setStartTransform() { /* empty fn */ }, getDataStorage() { return dataStorage; } diff --git a/cypress/integration/unit/select.js b/cypress/integration/unit/select.js index 1fc91ba5..bd37c9fd 100644 --- a/cypress/integration/unit/select.js +++ b/cypress/integration/unit/select.js @@ -6,7 +6,7 @@ describe('select', function () { sandbox.id = 'sandbox'; let svgroot; - let svgcontent; + let svgContent; const mockConfig = { dimensions: [ 640, 480 ] }; @@ -45,7 +45,7 @@ describe('select', function () { return elem; }, svgRoot () { return svgroot; }, - svgContent () { return svgcontent; }, + svgContent () { return svgContent; }, getDataStorage () { return dataStorage; } }; @@ -58,13 +58,13 @@ describe('select', function () { element: 'svg', attr: { id: 'svgroot' } }); - svgcontent = mockFactory.createSVGElement({ + svgContent = mockFactory.createSVGElement({ element: 'svg', attr: { id: 'svgcontent' } }); - svgroot.append(svgcontent); - /* const rect = */ svgcontent.append( + svgroot.append(svgContent); + /* const rect = */ svgContent.append( mockFactory.createSVGElement({ element: 'rect', attr: { @@ -114,7 +114,7 @@ describe('select', function () { // Verify non-existence of Selector DOM nodes assert.equal(svgroot.childNodes.length, 1); - assert.equal(svgroot.childNodes.item(0), svgcontent); + assert.equal(svgroot.childNodes.item(0), svgContent); assert.ok(!svgroot.querySelector('#selectorParentGroup')); select.init(mockConfig, mockFactory); @@ -127,7 +127,7 @@ describe('select', function () { assert.equal(cb.id, 'canvasBackground'); assert.ok(svgroot.childNodes.item(1)); - assert.equal(svgroot.childNodes.item(1), svgcontent); + assert.equal(svgroot.childNodes.item(1), svgContent); // Verify existence of selectorParentGroup. const spg = svgroot.childNodes.item(2); diff --git a/cypress/integration/unit/test1.js b/cypress/integration/unit/test1.js index cba8bf26..1d4e05e2 100644 --- a/cypress/integration/unit/test1.js +++ b/cypress/integration/unit/test1.js @@ -208,10 +208,10 @@ describe('Basic Module', function () { '' ); - const svgcontent = document.getElementById('svgcontent'); - const circles = svgcontent.getElementsByTagNameNS(svgns, 'circle'); - const rects = svgcontent.getElementsByTagNameNS(svgns, 'rect'); - const ellipses = svgcontent.getElementsByTagNameNS(svgns, 'ellipse'); + const svgContent = document.getElementById('svgcontent'); + const circles = svgContent.getElementsByTagNameNS(svgns, 'circle'); + const rects = svgContent.getElementsByTagNameNS(svgns, 'rect'); + const ellipses = svgContent.getElementsByTagNameNS(svgns, 'ellipse'); assert.equal(circles.length, 2, 'Found two circles upon importing'); assert.equal(rects.length, 1, 'Found one rectangle upon importing'); assert.equal(ellipses.length, 1, 'Found one ellipse upon importing'); @@ -242,13 +242,13 @@ describe('Basic Module', function () { '' ); - const svgcontent = document.getElementById('svgcontent'); - const circles = svgcontent.getElementsByTagNameNS(svgns, 'circle'); - const rects = svgcontent.getElementsByTagNameNS(svgns, 'rect'); - // ellipses = svgcontent.getElementsByTagNameNS(svgns, 'ellipse'), - const defs = svgcontent.getElementsByTagNameNS(svgns, 'defs'); - // grads = svgcontent.getElementsByTagNameNS(svgns, 'linearGradient'), - const uses = svgcontent.getElementsByTagNameNS(svgns, 'use'); + const svgContent = document.getElementById('svgcontent'); + const circles = svgContent.getElementsByTagNameNS(svgns, 'circle'); + const rects = svgContent.getElementsByTagNameNS(svgns, 'rect'); + // ellipses = svgContent.getElementsByTagNameNS(svgns, 'ellipse'), + const defs = svgContent.getElementsByTagNameNS(svgns, 'defs'); + // grads = svgContent.getElementsByTagNameNS(svgns, 'linearGradient'), + const uses = svgContent.getElementsByTagNameNS(svgns, 'use'); assert.notEqual(circles.item(0).id, 'svg_1', 'Circle not re-identified'); assert.notEqual(rects.item(0).id, 'svg_3', 'Rectangle not re-identified'); // TODO: determine why this test fails in WebKit browsers diff --git a/cypress/integration/unit/utilities-bbox.js b/cypress/integration/unit/utilities-bbox.js index 11e7a757..68ac4511 100644 --- a/cypress/integration/unit/utilities-bbox.js +++ b/cypress/integration/unit/utilities-bbox.js @@ -21,17 +21,17 @@ describe('utilities bbox', function () { }); return elem; } - let mockaddSVGElementFromJsonCallCount = 0; + let mockaddSVGElemensFromJsonCallCount = 0; /** - * Mock of {@link module:utilities.EditorContext#addSVGElementFromJson}. + * Mock of {@link module:utilities.EditorContext#addSVGElemensFromJson}. * @param {module:utilities.SVGElementJSON} json * @returns {SVGElement} */ - function mockaddSVGElementFromJson (json) { + function mockaddSVGElemensFromJson (json) { const elem = mockCreateSVGElement(json); svgroot.append(elem); - mockaddSVGElementFromJsonCallCount++; + mockaddSVGElemensFromJsonCallCount++; return elem; } const mockPathActions = { @@ -83,7 +83,7 @@ describe('utilities bbox', function () { sandbox.append(svgroot); path.init(null); - mockaddSVGElementFromJsonCallCount = 0; + mockaddSVGElemensFromJsonCallCount = 0; }); it('Test svgedit.utilities package', function () { @@ -102,9 +102,9 @@ describe('utilities bbox', function () { attr: { id: 'path', d: 'M0,1 L2,3' } }); svgroot.append(elem); - let bbox = getBBoxWithTransform(elem, mockaddSVGElementFromJson, mockPathActions); + let bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions); assert.deepEqual(bbox, { x: 0, y: 1, width: 2, height: 2 }); - assert.equal(mockaddSVGElementFromJsonCallCount, 0); + assert.equal(mockaddSVGElemensFromJsonCallCount, 0); elem.remove(); elem = mockCreateSVGElement({ @@ -112,9 +112,9 @@ describe('utilities bbox', function () { attr: { id: 'rect', x: '0', y: '1', width: '5', height: '10' } }); svgroot.append(elem); - bbox = getBBoxWithTransform(elem, mockaddSVGElementFromJson, mockPathActions); + bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions); assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 10 }); - assert.equal(mockaddSVGElementFromJsonCallCount, 0); + assert.equal(mockaddSVGElemensFromJsonCallCount, 0); elem.remove(); elem = mockCreateSVGElement({ @@ -122,9 +122,9 @@ describe('utilities bbox', function () { attr: { id: 'line', x1: '0', y1: '1', x2: '5', y2: '6' } }); svgroot.append(elem); - bbox = getBBoxWithTransform(elem, mockaddSVGElementFromJson, mockPathActions); + bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions); assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 5 }); - assert.equal(mockaddSVGElementFromJsonCallCount, 0); + assert.equal(mockaddSVGElemensFromJsonCallCount, 0); elem.remove(); elem = mockCreateSVGElement({ @@ -137,9 +137,9 @@ describe('utilities bbox', function () { }); g.append(elem); svgroot.append(g); - bbox = getBBoxWithTransform(elem, mockaddSVGElementFromJson, mockPathActions); + bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions); assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 10 }); - assert.equal(mockaddSVGElementFromJsonCallCount, 0); + assert.equal(mockaddSVGElemensFromJsonCallCount, 0); g.remove(); }); @@ -151,7 +151,7 @@ describe('utilities bbox', function () { attr: { id: 'path', d: 'M10,10 L20,20', transform: 'rotate(45 10,10)' } }); svgroot.append(elem); - let bbox = getBBoxWithTransform(elem, mockaddSVGElementFromJson, mockPathActions); + let bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions); assert.close(bbox.x, 10, EPSILON); assert.close(bbox.y, 10, EPSILON); assert.close(bbox.width, 0, EPSILON); @@ -163,12 +163,12 @@ describe('utilities bbox', function () { attr: { id: 'rect', x: '10', y: '10', width: '10', height: '20', transform: 'rotate(90 15,20)' } }); svgroot.append(elem); - bbox = getBBoxWithTransform(elem, mockaddSVGElementFromJson, mockPathActions); + bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions); assert.close(bbox.x, 5, EPSILON); assert.close(bbox.y, 15, EPSILON); assert.close(bbox.width, 20, EPSILON); assert.close(bbox.height, 10, EPSILON); - assert.equal(mockaddSVGElementFromJsonCallCount, 1); + assert.equal(mockaddSVGElemensFromJsonCallCount, 1); elem.remove(); const rect = { x: 10, y: 10, width: 10, height: 20 }; @@ -179,14 +179,14 @@ describe('utilities bbox', function () { attr: { id: 'rect2', x: rect.x, y: rect.y, width: rect.width, height: rect.height, transform: 'rotate(' + angle + ' ' + origin.x + ',' + origin.y + ')' } }); svgroot.append(elem); - mockaddSVGElementFromJsonCallCount = 0; - bbox = getBBoxWithTransform(elem, mockaddSVGElementFromJson, mockPathActions); + mockaddSVGElemensFromJsonCallCount = 0; + bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions); const r2 = rotateRect(rect, angle, origin); assert.close(bbox.x, r2.x, EPSILON, 'rect2 x is ' + r2.x); assert.close(bbox.y, r2.y, EPSILON, 'rect2 y is ' + r2.y); assert.close(bbox.width, r2.width, EPSILON, 'rect2 width is' + r2.width); assert.close(bbox.height, r2.height, EPSILON, 'rect2 height is ' + r2.height); - assert.equal(mockaddSVGElementFromJsonCallCount, 0); + assert.equal(mockaddSVGElemensFromJsonCallCount, 0); elem.remove(); // Same as previous but wrapped with g and the transform is with the g. @@ -200,13 +200,13 @@ describe('utilities bbox', function () { }); g.append(elem); svgroot.append(g); - mockaddSVGElementFromJsonCallCount = 0; - bbox = getBBoxWithTransform(g, mockaddSVGElementFromJson, mockPathActions); + mockaddSVGElemensFromJsonCallCount = 0; + bbox = getBBoxWithTransform(g, mockaddSVGElemensFromJson, mockPathActions); assert.close(bbox.x, r2.x, EPSILON, 'rect2 x is ' + r2.x); assert.close(bbox.y, r2.y, EPSILON, 'rect2 y is ' + r2.y); assert.close(bbox.width, r2.width, EPSILON, 'rect2 width is' + r2.width); assert.close(bbox.height, r2.height, EPSILON, 'rect2 height is ' + r2.height); - assert.equal(mockaddSVGElementFromJsonCallCount, 0); + assert.equal(mockaddSVGElemensFromJsonCallCount, 0); g.remove(); elem = mockCreateSVGElement({ @@ -214,14 +214,14 @@ describe('utilities bbox', function () { attr: { id: 'ellipse1', cx: '100', cy: '100', rx: '50', ry: '50', transform: 'rotate(45 100,100)' } }); svgroot.append(elem); - mockaddSVGElementFromJsonCallCount = 0; - bbox = getBBoxWithTransform(elem, mockaddSVGElementFromJson, mockPathActions); + mockaddSVGElemensFromJsonCallCount = 0; + bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions); /** @todo: Review these test the BBox algorithm is using the bezier control points to calculate the bounding box. Should be 50, 50, 100, 100. */ // assert.ok(bbox.x > 45 && bbox.x <= 50); assert.ok(bbox.y > 45 && bbox.y <= 50); // assert.ok(bbox.width >= 100 && bbox.width < 110); // assert.ok(bbox.height >= 100 && bbox.height < 110); - assert.equal(mockaddSVGElementFromJsonCallCount, 1); + assert.equal(mockaddSVGElemensFromJsonCallCount, 1); elem.remove(); }); @@ -238,7 +238,7 @@ describe('utilities bbox', function () { attr: { id: 'path', d: 'M10,10 L20,20', transform: 'rotate(45 10,10) ' + matrix } }); svgroot.append(elem); - let bbox = getBBoxWithTransform(elem, mockaddSVGElementFromJson, mockPathActions); + let bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions); assert.close(bbox.x, 10 + tx, EPSILON); assert.close(bbox.y, 10 + ty, EPSILON); assert.close(bbox.width, 0, EPSILON); @@ -253,7 +253,7 @@ describe('utilities bbox', function () { attr: { id: 'rect', x: '10', y: '10', width: '10', height: '20', transform: 'rotate(90 15,20) ' + matrix } }); svgroot.append(elem); - bbox = getBBoxWithTransform(elem, mockaddSVGElementFromJson, mockPathActions); + bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions); assert.close(bbox.x, 5 + tx, EPSILON); assert.close(bbox.y, 15 + ty, EPSILON); assert.close(bbox.width, 20, EPSILON); @@ -273,7 +273,7 @@ describe('utilities bbox', function () { attr: { id: 'rect2', x: rect.x, y: rect.y, width: rect.width, height: rect.height, transform: 'rotate(' + angle + ' ' + origin.x + ',' + origin.y + ') ' + matrix } }); svgroot.append(elem); - bbox = getBBoxWithTransform(elem, mockaddSVGElementFromJson, mockPathActions); + bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions); const r2 = rotateRect(rect, angle, origin); assert.close(bbox.x, r2.x + tx, EPSILON, 'rect2 x is ' + r2.x); assert.close(bbox.y, r2.y + ty, EPSILON, 'rect2 y is ' + r2.y); @@ -292,7 +292,7 @@ describe('utilities bbox', function () { }); g.append(elem); svgroot.append(g); - bbox = getBBoxWithTransform(g, mockaddSVGElementFromJson, mockPathActions); + bbox = getBBoxWithTransform(g, mockaddSVGElemensFromJson, mockPathActions); assert.close(bbox.x, r2.x + tx, EPSILON, 'rect2 x is ' + r2.x); assert.close(bbox.y, r2.y + ty, EPSILON, 'rect2 y is ' + r2.y); assert.close(bbox.width, r2.width, EPSILON, 'rect2 width is' + r2.width); @@ -304,7 +304,7 @@ describe('utilities bbox', function () { attr: { id: 'ellipse1', cx: '100', cy: '100', rx: '50', ry: '50', transform: 'rotate(45 100,100) ' + matrix } }); svgroot.append(elem); - bbox = getBBoxWithTransform(elem, mockaddSVGElementFromJson, mockPathActions); + bbox = getBBoxWithTransform(elem, mockaddSVGElemensFromJson, mockPathActions); /** @todo: the BBox algorithm is using the bezier control points to calculate the bounding box. Should be 50, 50, 100, 100. */ // assert.ok(bbox.x > 45 + tx && bbox.x <= 50 + tx); assert.ok(bbox.y > 45 + ty && bbox.y <= 50 + ty); @@ -322,7 +322,7 @@ describe('utilities bbox', function () { attr: { id: 'path', d: 'M0,1 L2,3', 'stroke-width': strokeWidth } }); svgroot.append(elem); - let bbox = getStrokedBBox([ elem ], mockaddSVGElementFromJson, mockPathActions); + let bbox = getStrokedBBox([ elem ], mockaddSVGElemensFromJson, mockPathActions); assert.deepEqual(bbox, { x: 0 - strokeWidth / 2, y: 1 - strokeWidth / 2, width: 2 + strokeWidth, height: 2 + strokeWidth }); elem.remove(); @@ -331,7 +331,7 @@ describe('utilities bbox', function () { attr: { id: 'rect', x: '0', y: '1', width: '5', height: '10', 'stroke-width': strokeWidth } }); svgroot.append(elem); - bbox = getStrokedBBox([ elem ], mockaddSVGElementFromJson, mockPathActions); + bbox = getStrokedBBox([ elem ], mockaddSVGElemensFromJson, mockPathActions); assert.deepEqual(bbox, { x: 0 - strokeWidth / 2, y: 1 - strokeWidth / 2, width: 5 + strokeWidth, height: 10 + strokeWidth }); elem.remove(); @@ -340,7 +340,7 @@ describe('utilities bbox', function () { attr: { id: 'line', x1: '0', y1: '1', x2: '5', y2: '6', 'stroke-width': strokeWidth } }); svgroot.append(elem); - bbox = getStrokedBBox([ elem ], mockaddSVGElementFromJson, mockPathActions); + bbox = getStrokedBBox([ elem ], mockaddSVGElemensFromJson, mockPathActions); assert.deepEqual(bbox, { x: 0 - strokeWidth / 2, y: 1 - strokeWidth / 2, width: 5 + strokeWidth, height: 5 + strokeWidth }); elem.remove(); @@ -354,7 +354,7 @@ describe('utilities bbox', function () { }); g.append(elem); svgroot.append(g); - bbox = getStrokedBBox([ elem ], mockaddSVGElementFromJson, mockPathActions); + bbox = getStrokedBBox([ elem ], mockaddSVGElemensFromJson, mockPathActions); assert.deepEqual(bbox, { x: 0 - strokeWidth / 2, y: 1 - strokeWidth / 2, width: 5 + strokeWidth, height: 10 + strokeWidth }); g.remove(); }); @@ -367,7 +367,7 @@ describe('utilities bbox', function () { attr: { id: 'path', d: 'M0,1 L2,3', 'stroke-width': 'none' } }); svgroot.append(elem); - let bbox = getStrokedBBox([ elem ], mockaddSVGElementFromJson, mockPathActions); + let bbox = getStrokedBBox([ elem ], mockaddSVGElemensFromJson, mockPathActions); assert.deepEqual(bbox, { x: 0, y: 1, width: 2, height: 2 }); elem.remove(); @@ -376,7 +376,7 @@ describe('utilities bbox', function () { attr: { id: 'rect', x: '0', y: '1', width: '5', height: '10', 'stroke-width': 'none' } }); svgroot.append(elem); - bbox = getStrokedBBox([ elem ], mockaddSVGElementFromJson, mockPathActions); + bbox = getStrokedBBox([ elem ], mockaddSVGElemensFromJson, mockPathActions); assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 10 }); elem.remove(); @@ -385,7 +385,7 @@ describe('utilities bbox', function () { attr: { id: 'line', x1: '0', y1: '1', x2: '5', y2: '6', 'stroke-width': 'none' } }); svgroot.append(elem); - bbox = getStrokedBBox([ elem ], mockaddSVGElementFromJson, mockPathActions); + bbox = getStrokedBBox([ elem ], mockaddSVGElemensFromJson, mockPathActions); assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 5 }); elem.remove(); @@ -399,7 +399,7 @@ describe('utilities bbox', function () { }); g.append(elem); svgroot.append(g); - bbox = getStrokedBBox([ elem ], mockaddSVGElementFromJson, mockPathActions); + bbox = getStrokedBBox([ elem ], mockaddSVGElemensFromJson, mockPathActions); assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 10 }); g.remove(); }); @@ -412,7 +412,7 @@ describe('utilities bbox', function () { attr: { id: 'path', d: 'M0,1 L2,3' } }); svgroot.append(elem); - let bbox = getStrokedBBox([ elem ], mockaddSVGElementFromJson, mockPathActions); + let bbox = getStrokedBBox([ elem ], mockaddSVGElemensFromJson, mockPathActions); assert.deepEqual(bbox, { x: 0, y: 1, width: 2, height: 2 }); elem.remove(); @@ -421,7 +421,7 @@ describe('utilities bbox', function () { attr: { id: 'rect', x: '0', y: '1', width: '5', height: '10' } }); svgroot.append(elem); - bbox = getStrokedBBox([ elem ], mockaddSVGElementFromJson, mockPathActions); + bbox = getStrokedBBox([ elem ], mockaddSVGElemensFromJson, mockPathActions); assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 10 }); elem.remove(); @@ -430,7 +430,7 @@ describe('utilities bbox', function () { attr: { id: 'line', x1: '0', y1: '1', x2: '5', y2: '6' } }); svgroot.append(elem); - bbox = getStrokedBBox([ elem ], mockaddSVGElementFromJson, mockPathActions); + bbox = getStrokedBBox([ elem ], mockaddSVGElemensFromJson, mockPathActions); assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 5 }); elem.remove(); @@ -444,7 +444,7 @@ describe('utilities bbox', function () { }); g.append(elem); svgroot.append(g); - bbox = getStrokedBBox([ elem ], mockaddSVGElementFromJson, mockPathActions); + bbox = getStrokedBBox([ elem ], mockaddSVGElemensFromJson, mockPathActions); assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 10 }); g.remove(); }); diff --git a/cypress/integration/unit/utilities-performance.js b/cypress/integration/unit/utilities-performance.js index 0265f0d6..72ab0efa 100644 --- a/cypress/integration/unit/utilities-performance.js +++ b/cypress/integration/unit/utilities-performance.js @@ -87,11 +87,11 @@ describe('utilities performance', function () { } /** - * Mock of {@link module:utilities.EditorContext#addSVGElementFromJson}. + * Mock of {@link module:utilities.EditorContext#addSVGElemensFromJson}. * @param {module:utilities.SVGElementJSON} json * @returns {SVGElement} */ - function mockaddSVGElementFromJson (json) { + function mockaddSVGElemensFromJson (json) { const elem = mockCreateSVGElement(json); currentLayer.append(elem); return elem; @@ -198,7 +198,7 @@ describe('utilities performance', function () { // Skip the first child which is the title. for (let index = 1; index < count; index++) { const child = children[index]; - /* const obj = */ getStrokedBBox([ child ], mockaddSVGElementFromJson, mockPathActions); + /* const obj = */ getStrokedBBox([ child ], mockaddSVGElemensFromJson, mockPathActions); now = Date.now(); const delta = now - lastTime; lastTime = now; total += delta; min = Math.min(min, delta); @@ -218,7 +218,7 @@ describe('utilities performance', function () { // Skip the first child which is the title. for (let index = 1; index < ct; index++) { const child = children[index]; - /* const obj = */ getStrokedBBox([ child ], mockaddSVGElementFromJson, mockPathActions); + /* const obj = */ getStrokedBBox([ child ], mockaddSVGElemensFromJson, mockPathActions); now = Date.now(); const delta = now - lastTime; lastTime = now; total += delta; min = Math.min(min, delta); diff --git a/cypress/integration/unit/utilities.js b/cypress/integration/unit/utilities.js index d925f3a7..aa1616cc 100644 --- a/cypress/integration/unit/utilities.js +++ b/cypress/integration/unit/utilities.js @@ -19,7 +19,7 @@ describe('utilities', function () { * @param {module:utilities.SVGElementJSON} json * @returns {SVGElement} */ - function mockaddSVGElementFromJson (json) { + function mockaddSVGElemensFromJson (json) { const elem = mockCreateSVGElement(json); svgroot.append(elem); return elem; @@ -245,8 +245,8 @@ describe('utilities', function () { * Wrap `utilities.getBBoxOfElementAsPath` to convert bbox to object for testing. * @type {module:utilities.getBBoxOfElementAsPath} */ - function getBBoxOfElementAsPath (elem, addSVGElementFromJson, pathActions) { - const bbox = utilities.getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions); + function getBBoxOfElementAsPath (elem, addSVGElemensFromJson, pathActions) { + const bbox = utilities.getBBoxOfElementAsPath(elem, addSVGElemensFromJson, pathActions); return utilities.bboxToObj(bbox); // need this for assert.equal() to work. } @@ -255,7 +255,7 @@ describe('utilities', function () { attr: { id: 'path', d: 'M0,1 Z' } }); svgroot.append(elem); - let bbox = getBBoxOfElementAsPath(elem, mockaddSVGElementFromJson, mockPathActions); + let bbox = getBBoxOfElementAsPath(elem, mockaddSVGElemensFromJson, mockPathActions); assert.deepEqual(bbox, { x: 0, y: 1, width: 0, height: 0 }); elem.remove(); @@ -264,7 +264,7 @@ describe('utilities', function () { attr: { id: 'rect', x: '0', y: '1', width: '5', height: '10' } }); svgroot.append(elem); - bbox = getBBoxOfElementAsPath(elem, mockaddSVGElementFromJson, mockPathActions); + bbox = getBBoxOfElementAsPath(elem, mockaddSVGElemensFromJson, mockPathActions); assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 10 }); elem.remove(); @@ -273,7 +273,7 @@ describe('utilities', function () { attr: { id: 'line', x1: '0', y1: '1', x2: '5', y2: '6' } }); svgroot.append(elem); - bbox = getBBoxOfElementAsPath(elem, mockaddSVGElementFromJson, mockPathActions); + bbox = getBBoxOfElementAsPath(elem, mockaddSVGElemensFromJson, mockPathActions); assert.deepEqual(bbox, { x: 0, y: 1, width: 5, height: 5 }); elem.remove(); @@ -294,7 +294,7 @@ describe('utilities', function () { attr: { id: 'rect', x: '0', y: '1', width: '5', height: '10' } }); svgroot.append(elem); - const path = convertToPath(elem, attrs, mockaddSVGElementFromJson, mockPathActions, mockClearSelection, mockAddToSelection, mockHistory, mockAddCommandToHistory); + const path = convertToPath(elem, attrs, mockaddSVGElemensFromJson, mockPathActions, mockClearSelection, mockAddToSelection, mockHistory, mockAddCommandToHistory); assert.equal(path.getAttribute('d'), 'M0,1 L5,1 L5,11 L0,11 L0,1 Z'); assert.equal(path.getAttribute('visibilituy'), null); assert.equal(path.id, 'rect'); @@ -322,7 +322,7 @@ describe('utilities', function () { getAttribute () { return ''; }, parentNode: svgroot }; - const path = convertToPath(elem, attrs, mockaddSVGElementFromJson, mockPathActions, mockClearSelection, mockAddToSelection, mockHistory, mockAddCommandToHistory); + const path = convertToPath(elem, attrs, mockaddSVGElemensFromJson, mockPathActions, mockClearSelection, mockAddToSelection, mockHistory, mockAddCommandToHistory); assert.equal(path, null); assert.equal(elem.parentNode, svgroot); assert.equal(mockHistorySubCommands.length, 0); diff --git a/demos/canvas.html b/demos/canvas.html index 3d149e80..0a903806 100644 --- a/demos/canvas.html +++ b/demos/canvas.html @@ -50,7 +50,7 @@ window.canvas = new SvgCanvas(container, config); canvas.updateCanvas(width, height); window.fill = function (colour) { - canvas.getSelectedElems().forEach((el) => { + canvas.getSelectedElements().forEach((el) => { el.setAttribute('fill', colour); }); }; diff --git a/src/common/browser.js b/src/common/browser.js index 00e3b4b7..8d5c8131 100644 --- a/src/common/browser.js +++ b/src/common/browser.js @@ -20,13 +20,13 @@ const isTouch_ = 'ontouchstart' in window; // text character positioning (for IE9 and now Chrome) const supportsGoodTextCharPos_ = (function () { const svgroot = document.createElementNS(NSSVG, 'svg'); - const svgcontent = document.createElementNS(NSSVG, 'svg'); + const svgContent = document.createElementNS(NSSVG, 'svg'); document.documentElement.append(svgroot); - svgcontent.setAttribute('x', 5); - svgroot.append(svgcontent); + svgContent.setAttribute('x', 5); + svgroot.append(svgContent); const text = document.createElementNS(NSSVG, 'text'); text.textContent = 'a'; - svgcontent.append(text); + svgContent.append(text); try { // Chrome now fails here const pos = text.getStartPositionOfChar(0).x; return (pos === 0); diff --git a/src/editor/Editor.js b/src/editor/Editor.js index daf39569..bf39d3a6 100644 --- a/src/editor/Editor.js +++ b/src/editor/Editor.js @@ -729,7 +729,7 @@ class Editor extends EditorStartup { multiplier = multiplier ? resolution.zoom * multiplier : 1; // setResolution(res.w * multiplier, res.h * multiplier, true); $id('zoom').value = (multiplier * 100).toFixed(1); - this.svgCanvas.setZoom(multiplier); + this.svgCanvas.setCurrentZoom(multiplier); this.zoomDone(); this.updateCanvas(true); } @@ -1116,7 +1116,7 @@ class Editor extends EditorStartup { if (!this.svgCanvas) { throw new Error('Extension added too early'); } - return this.svgCanvas.addExtension.call(this, name, initfn, initArgs); + return this.svgCanvas.addExtension( name, initfn, initArgs); } } diff --git a/src/editor/Rulers.js b/src/editor/Rulers.js index 46048137..75bd7f6a 100644 --- a/src/editor/Rulers.js +++ b/src/editor/Rulers.js @@ -58,7 +58,7 @@ class Rulers { let d; let i; const limit = 30000; - const contentElem = this.svgCanvas.getContentElem(); + const contentElem = this.svgCanvas.getSvgContent(); const units = getTypeMap(); const unit = units[this.editor.configObj.curConfig.baseUnit]; // 1 = 1px diff --git a/src/editor/extensions/ext-eyedropper/ext-eyedropper.js b/src/editor/extensions/ext-eyedropper/ext-eyedropper.js index 366ae9e0..32ccda77 100644 --- a/src/editor/extensions/ext-eyedropper/ext-eyedropper.js +++ b/src/editor/extensions/ext-eyedropper/ext-eyedropper.js @@ -28,7 +28,7 @@ export default { async init(S) { const svgEditor = this; await loadExtensionTranslation(svgEditor); - const { ChangeElementCommand } = S; // , svgcontent, + const { ChangeElementCommand } = S; // svgdoc = S.svgroot.parentNode.ownerDocument, const { svgCanvas } = svgEditor; const addToHistory = function (cmd) { svgCanvas.undoMgr.addCommandToHistory(cmd); }; diff --git a/src/editor/extensions/ext-imagelib/ext-imagelib.js b/src/editor/extensions/ext-imagelib/ext-imagelib.js index 7901866c..941ef901 100644 --- a/src/editor/extensions/ext-imagelib/ext-imagelib.js +++ b/src/editor/extensions/ext-imagelib/ext-imagelib.js @@ -71,7 +71,7 @@ export default { * @returns {void} */ const importImage = (url) => { - const newImage = svgCanvas.addSVGElementFromJson({ + const newImage = svgCanvas.addSVGElemensFromJson({ element: 'image', attr: { x: 0, diff --git a/src/editor/extensions/ext-markers/ext-markers.js b/src/editor/extensions/ext-markers/ext-markers.js index d1c0592b..227f67de 100644 --- a/src/editor/extensions/ext-markers/ext-markers.js +++ b/src/editor/extensions/ext-markers/ext-markers.js @@ -32,7 +32,7 @@ export default { async init (S) { const svgEditor = this; const { svgCanvas } = svgEditor; - const { $id, addSVGElementFromJson: addElem } = svgCanvas; + const { $id, addSVGElemensFromJson: addElem } = svgCanvas; const mtypes = [ 'start', 'mid', 'end' ]; const markerElems = [ 'line', 'path', 'polyline', 'polygon' ]; @@ -99,7 +99,7 @@ export default { * @returns {SVGMarkerElement} */ const addMarker = (id, seType) => { - const selElems = svgCanvas.getSelectedElems(); + const selElems = svgCanvas.getSelectedElements(); let marker = svgCanvas.getElem(id); if (marker) { return undefined; } if (seType === '' || seType === 'nomarker') { return undefined; } @@ -200,7 +200,7 @@ export default { * @returns {void} */ const setMarker = (pos, markerType) => { - const selElems = svgCanvas.getSelectedElems(); + const selElems = svgCanvas.getSelectedElements(); if (selElems.length === 0) return; const markerName = 'marker-' + pos; const el = selElems[0]; @@ -252,7 +252,7 @@ export default { * @returns {void} */ const updateReferences = (el) => { - const selElems = svgCanvas.getSelectedElems(); + const selElems = svgCanvas.getSelectedElements(); mtypes.forEach((pos) => { const markerName = 'marker-' + pos; const marker = getLinked(el, markerName); diff --git a/src/editor/extensions/ext-opensave/ext-opensave.js b/src/editor/extensions/ext-opensave/ext-opensave.js index 9894ffa1..d5b986ac 100644 --- a/src/editor/extensions/ext-opensave/ext-opensave.js +++ b/src/editor/extensions/ext-opensave/ext-opensave.js @@ -83,7 +83,7 @@ export default { * @returns {void} */ const insertNewImage = (imageWidth, imageHeight) => { - const newImage = this.svgCanvas.addSVGElementFromJson({ + const newImage = this.svgCanvas.addSVGElemensFromJson({ element: 'image', attr: { x: 0, diff --git a/src/editor/extensions/ext-polystar/ext-polystar.js b/src/editor/extensions/ext-polystar/ext-polystar.js index 1451f444..9ecfdd15 100644 --- a/src/editor/extensions/ext-polystar/ext-polystar.js +++ b/src/editor/extensions/ext-polystar/ext-polystar.js @@ -246,7 +246,7 @@ export default { const sRgb = svgCanvas.getColor("stroke"); const sWidth = svgCanvas.getStrokeWidth(); started = true; - newFO = svgCanvas.addSVGElementFromJson({ + newFO = svgCanvas.addSVGElemensFromJson({ element: "polygon", attr: { cx: opts.start_x, @@ -275,7 +275,7 @@ export default { // ccSRgbEl = sRgb.substring(1, rgb.length); const sWidth = svgCanvas.getStrokeWidth(); started = true; - newFO = svgCanvas.addSVGElementFromJson({ + newFO = svgCanvas.addSVGElemensFromJson({ element: "polygon", attr: { cx: opts.start_x, diff --git a/src/editor/extensions/ext-shapes/ext-shapes.js b/src/editor/extensions/ext-shapes/ext-shapes.js index 129695d1..ec46064e 100644 --- a/src/editor/extensions/ext-shapes/ext-shapes.js +++ b/src/editor/extensions/ext-shapes/ext-shapes.js @@ -27,7 +27,7 @@ export default { const svgEditor = this; const canv = svgEditor.svgCanvas; const { $id } = canv; - const svgroot = canv.getRootElem(); + const svgroot = canv.getSvgRoot(); let lastBBox = {}; await loadExtensionTranslation(svgEditor); @@ -67,7 +67,7 @@ export default { startClientPos.x = opts.event.clientX; startClientPos.y = opts.event.clientY; - curShape = canv.addSVGElementFromJson({ + curShape = canv.addSVGElemensFromJson({ element: 'path', curStyles: true, attr: { diff --git a/src/editor/extensions/ext-storage/ext-storage.js b/src/editor/extensions/ext-storage/ext-storage.js index dc3136d0..9d6b8ab6 100644 --- a/src/editor/extensions/ext-storage/ext-storage.js +++ b/src/editor/extensions/ext-storage/ext-storage.js @@ -100,7 +100,7 @@ export default { } else { removeStoragePrefCookie(); if (svgEditor.configObj.curConfig.emptyStorageOnDecline && e?.detail?.checkbox) { - this.setSVGContentStorage(''); + this.setSvgContentStorage(''); Object.keys(svgEditor.curPrefs).forEach((name) => { name = 'svg-edit-' + name; if (svgEditor.storage) { @@ -128,7 +128,7 @@ export default { * @param {string} val * @returns {void} */ - function setSVGContentStorage (val) { + function setSvgContentStorage (val) { if (storage) { const name = 'svgedit-' + svgEditor.configObj.curConfig.canvasName; if (!val) { @@ -155,7 +155,7 @@ export default { return; } if ((/(?:^|;\s*)svgeditstore=prefsAndContent/).test(document.cookie)) { - setSVGContentStorage(svgCanvas.getSvgString()); + setSvgContentStorage(svgCanvas.getSvgString()); } svgEditor.setConfig({ no_save_warning: true }); // No need for explicit saving at all once storage is on diff --git a/src/editor/extensions/ext-storage/storageDialog.js b/src/editor/extensions/ext-storage/storageDialog.js index b2807a9e..d106fde4 100644 --- a/src/editor/extensions/ext-storage/storageDialog.js +++ b/src/editor/extensions/ext-storage/storageDialog.js @@ -139,7 +139,7 @@ export class SeStorageDialog extends HTMLElement { * @param {string} val * @returns {void} */ - setSVGContentStorage (val) { + setSvgContentStorage (val) { if (this.storage) { const name = 'svgedit-' + this.configObj.curConfig.canvasName; if (!val) { diff --git a/src/editor/panels/TopPanel.js b/src/editor/panels/TopPanel.js index 4b336841..3a21cdca 100644 --- a/src/editor/panels/TopPanel.js +++ b/src/editor/panels/TopPanel.js @@ -780,7 +780,7 @@ class TopPanel { .then(() => { // switch into "select" mode if we've clicked on an element editor.svgCanvas.setMode('select'); - editor.svgCanvas.selectOnly(editor.svgCanvas.getSelectedElems(), true); + editor.svgCanvas.selectOnly(editor.svgCanvas.getSelectedElements(), true); }, (error) => { console.error("error =", error); seAlert(editor.i18next.t('tools.no_embed')); diff --git a/src/svgcanvas/blur-event.js b/src/svgcanvas/blur-event.js index 9897ece1..320b910c 100644 --- a/src/svgcanvas/blur-event.js +++ b/src/svgcanvas/blur-event.js @@ -10,15 +10,15 @@ const { InsertElementCommand, ChangeElementCommand, BatchCommand } = hstry; -let blurContext_ = null; +let svgCanvas = null; /** * @function module:blur.init * @param {module:blur.blurContext} blurContext * @returns {void} */ -export const init = function (blurContext) { - blurContext_ = blurContext; +export const init = function (canvas) { + svgCanvas = canvas; }; /** @@ -28,28 +28,28 @@ export const init = function (blurContext) { * @returns {void} */ export const setBlurNoUndo = function (val) { - const selectedElements = blurContext_.getSelectedElements(); - if (!blurContext_.getFilter()) { - blurContext_.getCanvas().setBlur(val); + const selectedElements = svgCanvas.getSelectedElements(); + if (!svgCanvas.getFilter()) { + svgCanvas.setBlur(val); return; } if (val === 0) { // Don't change the StdDev, as that will hide the element. // Instead, just remove the value for "filter" - blurContext_.changeSelectedAttributeNoUndoMethod('filter', ''); - blurContext_.setFilterHidden(true); + svgCanvas.changeSelectedAttributeNoUndoMethod('filter', ''); + svgCanvas.setFilterHidden(true); } else { const elem = selectedElements[0]; - if (blurContext_.getFilterHidden()) { - blurContext_.changeSelectedAttributeNoUndoMethod('filter', 'url(#' + elem.id + '_blur)'); + if (svgCanvas.getFilterHidden()) { + svgCanvas.changeSelectedAttributeNoUndoMethod('filter', 'url(#' + elem.id + '_blur)'); } - if (blurContext_.isWebkit()) { + if (svgCanvas.isWebkit()) { elem.removeAttribute('filter'); elem.setAttribute('filter', 'url(#' + elem.id + '_blur)'); } - const filter = blurContext_.getFilter(); - blurContext_.changeSelectedAttributeNoUndoMethod('stdDeviation', val, [ filter.firstChild ]); - blurContext_.getCanvas().setBlurOffsets(filter, val); + const filter = svgCanvas.getFilter(); + svgCanvas.changeSelectedAttributeNoUndoMethod('stdDeviation', val, [ filter.firstChild ]); + svgCanvas.setBlurOffsets(filter, val); } }; @@ -58,11 +58,11 @@ export const setBlurNoUndo = function (val) { * @returns {void} */ function finishChange () { - const bCmd = blurContext_.getCanvas().undoMgr.finishUndoableChange(); - blurContext_.getCurCommand().addSubCommand(bCmd); - blurContext_.addCommandToHistory(blurContext_.getCurCommand()); - blurContext_.setCurCommand(null); - blurContext_.setFilter(null); + const bCmd = svgCanvas.undoMgr.finishUndoableChange(); + svgCanvas.getCurCommand().addSubCommand(bCmd); + svgCanvas.addCommandToHistory(svgCanvas.getCurCommand()); + svgCanvas.setCurCommand(null); + svgCanvas.setFilter(null); } /** @@ -76,14 +76,14 @@ function finishChange () { export const setBlurOffsets = function (filterElem, stdDev) { if (stdDev > 3) { // TODO: Create algorithm here where size is based on expected blur - blurContext_.getCanvas().assignAttributes(filterElem, { + svgCanvas.assignAttributes(filterElem, { x: '-50%', y: '-50%', width: '200%', height: '200%' }, 100); // Removing these attributes hides text in Chrome (see Issue 579) - } else if (!blurContext_.isWebkit()) { + } else if (!svgCanvas.isWebkit()) { filterElem.removeAttribute('x'); filterElem.removeAttribute('y'); filterElem.removeAttribute('width'); @@ -99,8 +99,8 @@ export const setBlurOffsets = function (filterElem, stdDev) { * @returns {void} */ export const setBlur = function (val, complete) { - const selectedElements = blurContext_.getSelectedElements(); - if (blurContext_.getCurCommand()) { + const selectedElements = svgCanvas.getSelectedElements(); + if (svgCanvas.getCurCommand()) { finishChange(); return; } @@ -108,35 +108,35 @@ export const setBlur = function (val, complete) { // Looks for associated blur, creates one if not found const elem = selectedElements[0]; const elemId = elem.id; - blurContext_.setFilter(blurContext_.getCanvas().getElem(elemId + '_blur')); + svgCanvas.setFilter(svgCanvas.getElem(elemId + '_blur')); val -= 0; const batchCmd = new BatchCommand(); // Blur found! - if (blurContext_.getFilter()) { + if (svgCanvas.getFilter()) { if (val === 0) { - blurContext_.setFilter(null); + svgCanvas.setFilter(null); } } else { // Not found, so create - const newblur = blurContext_.getCanvas().addSVGElementFromJson({ element: 'feGaussianBlur', + const newblur = svgCanvas.addSVGElemensFromJson({ element: 'feGaussianBlur', attr: { in: 'SourceGraphic', stdDeviation: val } }); - blurContext_.setFilter(blurContext_.getCanvas().addSVGElementFromJson({ element: 'filter', + svgCanvas.setFilter(svgCanvas.addSVGElemensFromJson({ element: 'filter', attr: { id: elemId + '_blur' } })); - blurContext_.getFilter().append(newblur); - blurContext_.getCanvas().findDefs().append(blurContext_.getFilter()); + svgCanvas.getFilter().append(newblur); + svgCanvas.findDefs().append(svgCanvas.getFilter()); - batchCmd.addSubCommand(new InsertElementCommand(blurContext_.getFilter())); + batchCmd.addSubCommand(new InsertElementCommand(svgCanvas.getFilter())); } const changes = { filter: elem.getAttribute('filter') }; @@ -147,14 +147,14 @@ export const setBlur = function (val, complete) { return; } - blurContext_.changeSelectedAttributeMethod('filter', 'url(#' + elemId + '_blur)'); + svgCanvas.changeSelectedAttributeMethod('filter', 'url(#' + elemId + '_blur)'); batchCmd.addSubCommand(new ChangeElementCommand(elem, changes)); - blurContext_.getCanvas().setBlurOffsets(blurContext_.getFilter(), val); - const filter = blurContext_.getFilter(); - blurContext_.setCurCommand(batchCmd); - blurContext_.getCanvas().undoMgr.beginUndoableChange('stdDeviation', [ filter ? filter.firstChild : null ]); + svgCanvas.setBlurOffsets(svgCanvas.getFilter(), val); + const filter = svgCanvas.getFilter(); + svgCanvas.setCurCommand(batchCmd); + svgCanvas.undoMgr.beginUndoableChange('stdDeviation', [ filter ? filter.firstChild : null ]); if (complete) { - blurContext_.getCanvas().setBlurNoUndo(val); + svgCanvas.setBlurNoUndo(val); finishChange(); } }; diff --git a/src/svgcanvas/clear.js b/src/svgcanvas/clear.js index 36faac3a..dd51b01f 100644 --- a/src/svgcanvas/clear.js +++ b/src/svgcanvas/clear.js @@ -6,27 +6,27 @@ */ import { NS } from './namespaces.js'; -let clearContext_ = null; +let svgCanvas = null; /** * @function module:clear.init * @param {module:clear.SvgCanvas#init} clearContext * @returns {void} */ -export const init = function (clearContext) { - clearContext_ = clearContext; +export const init = (canvas) => { + svgCanvas = canvas; }; -export const clearSvgContentElementInit = function () { - const curConfig = clearContext_.getCurConfig(); +export const clearSvgContentElementInit = () => { + const curConfig = svgCanvas.getCurConfig(); const { dimensions } = curConfig; - const el = clearContext_.getSVGContent(); - // empty() + const el = svgCanvas.getSvgContent(); + // empty while(el.firstChild) el.removeChild(el.firstChild); // TODO: Clear out all other attributes first? - const pel = clearContext_.getSVGRoot(); + const pel = svgCanvas.getSvgRoot(); el.setAttribute('id', 'svgcontent'); el.setAttribute('width', dimensions[0]); el.setAttribute('height', dimensions[1]); @@ -39,6 +39,6 @@ export const clearSvgContentElementInit = function () { pel.appendChild(el); // TODO: make this string optional and set by the client - const comment = clearContext_.getDOMDocument().createComment(' Created with SVG-edit - https://github.com/SVG-Edit/svgedit'); - clearContext_.getSVGContent().append(comment); + const comment = svgCanvas.getDOMDocument().createComment(' Created with SVG-edit - https://github.com/SVG-Edit/svgedit'); + svgCanvas.getSvgContent().append(comment); }; diff --git a/src/svgcanvas/coords.js b/src/svgcanvas/coords.js index 7d63f49f..167f3945 100644 --- a/src/svgcanvas/coords.js +++ b/src/svgcanvas/coords.js @@ -29,19 +29,19 @@ const pathMap = [ * @returns {module:draw.Drawing} */ /** - * @function module:coords.EditorContext#getSVGRoot + * @function module:coords.EditorContext#getSvgRoot * @returns {SVGSVGElement} */ -let editorContext_ = null; +let svgCanvas = null; /** * @function module:coords.init * @param {module:svgcanvas.SvgCanvas#event:pointsAdded} editorContext * @returns {void} */ -export const init = function (editorContext) { - editorContext_ = editorContext; +export const init = function (canvas) { + svgCanvas = canvas; }; /** @@ -53,7 +53,7 @@ export const remapElement = function (selected, changes, m) { const remap = (x, y) => transformPoint(x, y, m); const scalew = (w) => m.a * w; const scaleh = (h) => m.d * h; - const doSnapping = editorContext_.getGridSnapping() && selected.parentNode.parentNode.localName === 'svg'; + const doSnapping = svgCanvas.getGridSnapping() && selected.parentNode.parentNode.localName === 'svg'; const finishUp = () => { if (doSnapping) { Object.entries(changes).forEach(([ o, value ]) => { @@ -84,7 +84,7 @@ export const remapElement = function (selected, changes, m) { newgrad.setAttribute('y1', -(y1 - 1)); newgrad.setAttribute('y2', -(y2 - 1)); } - newgrad.id = editorContext_.getDrawing().getNextId(); + newgrad.id = svgCanvas.getDrawing().getNextId(); findDefs().append(newgrad); selected.setAttribute(type, 'url(#' + newgrad.id + ')'); } @@ -103,7 +103,7 @@ export const remapElement = function (selected, changes, m) { } else { // we just absorb all matrices into the element and don't do any remapping const chlist = selected.transform.baseVal; - const mt = editorContext_.getSVGRoot().createSVGTransform(); + const mt = svgCanvas.getSvgRoot().createSVGTransform(); mt.setMatrix(matrixMultiply(transformListToTransform(chlist).matrix, m)); chlist.clear(); chlist.appendItem(mt); @@ -120,7 +120,7 @@ export const remapElement = function (selected, changes, m) { if (elName === 'image' && (m.a < 0 || m.d < 0)) { // Convert to matrix const chlist = selected.transform.baseVal; - const mt = editorContext_.getSVGRoot().createSVGTransform(); + const mt = svgCanvas.getSvgRoot().createSVGTransform(); mt.setMatrix(matrixMultiply(transformListToTransform(chlist).matrix, m)); chlist.clear(); chlist.appendItem(mt); @@ -171,7 +171,7 @@ export const remapElement = function (selected, changes, m) { finishUp(); break; } case 'g': { - const dataStorage = editorContext_.getDataStorage(); + const dataStorage = svgCanvas.getDataStorage(); const gsvg = dataStorage.get(selected, 'gsvg'); if (gsvg) { assignAttributes(gsvg, changes, 1000, true); diff --git a/src/svgcanvas/draw.js b/src/svgcanvas/draw.js index b213e1ea..bf090259 100644 --- a/src/svgcanvas/draw.js +++ b/src/svgcanvas/draw.js @@ -37,7 +37,7 @@ let disabledElems = []; * @returns {module:history.HistoryRecordingService} */ function historyRecordingService (hrService) { - return hrService || new HistoryRecordingService(canvas_.undoMgr); + return hrService || new HistoryRecordingService(svgCanvas.undoMgr); } /** @@ -720,7 +720,7 @@ export const randomizeIds = function (enableRandomization, currentDrawing) { * @returns {Element[]} the array with selected DOM elements */ /** - * @function module:draw.DrawCanvasInit#getSVGContent + * @function module:draw.DrawCanvasInit#getSvgContent * @returns {SVGSVGElement} */ /** @@ -747,18 +747,18 @@ export const randomizeIds = function (enableRandomization, currentDrawing) { * @returns {void} */ /** - * @function module:draw.DrawCanvasInit#changeSVGContent + * @function module:draw.DrawCanvasInit#changeSvgContent * @returns {void} */ -let canvas_; +let svgCanvas; /** * @function module:draw.init * @param {module:draw.DrawCanvasInit} canvas * @returns {void} */ export const init = function (canvas) { - canvas_ = canvas; + svgCanvas = canvas; }; /** @@ -768,7 +768,7 @@ export const init = function (canvas) { */ export const identifyLayers = function () { leaveContext(); - canvas_.getCurrentDrawing().identifyLayers(); + svgCanvas.getCurrentDrawing().identifyLayers(); }; /** @@ -782,12 +782,12 @@ export const identifyLayers = function () { * @returns {void} */ export const createLayer = function (name, hrService) { - const newLayer = canvas_.getCurrentDrawing().createLayer( + const newLayer = svgCanvas.getCurrentDrawing().createLayer( name, historyRecordingService(hrService) ); - canvas_.clearSelection(); - canvas_.call('changed', [ newLayer ]); + svgCanvas.clearSelection(); + svgCanvas.call('changed', [ newLayer ]); }; /** @@ -802,11 +802,11 @@ export const createLayer = function (name, hrService) { */ export const cloneLayer = function (name, hrService) { // Clone the current layer and make the cloned layer the new current layer - const newLayer = canvas_.getCurrentDrawing().cloneLayer(name, historyRecordingService(hrService)); + const newLayer = svgCanvas.getCurrentDrawing().cloneLayer(name, historyRecordingService(hrService)); - canvas_.clearSelection(); + svgCanvas.clearSelection(); leaveContext(); - canvas_.call('changed', [ newLayer ]); + svgCanvas.call('changed', [ newLayer ]); }; /** @@ -817,17 +817,17 @@ export const cloneLayer = function (name, hrService) { * @returns {boolean} `true` if an old layer group was found to delete */ export const deleteCurrentLayer = function () { - let currentLayer = canvas_.getCurrentDrawing().getCurrentLayer(); + let currentLayer = svgCanvas.getCurrentDrawing().getCurrentLayer(); const { nextSibling } = currentLayer; const parent = currentLayer.parentNode; - currentLayer = canvas_.getCurrentDrawing().deleteCurrentLayer(); + currentLayer = svgCanvas.getCurrentDrawing().deleteCurrentLayer(); if (currentLayer) { const batchCmd = new BatchCommand('Delete Layer'); // store in our Undo History batchCmd.addSubCommand(new RemoveElementCommand(currentLayer, nextSibling, parent)); - canvas_.addCommandToHistory(batchCmd); - canvas_.clearSelection(); - canvas_.call('changed', [ parent ]); + svgCanvas.addCommandToHistory(batchCmd); + svgCanvas.clearSelection(); + svgCanvas.call('changed', [ parent ]); return true; } return false; @@ -841,9 +841,9 @@ export const deleteCurrentLayer = function () { * @returns {boolean} true if the current layer was switched, otherwise false */ export const setCurrentLayer = function (name) { - const result = canvas_.getCurrentDrawing().setCurrentLayer(toXml(name)); + const result = svgCanvas.getCurrentDrawing().setCurrentLayer(toXml(name)); if (result) { - canvas_.clearSelection(); + svgCanvas.clearSelection(); } return result; }; @@ -858,12 +858,12 @@ export const setCurrentLayer = function (name) { * @returns {boolean} Whether the rename succeeded */ export const renameCurrentLayer = function (newName) { - const drawing = canvas_.getCurrentDrawing(); + const drawing = svgCanvas.getCurrentDrawing(); const layer = drawing.getCurrentLayer(); if (layer) { const result = drawing.setCurrentLayerName(newName, historyRecordingService()); if (result) { - canvas_.call('changed', [ layer ]); + svgCanvas.call('changed', [ layer ]); return true; } } @@ -880,10 +880,10 @@ export const renameCurrentLayer = function (newName) { * @returns {boolean} `true` if the current layer position was changed, `false` otherwise. */ export const setCurrentLayerPosition = function (newPos) { - const drawing = canvas_.getCurrentDrawing(); + const drawing = svgCanvas.getCurrentDrawing(); const result = drawing.setCurrentLayerPosition(newPos); if (result) { - canvas_.addCommandToHistory(new MoveElementCommand(result.currentGroup, result.oldNextSibling, canvas_.getSVGContent())); + svgCanvas.addCommandToHistory(new MoveElementCommand(result.currentGroup, result.oldNextSibling, svgCanvas.getSvgContent())); return true; } return false; @@ -898,19 +898,19 @@ export const setCurrentLayerPosition = function (newPos) { * @returns {boolean} true if the layer's visibility was set, false otherwise */ export const setLayerVisibility = function (layerName, bVisible) { - const drawing = canvas_.getCurrentDrawing(); + const drawing = svgCanvas.getCurrentDrawing(); const prevVisibility = drawing.getLayerVisibility(layerName); const layer = drawing.setLayerVisibility(layerName, bVisible); if (layer) { const oldDisplay = prevVisibility ? 'inline' : 'none'; - canvas_.addCommandToHistory(new ChangeElementCommand(layer, { display: oldDisplay }, 'Layer Visibility')); + svgCanvas.addCommandToHistory(new ChangeElementCommand(layer, { display: oldDisplay }, 'Layer Visibility')); } else { return false; } if (layer === drawing.getCurrentLayer()) { - canvas_.clearSelection(); - canvas_.pathActions.clear(); + svgCanvas.clearSelection(); + svgCanvas.pathActions.clear(); } // call('changed', [selected]); return true; @@ -925,14 +925,14 @@ export const setLayerVisibility = function (layerName, bVisible) { */ export const moveSelectedToLayer = function (layerName) { // find the layer - const drawing = canvas_.getCurrentDrawing(); + const drawing = svgCanvas.getCurrentDrawing(); const layer = drawing.getLayerByName(layerName); if (!layer) { return false; } const batchCmd = new BatchCommand('Move Elements to Layer'); // loop for each selected element and move it - const selElems = canvas_.getSelectedElements(); + const selElems = svgCanvas.getSelectedElements(); let i = selElems.length; while (i--) { const elem = selElems[i]; @@ -944,7 +944,7 @@ export const moveSelectedToLayer = function (layerName) { batchCmd.addSubCommand(new MoveElementCommand(elem, oldNextSibling, oldLayer)); } - canvas_.addCommandToHistory(batchCmd); + svgCanvas.addCommandToHistory(batchCmd); return true; }; @@ -955,10 +955,10 @@ export const moveSelectedToLayer = function (layerName) { * @returns {void} */ export const mergeLayer = function (hrService) { - canvas_.getCurrentDrawing().mergeLayer(historyRecordingService(hrService)); - canvas_.clearSelection(); + svgCanvas.getCurrentDrawing().mergeLayer(historyRecordingService(hrService)); + svgCanvas.clearSelection(); leaveContext(); - canvas_.changeSVGContent(); + svgCanvas.changeSvgContent(); }; /** @@ -967,10 +967,10 @@ export const mergeLayer = function (hrService) { * @returns {void} */ export const mergeAllLayers = function (hrService) { - canvas_.getCurrentDrawing().mergeAllLayers(historyRecordingService(hrService)); - canvas_.clearSelection(); + svgCanvas.getCurrentDrawing().mergeAllLayers(historyRecordingService(hrService)); + svgCanvas.clearSelection(); leaveContext(); - canvas_.changeSVGContent(); + svgCanvas.changeSvgContent(); }; /** @@ -982,7 +982,7 @@ export const mergeAllLayers = function (hrService) { */ export const leaveContext = function () { const len = disabledElems.length; - const dataStorage = canvas_.getDataStorage(); + const dataStorage = svgCanvas.getDataStorage(); if (len) { for (let i = 0; i < len; i++) { const elem = disabledElems[i]; @@ -995,10 +995,10 @@ export const leaveContext = function () { elem.setAttribute('style', 'pointer-events: inherit'); } disabledElems = []; - canvas_.clearSelection(true); - canvas_.call('contextset', null); + svgCanvas.clearSelection(true); + svgCanvas.call('contextset', null); } - canvas_.setCurrentGroup(null); + svgCanvas.setCurrentGroup(null); }; /** @@ -1009,14 +1009,14 @@ export const leaveContext = function () { * @returns {void} */ export const setContext = function (elem) { - const dataStorage = canvas_.getDataStorage(); + const dataStorage = svgCanvas.getDataStorage(); leaveContext(); if (typeof elem === 'string') { elem = getElem(elem); } // Edit inside this group - canvas_.setCurrentGroup(elem); + svgCanvas.setCurrentGroup(elem); // Disable other elements const parentsUntil = getParentsUntil(elem, '#svgcontent'); @@ -1038,8 +1038,8 @@ export const setContext = function (elem) { curthis.setAttribute('style', 'pointer-events: none'); disabledElems.push(curthis); }); - canvas_.clearSelection(); - canvas_.call('contextset', canvas_.getCurrentGroup()); + svgCanvas.clearSelection(); + svgCanvas.call('contextset', svgCanvas.getCurrentGroup()); }; /** diff --git a/src/svgcanvas/elem-get-set.js b/src/svgcanvas/elem-get-set.js index c7198042..47250d89 100644 --- a/src/svgcanvas/elem-get-set.js +++ b/src/svgcanvas/elem-get-set.js @@ -21,15 +21,15 @@ const { ChangeElementCommand, BatchCommand } = hstry; -let elemContext_ = null; +let svgCanvas = null; /** * @function module:elem-get-set.init * @param {module:elem-get-set.elemContext} elemContext * @returns {void} */ -export const init = function (elemContext) { - elemContext_ = elemContext; +export const init = function (canvas) { + svgCanvas = canvas; }; /** @@ -37,14 +37,14 @@ export const init = function (elemContext) { * @returns {DimensionsAndZoom} The current dimensions and zoom level in an object */ export const getResolutionMethod = function () { - const currentZoom = elemContext_.getCurrentZoom(); - const w = elemContext_.getSVGContent().getAttribute('width') / currentZoom; - const h = elemContext_.getSVGContent().getAttribute('height') / currentZoom; + const zoom = svgCanvas.getZoom(); + const w = svgCanvas.getSvgContent().getAttribute('width') / zoom; + const h = svgCanvas.getSvgContent().getAttribute('height') / zoom; return { w, h, - zoom: currentZoom + zoom }; }; @@ -55,8 +55,8 @@ export const getResolutionMethod = function () { * `undefined` if no element is passed nd there are no selected elements. */ export const getTitleMethod = function (elem) { - const selectedElements = elemContext_.getSelectedElements(); - const dataStorage = elemContext_.getDataStorage(); + const selectedElements = svgCanvas.getSelectedElements(); + const dataStorage = svgCanvas.getDataStorage(); elem = elem || selectedElements[0]; if (!elem) { return undefined; } if (dataStorage.has(elem, 'gsvg')) { @@ -81,8 +81,8 @@ export const getTitleMethod = function (elem) { * @returns {void} */ export const setGroupTitleMethod = function (val) { - const selectedElements = elemContext_.getSelectedElements(); - const dataStorage = elemContext_.getDataStorage(); + const selectedElements = svgCanvas.getSelectedElements(); + const dataStorage = svgCanvas.getDataStorage(); let elem = selectedElements[0]; if (dataStorage.has(elem, 'gsvg')) { elem = dataStorage.get(elem, 'gsvg'); @@ -105,13 +105,13 @@ export const setGroupTitleMethod = function (val) { title.textContent = val; } else { // Add title element - title = elemContext_.getDOMDocument().createElementNS(NS.SVG, 'title'); + title = svgCanvas.getDOMDocument().createElementNS(NS.SVG, 'title'); title.textContent = val; elem.insertBefore(title, elem.firstChild); batchCmd.addSubCommand(new InsertElementCommand(title)); } - elemContext_.addCommandToHistory(batchCmd); + svgCanvas.addCommandToHistory(batchCmd); }; /** @@ -122,7 +122,7 @@ export const setGroupTitleMethod = function (val) { * @returns {void} */ export const setDocumentTitleMethod = function (newTitle) { - const childs = elemContext_.getSVGContent().childNodes; + const childs = svgCanvas.getSvgContent().childNodes; let docTitle = false; let oldTitle = ''; const batchCmd = new BatchCommand('Change Image Title'); @@ -135,9 +135,9 @@ export const setDocumentTitleMethod = function (newTitle) { } } if (!docTitle) { - docTitle = elemContext_.getDOMDocument().createElementNS(NS.SVG, 'title'); - elemContext_.getSVGContent().insertBefore(docTitle, elemContext_.getSVGContent().firstChild); - // svgcontent.firstChild.before(docTitle); // Ok to replace above with this? + docTitle = svgCanvas.getDOMDocument().createElementNS(NS.SVG, 'title'); + svgCanvas.getSvgContent().insertBefore(docTitle, svgCanvas.getSvgContent().firstChild); + // svgContent.firstChild.before(docTitle); // Ok to replace above with this? } if (newTitle.length) { @@ -147,7 +147,7 @@ export const setDocumentTitleMethod = function (newTitle) { docTitle.remove(); } batchCmd.addSubCommand(new ChangeElementCommand(docTitle, { '#text': oldTitle })); - elemContext_.addCommandToHistory(batchCmd); + svgCanvas.addCommandToHistory(batchCmd); }; /** @@ -161,8 +161,8 @@ export const setDocumentTitleMethod = function (newTitle) { * It will fail on "fit to content" option with no content to fit to. */ export const setResolutionMethod = function (x, y) { - const currentZoom = elemContext_.getCurrentZoom(); - const res = elemContext_.getCanvas().getResolution(); + const zoom = svgCanvas.getZoom(); + const res = svgCanvas.getResolution(); const { w, h } = res; let batchCmd; @@ -173,16 +173,16 @@ export const setResolutionMethod = function (x, y) { if (bbox) { batchCmd = new BatchCommand('Fit Canvas to Content'); const visEls = getVisibleElements(); - elemContext_.getCanvas().addToSelection(visEls); + svgCanvas.addToSelection(visEls); const dx = []; const dy = []; visEls.forEach(function(_item, _i){ dx.push(bbox.x * -1); dy.push(bbox.y * -1); }); - const cmd = elemContext_.getCanvas().moveSelectedElements(dx, dy, true); + const cmd = svgCanvas.moveSelectedElements(dx, dy, true); batchCmd.addSubCommand(cmd); - elemContext_.getCanvas().clearSelection(); + svgCanvas.clearSelection(); x = Math.round(bbox.width); y = Math.round(bbox.height); @@ -198,18 +198,18 @@ export const setResolutionMethod = function (x, y) { x = convertToNum('width', x); y = convertToNum('height', y); - elemContext_.getSVGContent().setAttribute('width', x); - elemContext_.getSVGContent().setAttribute('height', y); + svgCanvas.getSvgContent().setAttribute('width', x); + svgCanvas.getSvgContent().setAttribute('height', y); this.contentW = x; this.contentH = y; - batchCmd.addSubCommand(new ChangeElementCommand(elemContext_.getSVGContent(), { width: w, height: h })); + batchCmd.addSubCommand(new ChangeElementCommand(svgCanvas.getSvgContent(), { width: w, height: h })); - elemContext_.getSVGContent().setAttribute('viewBox', [ 0, 0, x / currentZoom, y / currentZoom ].join(' ')); - batchCmd.addSubCommand(new ChangeElementCommand(elemContext_.getSVGContent(), { viewBox: [ '0 0', w, h ].join(' ') })); + svgCanvas.getSvgContent().setAttribute('viewBox', [ 0, 0, x / zoom, y / zoom ].join(' ')); + batchCmd.addSubCommand(new ChangeElementCommand(svgCanvas.getSvgContent(), { viewBox: [ '0 0', w, h ].join(' ') })); - elemContext_.addCommandToHistory(batchCmd); - elemContext_.call('changed', [ elemContext_.getSVGContent() ]); + svgCanvas.addCommandToHistory(batchCmd); + svgCanvas.call('changed', [ svgCanvas.getSvgContent() ]); } return true; }; @@ -222,7 +222,7 @@ export const setResolutionMethod = function (x, y) { */ export const getEditorNSMethod = function (add) { if (add) { - elemContext_.getSVGContent().setAttribute('xmlns:se', NS.SE); + svgCanvas.getSvgContent().setAttribute('xmlns:se', NS.SE); } return NS.SE; }; @@ -241,8 +241,8 @@ export const getEditorNSMethod = function (add) { * @returns {module:elem-get-set.ZoomAndBBox|void} */ export const setBBoxZoomMethod = function (val, editorW, editorH) { - const currentZoom = elemContext_.getCurrentZoom(); - const selectedElements = elemContext_.getSelectedElements(); + const zoom = svgCanvas.getZoom(); + const selectedElements = svgCanvas.getSelectedElements(); let spacer = 0.85; let bb; const calcZoom = function (bb) { @@ -250,16 +250,16 @@ export const setBBoxZoomMethod = function (val, editorW, editorH) { const wZoom = Math.round((editorW / bb.width) * 100 * spacer) / 100; const hZoom = Math.round((editorH / bb.height) * 100 * spacer) / 100; const zoom = Math.min(wZoom, hZoom); - elemContext_.getCanvas().setZoom(zoom); + svgCanvas.setZoom(zoom); return { zoom, bbox: bb }; }; if (typeof val === 'object') { bb = val; if (bb.width === 0 || bb.height === 0) { - const newzoom = bb.zoom ? bb.zoom : currentZoom * bb.factor; - elemContext_.getCanvas().setZoom(newzoom); - return { zoom: currentZoom, bbox: bb }; + const newzoom = bb.zoom ? bb.zoom : zoom * bb.factor; + svgCanvas.setZoom(newzoom); + return { zoom: zoom, bbox: bb }; } return calcZoom(bb); } @@ -276,7 +276,7 @@ export const setBBoxZoomMethod = function (val, editorW, editorH) { bb = getStrokedBBoxDefaultVisible(selectedElems); break; } case 'canvas': { - const res = elemContext_.getCanvas().getResolution(); + const res = svgCanvas.getResolution(); spacer = 0.95; bb = { width: res.w, height: res.h, x: 0, y: 0 }; break; @@ -284,7 +284,7 @@ export const setBBoxZoomMethod = function (val, editorW, editorH) { bb = getStrokedBBoxDefaultVisible(); break; case 'layer': - bb = getStrokedBBoxDefaultVisible(getVisibleElements(elemContext_.getCanvas().getCurrentDrawing().getCurrentLayer())); + bb = getStrokedBBoxDefaultVisible(getVisibleElements(svgCanvas.getCurrentDrawing().getCurrentLayer())); break; default: return undefined; @@ -300,16 +300,16 @@ export const setBBoxZoomMethod = function (val, editorW, editorH) { * @returns {void} */ export const setZoomMethod = function (zoomLevel) { - const selectedElements = elemContext_.getSelectedElements(); - const res = elemContext_.getCanvas().getResolution(); - elemContext_.getSVGContent().setAttribute('viewBox', '0 0 ' + res.w / zoomLevel + ' ' + res.h / zoomLevel); - elemContext_.setCurrentZoom(zoomLevel); + const selectedElements = svgCanvas.getSelectedElements(); + const res = svgCanvas.getResolution(); + svgCanvas.getSvgContent().setAttribute('viewBox', '0 0 ' + res.w / zoomLevel + ' ' + res.h / zoomLevel); + svgCanvas.setZoom(zoomLevel); selectedElements.forEach(function(elem){ if (!elem) { return; } - elemContext_.getCanvas().selectorManager.requestSelector(elem).resize(); + svgCanvas.selectorManager.requestSelector(elem).resize(); }); - elemContext_.getCanvas().pathActions.zoomChange(); - elemContext_.getCanvas().runExtensions('zoomChanged', zoomLevel); + svgCanvas.pathActions.zoomChange(); + svgCanvas.runExtensions('zoomChanged', zoomLevel); }; /** @@ -322,9 +322,9 @@ export const setZoomMethod = function (zoomLevel) { * @returns {void} */ export const setColorMethod = function (type, val, preventUndo) { - const selectedElements = elemContext_.getSelectedElements(); - elemContext_.setCurShape(type, val); - elemContext_.setCurProperties(type + '_paint', { type: 'solidColor' }); + const selectedElements = svgCanvas.getSelectedElements(); + svgCanvas.setCurShape(type, val); + svgCanvas.setCurProperties(type + '_paint', { type: 'solidColor' }); const elems = []; /** * @@ -353,10 +353,10 @@ export const setColorMethod = function (type, val, preventUndo) { } if (elems.length > 0) { if (!preventUndo) { - elemContext_.getCanvas().changeSelectedAttribute(type, val, elems); - elemContext_.call('changed', elems); + svgCanvas.changeSelectedAttribute(type, val, elems); + svgCanvas.call('changed', elems); } else { - elemContext_.changeSelectedAttributeNoUndoMethod(type, val, elems); + svgCanvas.changeSelectedAttributeNoUndoMethod(type, val, elems); } } }; @@ -368,9 +368,9 @@ export const setColorMethod = function (type, val, preventUndo) { * @returns {void} */ export const setGradientMethod = function (type) { - if (!elemContext_.getCurProperties(type + '_paint') || - elemContext_.getCurProperties(type + '_paint').type === 'solidColor') { return; } - const canvas = elemContext_.getCanvas(); + if (!svgCanvas.getCurProperties(type + '_paint') || + svgCanvas.getCurProperties(type + '_paint').type === 'solidColor') { return; } + const canvas = svgCanvas; let grad = canvas[type + 'Grad']; // find out if there is a duplicate gradient already in the defs const duplicateGrad = findDuplicateGradient(grad); @@ -378,14 +378,14 @@ export const setGradientMethod = function (type) { // no duplicate found, so import gradient into defs if (!duplicateGrad) { // const origGrad = grad; - grad = elemContext_.getDOMDocument().importNode(grad, true); + grad = svgCanvas.getDOMDocument().importNode(grad, true); defs.append(grad); // get next id and set it on the grad - grad.id = elemContext_.getCanvas().getNextId(); + grad.id = svgCanvas.getNextId(); } else { // use existing gradient grad = duplicateGrad; } - elemContext_.getCanvas().setColor(type, 'url(#' + grad.id + ')'); + svgCanvas.setColor(type, 'url(#' + grad.id + ')'); }; /** @@ -474,15 +474,15 @@ export const setPaintMethod = function (type, paint) { this.setPaintOpacity(type, p.alpha / 100, true); // now set the current paint object - elemContext_.setCurProperties(type + '_paint', p); + svgCanvas.setCurProperties(type + '_paint', p); switch (p.type) { case 'solidColor': this.setColor(type, p.solidColor !== 'none' ? '#' + p.solidColor : 'none'); break; case 'linearGradient': case 'radialGradient': - elemContext_.setCanvas(type + 'Grad', p[p.type]); - elemContext_.getCanvas().setGradient(type); + svgCanvas.setCanvas(type + 'Grad', p[p.type]); + svgCanvas.setGradient(type); break; } }; @@ -495,12 +495,12 @@ export const setPaintMethod = function (type, paint) { * @returns {void} */ export const setStrokeWidthMethod = function (val) { - const selectedElements = elemContext_.getSelectedElements(); - if (val === 0 && [ 'line', 'path' ].includes(elemContext_.getCanvas().getMode())) { - elemContext_.getCanvas().setStrokeWidth(1); + const selectedElements = svgCanvas.getSelectedElements(); + if (val === 0 && [ 'line', 'path' ].includes(svgCanvas.getMode())) { + svgCanvas.setStrokeWidth(1); return; } - elemContext_.setCurProperties('stroke_width', val); + svgCanvas.setCurProperties('stroke_width', val); const elems = []; /** @@ -525,8 +525,8 @@ export const setStrokeWidthMethod = function (val) { } } if (elems.length > 0) { - elemContext_.getCanvas().changeSelectedAttribute('stroke-width', val, elems); - elemContext_.call('changed', selectedElements); + svgCanvas.changeSelectedAttribute('stroke-width', val, elems); + svgCanvas.call('changed', selectedElements); } }; @@ -539,8 +539,8 @@ export const setStrokeWidthMethod = function (val) { * @returns {void} */ export const setStrokeAttrMethod = function (attr, val) { - const selectedElements = elemContext_.getSelectedElements(); - elemContext_.setCurShape(attr.replace('-', '_'), val); + const selectedElements = svgCanvas.getSelectedElements(); + svgCanvas.setCurShape(attr.replace('-', '_'), val); const elems = []; let i = selectedElements.length; @@ -555,8 +555,8 @@ export const setStrokeAttrMethod = function (attr, val) { } } if (elems.length > 0) { - elemContext_.getCanvas().changeSelectedAttribute(attr, val, elems); - elemContext_.call('changed', selectedElements); + svgCanvas.changeSelectedAttribute(attr, val, elems); + svgCanvas.call('changed', selectedElements); } }; /** @@ -565,7 +565,7 @@ export const setStrokeAttrMethod = function (attr, val) { * @returns {boolean} Indicates whether or not element is bold */ export const getBoldMethod = function () { - const selectedElements = elemContext_.getSelectedElements(); + const selectedElements = svgCanvas.getSelectedElements(); // should only have one element selected const selected = selectedElements[0]; if (!isNullish(selected) && selected.tagName === 'text' && @@ -582,14 +582,14 @@ export const getBoldMethod = function () { * @returns {void} */ export const setBoldMethod = function (b) { - const selectedElements = elemContext_.getSelectedElements(); + const selectedElements = svgCanvas.getSelectedElements(); const selected = selectedElements[0]; if (!isNullish(selected) && selected.tagName === 'text' && isNullish(selectedElements[1])) { - elemContext_.getCanvas().changeSelectedAttribute('font-weight', b ? 'bold' : 'normal'); + svgCanvas.changeSelectedAttribute('font-weight', b ? 'bold' : 'normal'); } if (!selectedElements[0].textContent) { - elemContext_.getCanvas().textActions.setCursor(); + svgCanvas.textActions.setCursor(); } }; @@ -599,7 +599,7 @@ export const setBoldMethod = function (b) { * @returns {boolean} Indicates whether or not element is italic */ export const getItalicMethod = function () { - const selectedElements = elemContext_.getSelectedElements(); + const selectedElements = svgCanvas.getSelectedElements(); const selected = selectedElements[0]; if (!isNullish(selected) && selected.tagName === 'text' && isNullish(selectedElements[1])) { @@ -615,14 +615,14 @@ export const getItalicMethod = function () { * @returns {void} */ export const setItalicMethod = function (i) { - const selectedElements = elemContext_.getSelectedElements(); + const selectedElements = svgCanvas.getSelectedElements(); const selected = selectedElements[0]; if (!isNullish(selected) && selected.tagName === 'text' && isNullish(selectedElements[1])) { - elemContext_.getCanvas().changeSelectedAttribute('font-style', i ? 'italic' : 'normal'); + svgCanvas.changeSelectedAttribute('font-style', i ? 'italic' : 'normal'); } if (!selectedElements[0].textContent) { - elemContext_.getCanvas().textActions.setCursor(); + svgCanvas.textActions.setCursor(); } }; @@ -632,14 +632,14 @@ export const setItalicMethod = function (i) { * @returns {void} */ export const setTextAnchorMethod = function (value) { - const selectedElements = elemContext_.getSelectedElements(); + const selectedElements = svgCanvas.getSelectedElements(); const selected = selectedElements[0]; if (!isNullish(selected) && selected.tagName === 'text' && isNullish(selectedElements[1])) { - elemContext_.getCanvas().changeSelectedAttribute('text-anchor', value); + svgCanvas.changeSelectedAttribute('text-anchor', value); } if (!selectedElements[0].textContent) { - elemContext_.getCanvas().textActions.setCursor(); + svgCanvas.textActions.setCursor(); } }; @@ -648,7 +648,7 @@ export const setTextAnchorMethod = function (value) { * @returns {string} The current font family */ export const getFontFamilyMethod = function () { - return elemContext_.getCurText('font_family'); + return svgCanvas.getCurText('font_family'); }; /** @@ -658,11 +658,11 @@ export const getFontFamilyMethod = function () { * @returns {void} */ export const setFontFamilyMethod = function (val) { - const selectedElements = elemContext_.getSelectedElements(); - elemContext_.setCurText('font_family', val); - elemContext_.getCanvas().changeSelectedAttribute('font-family', val); + const selectedElements = svgCanvas.getSelectedElements(); + svgCanvas.setCurText('font_family', val); + svgCanvas.changeSelectedAttribute('font-family', val); if (selectedElements[0] && !selectedElements[0].textContent) { - elemContext_.getCanvas().textActions.setCursor(); + svgCanvas.textActions.setCursor(); } }; @@ -673,8 +673,8 @@ export const setFontFamilyMethod = function (val) { * @returns {void} */ export const setFontColorMethod = function (val) { - elemContext_.setCurText('fill', val); - elemContext_.getCanvas().changeSelectedAttribute('fill', val); + svgCanvas.setCurText('fill', val); + svgCanvas.changeSelectedAttribute('fill', val); }; /** @@ -682,7 +682,7 @@ export const setFontColorMethod = function (val) { * @returns {string} The current font color */ export const getFontColorMethod = function () { - return elemContext_.getCurText('fill'); + return svgCanvas.getCurText('fill'); }; /** @@ -690,7 +690,7 @@ export const getFontColorMethod = function () { * @returns {Float} The current font size */ export const getFontSizeMethod = function () { - return elemContext_.getCurText('font_size'); + return svgCanvas.getCurText('font_size'); }; /** @@ -700,11 +700,11 @@ export const getFontSizeMethod = function () { * @returns {void} */ export const setFontSizeMethod = function (val) { - const selectedElements = elemContext_.getSelectedElements(); - elemContext_.setCurText('font_size', val); - elemContext_.getCanvas().changeSelectedAttribute('font-size', val); + const selectedElements = svgCanvas.getSelectedElements(); + svgCanvas.setCurText('font_size', val); + svgCanvas.changeSelectedAttribute('font-size', val); if (!selectedElements[0].textContent) { - elemContext_.getCanvas().textActions.setCursor(); + svgCanvas.textActions.setCursor(); } }; @@ -713,7 +713,7 @@ export const setFontSizeMethod = function (val) { * @returns {string} The current text (`textContent`) of the selected element */ export const getTextMethod = function () { - const selectedElements = elemContext_.getSelectedElements(); + const selectedElements = svgCanvas.getSelectedElements(); const selected = selectedElements[0]; if (isNullish(selected)) { return ''; } return (selected) ? selected.textContent : ''; @@ -726,9 +726,9 @@ export const getTextMethod = function () { * @returns {void} */ export const setTextContentMethod = function (val) { - elemContext_.getCanvas().changeSelectedAttribute('#text', val); - elemContext_.getCanvas().textActions.init(val); - elemContext_.getCanvas().textActions.setCursor(); + svgCanvas.changeSelectedAttribute('#text', val); + svgCanvas.textActions.init(val); + svgCanvas.textActions.setCursor(); }; /** @@ -740,7 +740,7 @@ export const setTextContentMethod = function (val) { * @returns {void} */ export const setImageURLMethod = function (val) { - const selectedElements = elemContext_.getSelectedElements(); + const selectedElements = svgCanvas.getSelectedElements(); const elem = selectedElements[0]; if (!elem) { return; } @@ -772,11 +772,11 @@ export const setImageURLMethod = function (val) { elem.setAttribute('width', this.width); elem.setAttribute('height', this.height); - elemContext_.getCanvas().selectorManager.requestSelector(elem).resize(); + svgCanvas.selectorManager.requestSelector(elem).resize(); batchCmd.addSubCommand(new ChangeElementCommand(elem, changes)); - elemContext_.addCommandToHistory(batchCmd); - elemContext_.call('changed', [ elem ]); + svgCanvas.addCommandToHistory(batchCmd); + svgCanvas.call('changed', [ elem ]); }; img.src = val; }; @@ -788,7 +788,7 @@ export const setImageURLMethod = function (val) { * @returns {void} */ export const setLinkURLMethod = function (val) { - const selectedElements = elemContext_.getSelectedElements(); + const selectedElements = svgCanvas.getSelectedElements(); let elem = selectedElements[0]; if (!elem) { return; } if (elem.tagName !== 'a') { @@ -812,7 +812,7 @@ export const setLinkURLMethod = function (val) { '#href': curHref })); - elemContext_.addCommandToHistory(batchCmd); + svgCanvas.addCommandToHistory(batchCmd); }; /** @@ -824,15 +824,15 @@ export const setLinkURLMethod = function (val) { * @returns {void} */ export const setRectRadiusMethod = function (val) { - const selectedElements = elemContext_.getSelectedElements(); + const selectedElements = svgCanvas.getSelectedElements(); const selected = selectedElements[0]; if (!isNullish(selected) && selected.tagName === 'rect') { const r = Number(selected.getAttribute('rx')); if (r !== val) { selected.setAttribute('rx', val); selected.setAttribute('ry', val); - elemContext_.addCommandToHistory(new ChangeElementCommand(selected, { rx: r, ry: r }, 'Radius')); - elemContext_.call('changed', [ selected ]); + svgCanvas.addCommandToHistory(new ChangeElementCommand(selected, { rx: r, ry: r }, 'Radius')); + svgCanvas.call('changed', [ selected ]); } } }; @@ -844,7 +844,7 @@ export const setRectRadiusMethod = function (val) { * @returns {void} */ export const makeHyperlinkMethod = function (url) { - elemContext_.getCanvas().groupSelectedElements('a', url); + svgCanvas.groupSelectedElements('a', url); // TODO: If element is a single "g", convert to "a" // if (selectedElements.length > 1 && selectedElements[1]) { @@ -855,7 +855,7 @@ export const makeHyperlinkMethod = function (url) { * @returns {void} */ export const removeHyperlinkMethod = function () { - elemContext_.getCanvas().ungroupSelectedElement(); + svgCanvas.ungroupSelectedElement(); }; /** @@ -869,7 +869,7 @@ export const removeHyperlinkMethod = function () { * @returns {void} */ export const setSegTypeMethod = function (newType) { - elemContext_.getCanvas().pathActions.setSegType(newType); + svgCanvas.pathActions.setSegType(newType); }; /** @@ -887,8 +887,8 @@ export const setBackgroundMethod = function (color, url) { border.setAttribute('fill', color === 'chessboard' ? '#fff' : color); if (color === 'chessboard') { if (!bgPattern) { - bgPattern = elemContext_.getDOMDocument().createElementNS(NS.SVG, 'foreignObject'); - elemContext_.getCanvas().assignAttributes(bgPattern, { + bgPattern = svgCanvas.getDOMDocument().createElementNS(NS.SVG, 'foreignObject'); + svgCanvas.assignAttributes(bgPattern, { id: 'background_pattern', width: '100%', height: '100%', @@ -896,7 +896,7 @@ export const setBackgroundMethod = function (color, url) { style: 'pointer-events:none' }); const div = document.createElement('div'); - elemContext_.getCanvas().assignAttributes(div, { + svgCanvas.assignAttributes(div, { style: 'pointer-events:none;width:100%;height:100%;' + 'background-image:url(data:image/gif;base64,' + 'R0lGODlhEAAQAIAAAP///9bW1iH5BAAAAAAALAAAAAAQABAAAAIfjG+' + @@ -910,8 +910,8 @@ export const setBackgroundMethod = function (color, url) { } if (url) { if (!bgImg) { - bgImg = elemContext_.getDOMDocument().createElementNS(NS.SVG, 'image'); - elemContext_.getCanvas().assignAttributes(bgImg, { + bgImg = svgCanvas.getDOMDocument().createElementNS(NS.SVG, 'image'); + svgCanvas.assignAttributes(bgImg, { id: 'background_image', width: '100%', height: '100%', diff --git a/src/svgcanvas/event.js b/src/svgcanvas/event.js index 4d5a3c34..10b93cce 100644 --- a/src/svgcanvas/event.js +++ b/src/svgcanvas/event.js @@ -23,23 +23,23 @@ const { InsertElementCommand } = hstry; -let eventContext_ = null; +let svgCanvas = null; /** * @function module:undo.init * @param {module:undo.eventContext} eventContext * @returns {void} */ -export const init = function (eventContext) { - eventContext_ = eventContext; +export const init = (canvas) => { + svgCanvas = canvas; }; -export const getBsplinePoint = function (t) { +export const getBsplinePoint = (t) => { const spline = { x: 0, y: 0 }; - const p0 = { x: eventContext_.getControllPoint2('x'), y: eventContext_.getControllPoint2('y') }; - const p1 = { x: eventContext_.getControllPoint1('x'), y: eventContext_.getControllPoint1('y') }; - const p2 = { x: eventContext_.getStart('x'), y: eventContext_.getStart('y') }; - const p3 = { x: eventContext_.getEnd('x'), y: eventContext_.getEnd('y') }; + const p0 = { x: svgCanvas.getControllPoint2('x'), y: svgCanvas.getControllPoint2('y') }; + const p1 = { x: svgCanvas.getControllPoint1('x'), y: svgCanvas.getControllPoint1('y') }; + const p2 = { x: svgCanvas.getStart('x'), y: svgCanvas.getStart('y') }; + const p3 = { x: svgCanvas.getEnd('x'), y: svgCanvas.getEnd('y') }; const S = 1.0 / 6.0; const t2 = t * t; const t3 = t2 * t; @@ -77,13 +77,12 @@ export const getBsplinePoint = function (t) { * @fires module:svgcanvas.SvgCanvas#event:ext_mouseMove * @returns {void} */ -export const mouseMoveEvent = function (evt) { - const selectedElements = eventContext_.getSelectedElements(); - const currentZoom = eventContext_.getCurrentZoom(); - const svgRoot = eventContext_.getSVGRoot(); - const svgCanvas = eventContext_.getCanvas(); +export const mouseMoveEvent = (evt) => { + const selectedElements = svgCanvas.getSelectedElements(); + const zoom = svgCanvas.getZoom(); + const svgRoot = svgCanvas.getSvgRoot(); - if (!eventContext_.getStarted()) { return; } + if (!svgCanvas.getStarted()) { return; } if (evt.button === 1 || svgCanvas.spaceKey) { return; } let i; @@ -96,32 +95,32 @@ export const mouseMoveEvent = function (evt) { let angle; let box; let selected = selectedElements[0]; - const pt = transformPoint(evt.clientX, evt.clientY, eventContext_.getrootSctm()); - const mouseX = pt.x * currentZoom; - const mouseY = pt.y * currentZoom; - const shape = getElem(eventContext_.getId()); + const pt = transformPoint(evt.clientX, evt.clientY, svgCanvas.getrootSctm()); + const mouseX = pt.x * zoom; + const mouseY = pt.y * zoom; + const shape = getElem(svgCanvas.getId()); - let realX = mouseX / currentZoom; + let realX = mouseX / zoom; let x = realX; - let realY = mouseY / currentZoom; + let realY = mouseY / zoom; let y = realY; - if (eventContext_.getCurConfig().gridSnapping) { + if (svgCanvas.getCurConfig().gridSnapping) { x = snapToGrid(x); y = snapToGrid(y); } evt.preventDefault(); let tlist; - switch (eventContext_.getCurrentMode()) { + switch (svgCanvas.getCurrentMode()) { case 'select': { // we temporarily use a translate on the element(s) being dragged // this transform is removed upon mousing up and the element is // relocated to the new location if (selectedElements[0] !== null) { - dx = x - eventContext_.getStartX(); - dy = y - eventContext_.getStartY(); - if (eventContext_.getCurConfig().gridSnapping) { + dx = x - svgCanvas.getStartX(); + dy = y - svgCanvas.getStartY(); + if (svgCanvas.getCurConfig().gridSnapping) { dx = snapToGrid(dx); dy = snapToGrid(dy); } @@ -155,13 +154,13 @@ export const mouseMoveEvent = function (evt) { } break; } case 'multiselect': { - realX *= currentZoom; - realY *= currentZoom; - assignAttributes(eventContext_.getRubberBox(), { - x: Math.min(eventContext_.getRStartX(), realX), - y: Math.min(eventContext_.getRStartY(), realY), - width: Math.abs(realX - eventContext_.getRStartX()), - height: Math.abs(realY - eventContext_.getRStartY()) + realX *= zoom; + realY *= zoom; + assignAttributes(svgCanvas.getRubberBox(), { + x: Math.min(svgCanvas.getRStartX(), realX), + y: Math.min(svgCanvas.getRStartY(), realY), + width: Math.abs(realX - svgCanvas.getRStartX()), + height: Math.abs(realY - svgCanvas.getRStartY()) }, 100); // for each selected: @@ -169,7 +168,7 @@ export const mouseMoveEvent = function (evt) { // - if newList doesn't contain selected, remove it from selected // - for any newList that was not in selectedElements, add it to selected const elemsToRemove = selectedElements.slice(); const elemsToAdd = []; - const newList = eventContext_.getIntersectionList(); + const newList = svgCanvas.getIntersectionList(); // For every element in the intersection, add if not present in selectedElements. len = newList.length; @@ -201,14 +200,14 @@ export const mouseMoveEvent = function (evt) { // the shape's coordinates tlist = selected.transform.baseVal; const hasMatrix = hasMatrixTransform(tlist); - box = hasMatrix ? eventContext_.getInitBbox() : getBBox(selected); + box = hasMatrix ? svgCanvas.getInitBbox() : getBBox(selected); let left = box.x; let top = box.y; let { width, height } = box; - dx = (x - eventContext_.getStartX()); - dy = (y - eventContext_.getStartY()); + dx = (x - svgCanvas.getStartX()); + dy = (y - svgCanvas.getStartY()); - if (eventContext_.getCurConfig().gridSnapping) { + if (svgCanvas.getCurConfig().gridSnapping) { dx = snapToGrid(dx); dy = snapToGrid(dy); height = snapToGrid(height); @@ -226,10 +225,10 @@ export const mouseMoveEvent = function (evt) { // if not stretching in y direction, set dy to 0 // if not stretching in x direction, set dx to 0 - if (!eventContext_.getCurrentResizeMode().includes('n') && !eventContext_.getCurrentResizeMode().includes('s')) { + if (!svgCanvas.getCurrentResizeMode().includes('n') && !svgCanvas.getCurrentResizeMode().includes('s')) { dy = 0; } - if (!eventContext_.getCurrentResizeMode().includes('e') && !eventContext_.getCurrentResizeMode().includes('w')) { + if (!svgCanvas.getCurrentResizeMode().includes('e') && !svgCanvas.getCurrentResizeMode().includes('w')) { dx = 0; } @@ -238,13 +237,13 @@ export const mouseMoveEvent = function (evt) { let sy = height ? (height + dy) / height : 1; let sx = width ? (width + dx) / width : 1; // if we are dragging on the north side, then adjust the scale factor and ty - if (eventContext_.getCurrentResizeMode().includes('n')) { + if (svgCanvas.getCurrentResizeMode().includes('n')) { sy = height ? (height - dy) / height : 1; ty = height; } // if we dragging on the east side, then adjust the scale factor and tx - if (eventContext_.getCurrentResizeMode().includes('w')) { + if (svgCanvas.getCurrentResizeMode().includes('w')) { sx = width ? (width - dx) / width : 1; tx = width; } @@ -254,7 +253,7 @@ export const mouseMoveEvent = function (evt) { const scale = svgRoot.createSVGTransform(); const translateBack = svgRoot.createSVGTransform(); - if (eventContext_.getCurConfig().gridSnapping) { + if (svgCanvas.getCurConfig().gridSnapping) { left = snapToGrid(left); tx = snapToGrid(tx); top = snapToGrid(top); @@ -287,13 +286,13 @@ export const mouseMoveEvent = function (evt) { break; } case 'zoom': { - realX *= currentZoom; - realY *= currentZoom; - assignAttributes(eventContext_.getRubberBox(), { - x: Math.min(eventContext_.getRStartX() * currentZoom, realX), - y: Math.min(eventContext_.getRStartY() * currentZoom, realY), - width: Math.abs(realX - eventContext_.getRStartX() * currentZoom), - height: Math.abs(realY - eventContext_.getRStartY() * currentZoom) + realX *= zoom; + realY *= zoom; + assignAttributes(svgCanvas.getRubberBox(), { + x: Math.min(svgCanvas.getRStartX() * zoom, realX), + y: Math.min(svgCanvas.getRStartY() * zoom, realY), + width: Math.abs(realX - svgCanvas.getRStartX() * zoom), + height: Math.abs(realY - svgCanvas.getRStartY() * zoom) }, 100); break; } case 'text': { @@ -303,7 +302,7 @@ export const mouseMoveEvent = function (evt) { }, 1000); break; } case 'line': { - if (eventContext_.getCurConfig().gridSnapping) { + if (svgCanvas.getCurConfig().gridSnapping) { x = snapToGrid(x); y = snapToGrid(y); } @@ -312,7 +311,7 @@ export const mouseMoveEvent = function (evt) { let y2 = y; if (evt.shiftKey) { - xya = snapToAngle(eventContext_.getStartX(), eventContext_.getStartY(), x2, y2); + xya = snapToAngle(svgCanvas.getStartX(), svgCanvas.getStartY(), x2, y2); x2 = xya.x; y2 = xya.y; } @@ -327,21 +326,21 @@ export const mouseMoveEvent = function (evt) { case 'rect': // fall through case 'image': { - const square = (eventContext_.getCurrentMode() === 'square') || evt.shiftKey; + const square = (svgCanvas.getCurrentMode() === 'square') || evt.shiftKey; let - w = Math.abs(x - eventContext_.getStartX()); - let h = Math.abs(y - eventContext_.getStartY()); + w = Math.abs(x - svgCanvas.getStartX()); + let h = Math.abs(y - svgCanvas.getStartY()); let newX; let newY; if (square) { w = h = Math.max(w, h); - newX = eventContext_.getStartX() < x ? eventContext_.getStartX() : eventContext_.getStartX() - w; - newY = eventContext_.getStartY() < y ? eventContext_.getStartY() : eventContext_.getStartY() - h; + newX = svgCanvas.getStartX() < x ? svgCanvas.getStartX() : svgCanvas.getStartX() - w; + newY = svgCanvas.getStartY() < y ? svgCanvas.getStartY() : svgCanvas.getStartY() - h; } else { - newX = Math.min(eventContext_.getStartX(), x); - newY = Math.min(eventContext_.getStartY(), y); + newX = Math.min(svgCanvas.getStartX(), x); + newY = Math.min(svgCanvas.getStartY(), y); } - if (eventContext_.getCurConfig().gridSnapping) { + if (svgCanvas.getCurConfig().gridSnapping) { w = snapToGrid(w); h = snapToGrid(h); newX = snapToGrid(newX); @@ -360,7 +359,7 @@ export const mouseMoveEvent = function (evt) { cx = Number(shape.getAttribute('cx')); cy = Number(shape.getAttribute('cy')); let rad = Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy)); - if (eventContext_.getCurConfig().gridSnapping) { + if (svgCanvas.getCurConfig().gridSnapping) { rad = snapToGrid(rad); } shape.setAttribute('r', rad); @@ -368,7 +367,7 @@ export const mouseMoveEvent = function (evt) { } case 'ellipse': { cx = Number(shape.getAttribute('cx')); cy = Number(shape.getAttribute('cy')); - if (eventContext_.getCurConfig().gridSnapping) { + if (svgCanvas.getCurConfig().gridSnapping) { x = snapToGrid(x); cx = snapToGrid(cx); y = snapToGrid(y); @@ -381,96 +380,96 @@ export const mouseMoveEvent = function (evt) { } case 'fhellipse': case 'fhrect': { - eventContext_.setFreehand('minx', Math.min(realX, eventContext_.getFreehand('minx'))); - eventContext_.setFreehand('maxx', Math.max(realX, eventContext_.getFreehand('maxx'))); - eventContext_.setFreehand('miny', Math.min(realY, eventContext_.getFreehand('miny'))); - eventContext_.setFreehand('maxy', Math.max(realY, eventContext_.getFreehand('maxy'))); + svgCanvas.setFreehand('minx', Math.min(realX, svgCanvas.getFreehand('minx'))); + svgCanvas.setFreehand('maxx', Math.max(realX, svgCanvas.getFreehand('maxx'))); + svgCanvas.setFreehand('miny', Math.min(realY, svgCanvas.getFreehand('miny'))); + svgCanvas.setFreehand('maxy', Math.max(realY, svgCanvas.getFreehand('maxy'))); } // Fallthrough case 'fhpath': { // dAttr += + realX + ',' + realY + ' '; // shape.setAttribute('points', dAttr); - eventContext_.setEnd('x', realX); - eventContext_.setEnd('y', realY); - if (eventContext_.getControllPoint2('x') && eventContext_.getControllPoint2('y')) { - for (i = 0; i < eventContext_.getStepCount() - 1; i++) { - eventContext_.setParameter(i / eventContext_.getStepCount()); - eventContext_.setNextParameter((i + 1) / eventContext_.getStepCount()); - eventContext_.setbSpline(getBsplinePoint(eventContext_.getNextParameter())); - eventContext_.setNextPos({ x: eventContext_.getbSpline('x'), y: eventContext_.getbSpline('y') }); - eventContext_.setbSpline(getBsplinePoint(eventContext_.getParameter())); - eventContext_.setSumDistance( - eventContext_.getSumDistance() + Math.sqrt((eventContext_.getNextPos('x') - - eventContext_.getbSpline('x')) * (eventContext_.getNextPos('x') - - eventContext_.getbSpline('x')) + (eventContext_.getNextPos('y') - - eventContext_.getbSpline('y')) * (eventContext_.getNextPos('y') - eventContext_.getbSpline('y'))) + svgCanvas.setEnd('x', realX); + svgCanvas.setEnd('y', realY); + if (svgCanvas.getControllPoint2('x') && svgCanvas.getControllPoint2('y')) { + for (i = 0; i < svgCanvas.getStepCount() - 1; i++) { + svgCanvas.setParameter(i / svgCanvas.getStepCount()); + svgCanvas.setNextParameter((i + 1) / svgCanvas.getStepCount()); + svgCanvas.setbSpline(getBsplinePoint(svgCanvas.getNextParameter())); + svgCanvas.setNextPos({ x: svgCanvas.getbSpline('x'), y: svgCanvas.getbSpline('y') }); + svgCanvas.setbSpline(getBsplinePoint(svgCanvas.getParameter())); + svgCanvas.setSumDistance( + svgCanvas.getSumDistance() + Math.sqrt((svgCanvas.getNextPos('x') - + svgCanvas.getbSpline('x')) * (svgCanvas.getNextPos('x') - + svgCanvas.getbSpline('x')) + (svgCanvas.getNextPos('y') - + svgCanvas.getbSpline('y')) * (svgCanvas.getNextPos('y') - svgCanvas.getbSpline('y'))) ); - if (eventContext_.getSumDistance() > eventContext_.getThreSholdDist()) { - eventContext_.setSumDistance(eventContext_.getSumDistance() - eventContext_.getThreSholdDist()); + if (svgCanvas.getSumDistance() > svgCanvas.getThreSholdDist()) { + svgCanvas.setSumDistance(svgCanvas.getSumDistance() - svgCanvas.getThreSholdDist()); // Faster than completely re-writing the points attribute. - const point = eventContext_.getSVGContent().createSVGPoint(); - point.x = eventContext_.getbSpline('x'); - point.y = eventContext_.getbSpline('y'); + const point = svgCanvas.getSvgContent().createSVGPoint(); + point.x = svgCanvas.getbSpline('x'); + point.y = svgCanvas.getbSpline('y'); shape.points.appendItem(point); } } } - eventContext_.setControllPoint2('x', eventContext_.getControllPoint1('x')); - eventContext_.setControllPoint2('y', eventContext_.getControllPoint1('y')); - eventContext_.setControllPoint1('x', eventContext_.getStart('x')); - eventContext_.setControllPoint1('y', eventContext_.getStart('y')); - eventContext_.setStart({ x: eventContext_.getEnd('x'), y: eventContext_.getEnd('y') }); + svgCanvas.setControllPoint2('x', svgCanvas.getControllPoint1('x')); + svgCanvas.setControllPoint2('y', svgCanvas.getControllPoint1('y')); + svgCanvas.setControllPoint1('x', svgCanvas.getStart('x')); + svgCanvas.setControllPoint1('y', svgCanvas.getStart('y')); + svgCanvas.setStart({ x: svgCanvas.getEnd('x'), y: svgCanvas.getEnd('y') }); break; // update path stretch line coordinates } case 'path': // fall through case 'pathedit': { - x *= currentZoom; - y *= currentZoom; + x *= zoom; + y *= zoom; - if (eventContext_.getCurConfig().gridSnapping) { + if (svgCanvas.getCurConfig().gridSnapping) { x = snapToGrid(x); y = snapToGrid(y); - eventContext_.setStartX(snapToGrid(eventContext_.getStartX())); - eventContext_.setStartY(snapToGrid(eventContext_.getStartY())); + svgCanvas.setStartX(snapToGrid(svgCanvas.getStartX())); + svgCanvas.setStartY(snapToGrid(svgCanvas.getStartY())); } if (evt.shiftKey) { const { path } = pathModule; let x1; let y1; if (path) { - x1 = path.dragging ? path.dragging[0] : eventContext_.getStartX(); - y1 = path.dragging ? path.dragging[1] : eventContext_.getStartY(); + x1 = path.dragging ? path.dragging[0] : svgCanvas.getStartX(); + y1 = path.dragging ? path.dragging[1] : svgCanvas.getStartY(); } else { - x1 = eventContext_.getStartX(); - y1 = eventContext_.getStartY(); + x1 = svgCanvas.getStartX(); + y1 = svgCanvas.getStartY(); } xya = snapToAngle(x1, y1, x, y); ({ x, y } = xya); } - if (eventContext_.getRubberBox() && eventContext_.getRubberBox().getAttribute('display') !== 'none') { - realX *= currentZoom; - realY *= currentZoom; - assignAttributes(eventContext_.getRubberBox(), { - x: Math.min(eventContext_.getRStartX() * currentZoom, realX), - y: Math.min(eventContext_.getRStartY() * currentZoom, realY), - width: Math.abs(realX - eventContext_.getRStartX() * currentZoom), - height: Math.abs(realY - eventContext_.getRStartY() * currentZoom) + if (svgCanvas.getRubberBox() && svgCanvas.getRubberBox().getAttribute('display') !== 'none') { + realX *= zoom; + realY *= zoom; + assignAttributes(svgCanvas.getRubberBox(), { + x: Math.min(svgCanvas.getRStartX() * zoom, realX), + y: Math.min(svgCanvas.getRStartY() * zoom, realY), + width: Math.abs(realX - svgCanvas.getRStartX() * zoom), + height: Math.abs(realY - svgCanvas.getRStartY() * zoom) }, 100); } svgCanvas.pathActions.mouseMove(x, y); break; } case 'textedit': { - x *= currentZoom; - y *= currentZoom; - // if (eventContext_.getRubberBox() && eventContext_.getRubberBox().getAttribute('display') !== 'none') { - // assignAttributes(eventContext_.getRubberBox(), { - // x: Math.min(eventContext_.getStartX(), x), - // y: Math.min(eventContext_.getStartY(), y), - // width: Math.abs(x - eventContext_.getStartX()), - // height: Math.abs(y - eventContext_.getStartY()) + x *= zoom; + y *= zoom; + // if (svgCanvas.getRubberBox() && svgCanvas.getRubberBox().getAttribute('display') !== 'none') { + // assignAttributes(svgCanvas.getRubberBox(), { + // x: Math.min(svgCanvas.getStartX(), x), + // y: Math.min(svgCanvas.getStartY(), y), + // width: Math.abs(x - svgCanvas.getStartX()), + // height: Math.abs(y - svgCanvas.getStartY()) // }, 100); // } @@ -486,7 +485,7 @@ export const mouseMoveEvent = function (evt) { cx = center.x; cy = center.y; angle = ((Math.atan2(cy - y, cx - x) * (180 / Math.PI)) - 90) % 360; - if (eventContext_.getCurConfig().gridSnapping) { + if (svgCanvas.getCurConfig().gridSnapping) { angle = snapToGrid(angle); } if (evt.shiftKey) { // restrict rotations to nice angles (WRS) @@ -522,10 +521,9 @@ export const mouseMoveEvent = function (evt) { * * @returns {void} */ -export const mouseOutEvent = function () { - const svgCanvas = eventContext_.getCanvas(); +export const mouseOutEvent = () => { const { $id } = svgCanvas; - if(eventContext_.getCurrentMode() !== 'select' && eventContext_.getStarted()) { + if(svgCanvas.getCurrentMode() !== 'select' && svgCanvas.getStarted()) { const event = new Event("mouseup"); $id('svgcanvas').dispatchEvent(event); } @@ -544,39 +542,38 @@ export const mouseOutEvent = function () { * @fires module:svgcanvas.SvgCanvas#event:ext_mouseUp * @returns {void} */ -export const mouseUpEvent = function (evt) { - const selectedElements = eventContext_.getSelectedElements(); - const currentZoom = eventContext_.getCurrentZoom(); - const svgCanvas = eventContext_.getCanvas(); +export const mouseUpEvent = (evt) => { + const selectedElements = svgCanvas.getSelectedElements(); + const zoom = svgCanvas.getZoom(); if (evt.button === 2) { return; } - const tempJustSelected = eventContext_.getJustSelected(); - eventContext_.setJustSelected(null); - if (!eventContext_.getStarted()) { return; } - const pt = transformPoint(evt.clientX, evt.clientY, eventContext_.getrootSctm()); - const mouseX = pt.x * currentZoom; - const mouseY = pt.y * currentZoom; - const x = mouseX / currentZoom; - const y = mouseY / currentZoom; + const tempJustSelected = svgCanvas.getJustSelected(); + svgCanvas.setJustSelected(null); + if (!svgCanvas.getStarted()) { return; } + const pt = transformPoint(evt.clientX, evt.clientY, svgCanvas.getrootSctm()); + const mouseX = pt.x * zoom; + const mouseY = pt.y * zoom; + const x = mouseX / zoom; + const y = mouseY / zoom; - let element = getElem(eventContext_.getId()); + let element = getElem(svgCanvas.getId()); let keep = false; const realX = x; const realY = y; // TODO: Make true when in multi-unit mode - const useUnit = false; // (eventContext_.getCurConfig().baseUnit !== 'px'); - eventContext_.setStarted(false); + const useUnit = false; // (svgCanvas.getCurConfig().baseUnit !== 'px'); + svgCanvas.setStarted(false); let t; - switch (eventContext_.getCurrentMode()) { + switch (svgCanvas.getCurrentMode()) { // intentionally fall-through to select here case 'resize': case 'multiselect': - if (eventContext_.getRubberBox()) { - eventContext_.getRubberBox().setAttribute('display', 'none'); - eventContext_.setCurBBoxes([]); + if (svgCanvas.getRubberBox()) { + svgCanvas.getRubberBox().setAttribute('display', 'none'); + svgCanvas.setCurBBoxes([]); } - eventContext_.setCurrentMode('select'); + svgCanvas.setCurrentMode('select'); // Fallthrough case 'select': if (selectedElements[0]) { @@ -591,26 +588,26 @@ export const mouseUpEvent = function (evt) { case 'foreignObject': break; default: - eventContext_.setCurProperties('fill', selected.getAttribute('fill')); - eventContext_.setCurProperties('fill_opacity', selected.getAttribute('fill-opacity')); - eventContext_.setCurProperties('stroke', selected.getAttribute('stroke')); - eventContext_.setCurProperties('stroke_opacity', selected.getAttribute('stroke-opacity')); - eventContext_.setCurProperties('stroke_width', selected.getAttribute('stroke-width')); - eventContext_.setCurProperties('stroke_dasharray', selected.getAttribute('stroke-dasharray')); - eventContext_.setCurProperties('stroke_linejoin', selected.getAttribute('stroke-linejoin')); - eventContext_.setCurProperties('stroke_linecap', selected.getAttribute('stroke-linecap')); + svgCanvas.setCurProperties('fill', selected.getAttribute('fill')); + svgCanvas.setCurProperties('fill_opacity', selected.getAttribute('fill-opacity')); + svgCanvas.setCurProperties('stroke', selected.getAttribute('stroke')); + svgCanvas.setCurProperties('stroke_opacity', selected.getAttribute('stroke-opacity')); + svgCanvas.setCurProperties('stroke_width', selected.getAttribute('stroke-width')); + svgCanvas.setCurProperties('stroke_dasharray', selected.getAttribute('stroke-dasharray')); + svgCanvas.setCurProperties('stroke_linejoin', selected.getAttribute('stroke-linejoin')); + svgCanvas.setCurProperties('stroke_linecap', selected.getAttribute('stroke-linecap')); } if (selected.tagName === 'text') { - eventContext_.setCurText('font_size', selected.getAttribute('font-size')); - eventContext_.setCurText('font_family', selected.getAttribute('font-family')); + svgCanvas.setCurText('font_size', selected.getAttribute('font-size')); + svgCanvas.setCurText('font_family', selected.getAttribute('font-family')); } svgCanvas.selectorManager.requestSelector(selected).showGrips(true); } // always recalculate dimensions to strip off stray identity transforms svgCanvas.recalculateAllSelectedDimensions(); // if it was being dragged/resized - if (realX !== eventContext_.getRStartX() || realY !== eventContext_.getRStartY()) { + if (realX !== svgCanvas.getRStartX() || realY !== svgCanvas.getRStartY()) { const len = selectedElements.length; for (let i = 0; i < len; ++i) { if (isNullish(selectedElements[i])) { break; } @@ -631,7 +628,7 @@ export const mouseUpEvent = function (evt) { const elem = selectedElements[0]; if (elem) { elem.removeAttribute('style'); - walkTree(elem, function (el) { + walkTree(elem, (el) => { el.removeAttribute('style'); }); } @@ -639,15 +636,15 @@ export const mouseUpEvent = function (evt) { } return; case 'zoom': { - if (!isNullish(eventContext_.getRubberBox())) { - eventContext_.getRubberBox().setAttribute('display', 'none'); + if (!isNullish(svgCanvas.getRubberBox())) { + svgCanvas.getRubberBox().setAttribute('display', 'none'); } const factor = evt.shiftKey ? 0.5 : 2; svgCanvas.call('zoomed', { - x: Math.min(eventContext_.getRStartX(), realX), - y: Math.min(eventContext_.getRStartY(), realY), - width: Math.abs(realX - eventContext_.getRStartX()), - height: Math.abs(realY - eventContext_.getRStartY()), + x: Math.min(svgCanvas.getRStartX(), realX), + y: Math.min(svgCanvas.getRStartY(), realY), + width: Math.abs(realX - svgCanvas.getRStartX()), + height: Math.abs(realY - svgCanvas.getRStartY()), factor }); return; @@ -656,14 +653,14 @@ export const mouseUpEvent = function (evt) { // causes problems. // Webkit ignores how we set the points attribute with commas and uses space // to separate all coordinates, see https://bugs.webkit.org/show_bug.cgi?id=29870 - eventContext_.setSumDistance(0); - eventContext_.setControllPoint2('x', 0); - eventContext_.setControllPoint2('y', 0); - eventContext_.setControllPoint1('x', 0); - eventContext_.setControllPoint1('y', 0); - eventContext_.setStart({ x: 0, y: 0 }); - eventContext_.setEnd('x', 0); - eventContext_.setEnd('y', 0); + svgCanvas.setSumDistance(0); + svgCanvas.setControllPoint2('x', 0); + svgCanvas.setControllPoint2('y', 0); + svgCanvas.setControllPoint1('x', 0); + svgCanvas.setControllPoint1('y', 0); + svgCanvas.setStart({ x: 0, y: 0 }); + svgCanvas.setEnd('x', 0); + svgCanvas.setEnd('y', 0); const coords = element.getAttribute('points'); const commaIndex = coords.indexOf(','); keep = commaIndex >= 0 ? coords.includes(',', commaIndex + 1) : coords.includes(' ', coords.indexOf(' ') + 1); @@ -686,7 +683,7 @@ export const mouseUpEvent = function (evt) { const width = element.getAttribute('width'); const height = element.getAttribute('height'); // Image should be kept regardless of size (use inherit dimensions later) - keep = (width || height) || eventContext_.getCurrentMode() === 'image'; + keep = (width || height) || svgCanvas.getCurrentMode() === 'image'; } break; case 'circle': @@ -699,17 +696,17 @@ export const mouseUpEvent = function (evt) { } break; case 'fhellipse': - if ((eventContext_.getFreehand('maxx') - eventContext_.getFreehand('minx')) > 0 && - (eventContext_.getFreehand('maxy') - eventContext_.getFreehand('miny')) > 0) { - element = svgCanvas.addSVGElementFromJson({ + if ((svgCanvas.getFreehand('maxx') - svgCanvas.getFreehand('minx')) > 0 && + (svgCanvas.getFreehand('maxy') - svgCanvas.getFreehand('miny')) > 0) { + element = svgCanvas.addSVGElemensFromJson({ element: 'ellipse', curStyles: true, attr: { - cx: (eventContext_.getFreehand('minx') + eventContext_.getFreehand('maxx')) / 2, - cy: (eventContext_.getFreehand('miny') + eventContext_.getFreehand('maxy')) / 2, - rx: (eventContext_.getFreehand('maxx') - eventContext_.getFreehand('minx')) / 2, - ry: (eventContext_.getFreehand('maxy') - eventContext_.getFreehand('miny')) / 2, - id: eventContext_.getId() + cx: (svgCanvas.getFreehand('minx') + svgCanvas.getFreehand('maxx')) / 2, + cy: (svgCanvas.getFreehand('miny') + svgCanvas.getFreehand('maxy')) / 2, + rx: (svgCanvas.getFreehand('maxx') - svgCanvas.getFreehand('minx')) / 2, + ry: (svgCanvas.getFreehand('maxy') - svgCanvas.getFreehand('miny')) / 2, + id: svgCanvas.getId() } }); svgCanvas.call('changed', [ element ]); @@ -717,17 +714,17 @@ export const mouseUpEvent = function (evt) { } break; case 'fhrect': - if ((eventContext_.getFreehand('maxx') - eventContext_.getFreehand('minx')) > 0 && - (eventContext_.getFreehand('maxy') - eventContext_.getFreehand('miny')) > 0) { - element = svgCanvas.addSVGElementFromJson({ + if ((svgCanvas.getFreehand('maxx') - svgCanvas.getFreehand('minx')) > 0 && + (svgCanvas.getFreehand('maxy') - svgCanvas.getFreehand('miny')) > 0) { + element = svgCanvas.addSVGElemensFromJson({ element: 'rect', curStyles: true, attr: { - x: eventContext_.getFreehand('minx'), - y: eventContext_.getFreehand('miny'), - width: (eventContext_.getFreehand('maxx') - eventContext_.getFreehand('minx')), - height: (eventContext_.getFreehand('maxy') - eventContext_.getFreehand('miny')), - id: eventContext_.getId() + x: svgCanvas.getFreehand('minx'), + y: svgCanvas.getFreehand('miny'), + width: (svgCanvas.getFreehand('maxx') - svgCanvas.getFreehand('minx')), + height: (svgCanvas.getFreehand('maxy') - svgCanvas.getFreehand('miny')), + id: svgCanvas.getId() } }); svgCanvas.call('changed', [ element ]); @@ -743,7 +740,7 @@ export const mouseUpEvent = function (evt) { // set element to null here so that it is not removed nor finalized element = null; // continue to be set to true so that mouseMove happens - eventContext_.setStarted(true); + svgCanvas.setStarted(true); const res = svgCanvas.pathActions.mouseUp(evt, element, mouseX, mouseY); ({ element } = res); @@ -762,10 +759,10 @@ export const mouseUpEvent = function (evt) { case 'rotate': { keep = true; element = null; - eventContext_.setCurrentMode('select'); + svgCanvas.setCurrentMode('select'); const batchCmd = svgCanvas.undoMgr.finishUndoableChange(); if (!batchCmd.isEmpty()) { - eventContext_.addCommandToHistory(batchCmd); + svgCanvas.addCommandToHistory(batchCmd); } // perform recalculation to weed out any stray identity transforms that might get stuck svgCanvas.recalculateAllSelectedDimensions(); @@ -794,12 +791,12 @@ export const mouseUpEvent = function (evt) { if (r) { keep = r.keep || keep; ({ element } = r); - eventContext_.setStarted(r.started || eventContext_.getStarted()); + svgCanvas.setStarted(r.started || svgCanvas.getStarted()); } }); if (!keep && !isNullish(element)) { - svgCanvas.getCurrentDrawing().releaseId(eventContext_.getId()); + svgCanvas.getCurrentDrawing().releaseId(svgCanvas.getId()); element.remove(); element = null; @@ -814,7 +811,7 @@ export const mouseUpEvent = function (evt) { // if we are not in the middle of creating a path, and we've clicked on some shape, // then go to Select mode. // WebKit returns
when the canvas is clicked, Firefox/Opera return - if ((eventContext_.getCurrentMode() !== 'path' || !eventContext_.getDrawnPath()) && + if ((svgCanvas.getCurrentMode() !== 'path' || !svgCanvas.getDrawnPath()) && t && t.parentNode && t.parentNode.id !== 'selectorParentGroup' && t.id !== 'svgcanvas' && t.id !== 'svgroot' @@ -835,7 +832,7 @@ export const mouseUpEvent = function (evt) { let aniDur = 0.2; let cAni; const curShape = svgCanvas.getStyle(); - const opacAni = eventContext_.getOpacAni(); + const opacAni = svgCanvas.getOpacAni(); if (opacAni.beginElement && Number.parseFloat(element.getAttribute('opacity')) !== curShape.opacity) { cAni = opacAni.cloneNode(true); cAni.setAttribute('to', curShape.opacity); @@ -856,40 +853,39 @@ export const mouseUpEvent = function (evt) { element.setAttribute('opacity', curShape.opacity); element.setAttribute('style', 'pointer-events:inherit'); cleanupElement(element); - if (eventContext_.getCurrentMode() === 'path') { + if (svgCanvas.getCurrentMode() === 'path') { svgCanvas.pathActions.toEditMode(element); - } else if (eventContext_.getCurConfig().selectNew) { + } else if (svgCanvas.getCurConfig().selectNew) { const modes = [ 'circle', 'ellipse', 'square', 'rect', 'fhpath', 'line', 'fhellipse', 'fhrect', 'star', 'polygon' ]; - if ( modes.indexOf(eventContext_.getCurrentMode()) !== -1) { + if ( modes.indexOf(svgCanvas.getCurrentMode()) !== -1) { svgCanvas.setMode('select'); } svgCanvas.selectOnly([ element ], true); } // we create the insert command that is stored on the stack // undo means to call cmd.unapply(), redo means to call cmd.apply() - eventContext_.addCommandToHistory(new InsertElementCommand(element)); + svgCanvas.addCommandToHistory(new InsertElementCommand(element)); svgCanvas.call('changed', [ element ]); }, aniDur * 1000); } - eventContext_.setStartTransform(null); + svgCanvas.setStartTransform(null); }; -export const dblClickEvent = function (evt) { - const selectedElements = eventContext_.getSelectedElements(); +export const dblClickEvent = (evt) => { + const selectedElements = svgCanvas.getSelectedElements(); const evtTarget = evt.target; const parent = evtTarget.parentNode; - const svgCanvas = eventContext_.getCanvas(); let mouseTarget = svgCanvas.getMouseTarget(evt); const { tagName } = mouseTarget; - if (tagName === 'text' && eventContext_.getCurrentMode() !== 'textedit') { - const pt = transformPoint(evt.clientX, evt.clientY, eventContext_.getrootSctm()); + if (tagName === 'text' && svgCanvas.getCurrentMode() !== 'textedit') { + const pt = transformPoint(evt.clientX, evt.clientY, svgCanvas.getrootSctm()); svgCanvas.textActions.select(mouseTarget, pt.x, pt.y); } // Do nothing if already in current group - if (parent === eventContext_.getCurrentGroup()) { return; } + if (parent === svgCanvas.getCurrentGroup()) { return; } if ((tagName === 'g' || tagName === 'a') && getRotationAngle(mouseTarget)) { // TODO: Allow method of in-group editing without having to do @@ -901,7 +897,7 @@ export const dblClickEvent = function (evt) { svgCanvas.clearSelection(true); } // Reset context - if (eventContext_.getCurrentGroup()) { + if (svgCanvas.getCurrentGroup()) { draw.leaveContext(); } @@ -925,13 +921,12 @@ export const dblClickEvent = function (evt) { * @fires module:svgcanvas.SvgCanvas#event:ext_mouseDown * @returns {void} */ -export const mouseDownEvent = function (evt) { - const dataStorage = eventContext_.getDataStorage(); - const selectedElements = eventContext_.getSelectedElements; - const currentZoom = eventContext_.getCurrentZoom(); - const svgCanvas = eventContext_.getCanvas(); +export const mouseDownEvent = (evt) => { + const dataStorage = svgCanvas.getDataStorage(); + const selectedElements = svgCanvas.getSelectedElements(); + const zoom = svgCanvas.getZoom(); const curShape = svgCanvas.getStyle(); - const svgRoot = eventContext_.getSVGRoot(); + const svgRoot = svgCanvas.getSvgRoot(); const { $id } = svgCanvas; if (svgCanvas.spaceKey || evt.button === 1) { return; } @@ -942,24 +937,24 @@ export const mouseDownEvent = function (evt) { svgCanvas.cloneSelectedElements(0, 0); } - eventContext_.setRootSctm($id('svgcontent').querySelector('g').getScreenCTM().inverse()); + svgCanvas.setRootSctm($id('svgcontent').querySelector('g').getScreenCTM().inverse()); - const pt = transformPoint(evt.clientX, evt.clientY, eventContext_.getrootSctm()); - const mouseX = pt.x * currentZoom; - const mouseY = pt.y * currentZoom; + const pt = transformPoint(evt.clientX, evt.clientY, svgCanvas.getrootSctm()); + const mouseX = pt.x * zoom; + const mouseY = pt.y * zoom; evt.preventDefault(); if (rightClick) { - if(eventContext_.getCurrentMode() === 'path'){ + if(svgCanvas.getCurrentMode() === 'path'){ return; } - eventContext_.setCurrentMode('select'); - eventContext_.setLastClickPoint(pt); + svgCanvas.setCurrentMode('select'); + svgCanvas.setLastClickPoint(pt); } - let x = mouseX / currentZoom; - let y = mouseY / currentZoom; + let x = mouseX / zoom; + let y = mouseY / zoom; let mouseTarget = svgCanvas.getMouseTarget(evt); if (mouseTarget.tagName === 'a' && mouseTarget.childNodes.length === 1) { @@ -968,49 +963,49 @@ export const mouseDownEvent = function (evt) { // realX/y ignores grid-snap value const realX = x; - eventContext_.setStartX(x); - eventContext_.setRStartX(x); + svgCanvas.setStartX(x); + svgCanvas.setRStartX(x); const realY = y; - eventContext_.setStartY(y); - eventContext_.setRStartY(y); + svgCanvas.setStartY(y); + svgCanvas.setRStartY(y); - if (eventContext_.getCurConfig().gridSnapping) { + if (svgCanvas.getCurConfig().gridSnapping) { x = snapToGrid(x); y = snapToGrid(y); - eventContext_.setStartX(snapToGrid(eventContext_.getStartX())); - eventContext_.setStartY(snapToGrid(eventContext_.getStartY())); + svgCanvas.setStartX(snapToGrid(svgCanvas.getStartX())); + svgCanvas.setStartY(snapToGrid(svgCanvas.getStartY())); } // if it is a selector grip, then it must be a single element selected, // set the mouseTarget to that and update the mode to rotate/resize - if (mouseTarget === svgCanvas.selectorManager.selectorParentGroup && !isNullish(selectedElements()[0])) { + if (mouseTarget === svgCanvas.selectorManager.selectorParentGroup && !isNullish(selectedElements[0])) { const grip = evt.target; const griptype = dataStorage.get(grip, 'type'); // rotating if (griptype === 'rotate') { - eventContext_.setCurrentMode('rotate'); - // eventContext_.setCurrentRotateMode(dataStorage.get(grip, 'dir')); + svgCanvas.setCurrentMode('rotate'); + // svgCanvas.setCurrentRotateMode(dataStorage.get(grip, 'dir')); // resizing } else if (griptype === 'resize') { - eventContext_.setCurrentMode('resize'); - eventContext_.setCurrentResizeMode(dataStorage.get(grip, 'dir')); + svgCanvas.setCurrentMode('resize'); + svgCanvas.setCurrentResizeMode(dataStorage.get(grip, 'dir')); } - mouseTarget = selectedElements()[0]; + mouseTarget = selectedElements[0]; } - eventContext_.setStartTransform(mouseTarget.getAttribute('transform')); + svgCanvas.setStartTransform(mouseTarget.getAttribute('transform')); const tlist = mouseTarget.transform.baseVal; - switch (eventContext_.getCurrentMode()) { + switch (svgCanvas.getCurrentMode()) { case 'select': - eventContext_.setStarted(true); - eventContext_.setCurrentResizeMode('none'); - if (rightClick) { eventContext_.setStarted(false); } + svgCanvas.setStarted(true); + svgCanvas.setCurrentResizeMode('none'); + if (rightClick) { svgCanvas.setStarted(false); } if (mouseTarget !== svgRoot) { // if this element is not yet selected, clear selection and select it - if (!selectedElements().includes(mouseTarget)) { + if (!selectedElements.includes(mouseTarget)) { // only clear selection if shift is not pressed (otherwise, add // element to selection) if (!evt.shiftKey) { @@ -1018,7 +1013,7 @@ export const mouseDownEvent = function (evt) { svgCanvas.clearSelection(true); } svgCanvas.addToSelection([ mouseTarget ]); - eventContext_.setJustSelected(mouseTarget); + svgCanvas.setJustSelected(mouseTarget); svgCanvas.pathActions.clear(); } // else if it's a path, go into pathedit mode in mouseup @@ -1026,7 +1021,7 @@ export const mouseDownEvent = function (evt) { if (!rightClick) { // insert a dummy transform so if the element(s) are moved it will have // a transform to use for its translate - for (const selectedElement of selectedElements()) { + for (const selectedElement of selectedElements) { if (isNullish(selectedElement)) { continue; } const slist = selectedElement.transform?.baseVal; if (slist.numberOfItems) { @@ -1038,16 +1033,16 @@ export const mouseDownEvent = function (evt) { } } else if (!rightClick) { svgCanvas.clearSelection(); - eventContext_.setCurrentMode('multiselect'); - if (isNullish(eventContext_.getRubberBox())) { - eventContext_.setRubberBox(svgCanvas.selectorManager.getRubberBandBox()); + svgCanvas.setCurrentMode('multiselect'); + if (isNullish(svgCanvas.getRubberBox())) { + svgCanvas.setRubberBox(svgCanvas.selectorManager.getRubberBandBox()); } - eventContext_.setRStartX(eventContext_.getRStartX() * currentZoom); - eventContext_.setRStartY(eventContext_.getRStartY() * currentZoom); + svgCanvas.setRStartX(svgCanvas.getRStartX() * zoom); + svgCanvas.setRStartY(svgCanvas.getRStartY() * zoom); - assignAttributes(eventContext_.getRubberBox(), { - x: eventContext_.getRStartX(), - y: eventContext_.getRStartY(), + assignAttributes(svgCanvas.getRubberBox(), { + x: svgCanvas.getRStartX(), + y: svgCanvas.getRStartY(), width: 0, height: 0, display: 'inline' @@ -1055,31 +1050,31 @@ export const mouseDownEvent = function (evt) { } break; case 'zoom': - eventContext_.setStarted(true); - if (isNullish(eventContext_.getRubberBox())) { - eventContext_.setRubberBox(svgCanvas.selectorManager.getRubberBandBox()); + svgCanvas.setStarted(true); + if (isNullish(svgCanvas.getRubberBox())) { + svgCanvas.setRubberBox(svgCanvas.selectorManager.getRubberBandBox()); } - assignAttributes(eventContext_.getRubberBox(), { - x: realX * currentZoom, - y: realX * currentZoom, + assignAttributes(svgCanvas.getRubberBox(), { + x: realX * zoom, + y: realX * zoom, width: 0, height: 0, display: 'inline' }, 100); break; case 'resize': { - eventContext_.setStarted(true); - eventContext_.setStartX(x); - eventContext_.setStartY(y); + svgCanvas.setStarted(true); + svgCanvas.setStartX(x); + svgCanvas.setStartY(y); // Getting the BBox from the selection box, since we know we // want to orient around it - eventContext_.setInitBbox(getBBox($id('selectedBox0'))); + svgCanvas.setInitBbox(getBBox($id('selectedBox0'))); const bb = {}; - for (const [ key, val ] of Object.entries(eventContext_.getInitBbox())) { - bb[key] = val / currentZoom; + for (const [ key, val ] of Object.entries(svgCanvas.getInitBbox())) { + bb[key] = val / zoom; } - eventContext_.setInitBbox(bb); + svgCanvas.setInitBbox(bb); // append three dummy transforms to the tlist so that // we can translate,scale,translate in mousemove @@ -1099,20 +1094,20 @@ export const mouseDownEvent = function (evt) { case 'fhellipse': case 'fhrect': case 'fhpath': - eventContext_.setStart({ x: realX, y: realY }); - eventContext_.setControllPoint1('x', 0); - eventContext_.setControllPoint1('y', 0); - eventContext_.setControllPoint2('x', 0); - eventContext_.setControllPoint2('y', 0); - eventContext_.setStarted(true); - eventContext_.setDAttr(realX + ',' + realY + ' '); + svgCanvas.setStart({ x: realX, y: realY }); + svgCanvas.setControllPoint1('x', 0); + svgCanvas.setControllPoint1('y', 0); + svgCanvas.setControllPoint2('x', 0); + svgCanvas.setControllPoint2('y', 0); + svgCanvas.setStarted(true); + svgCanvas.setDAttr(realX + ',' + realY + ' '); // Commented out as doing nothing now: // strokeW = parseFloat(curShape.stroke_width) === 0 ? 1 : curShape.stroke_width; - svgCanvas.addSVGElementFromJson({ + svgCanvas.addSVGElemensFromJson({ element: 'polyline', curStyles: true, attr: { - points: eventContext_.getDAttr(), + points: svgCanvas.getDAttr(), id: svgCanvas.getNextId(), fill: 'none', opacity: curShape.opacity / 2, @@ -1120,14 +1115,14 @@ export const mouseDownEvent = function (evt) { style: 'pointer-events:none' } }); - eventContext_.setFreehand('minx', realX); - eventContext_.setFreehand('maxx', realX); - eventContext_.setFreehand('miny', realY); - eventContext_.setFreehand('maxy', realY); + svgCanvas.setFreehand('minx', realX); + svgCanvas.setFreehand('maxx', realX); + svgCanvas.setFreehand('miny', realY); + svgCanvas.setFreehand('maxy', realY); break; case 'image': { - eventContext_.setStarted(true); - const newImage = svgCanvas.addSVGElementFromJson({ + svgCanvas.setStarted(true); + const newImage = svgCanvas.addSVGElemensFromJson({ element: 'image', attr: { x, @@ -1139,7 +1134,7 @@ export const mouseDownEvent = function (evt) { style: 'pointer-events:inherit' } }); - setHref(newImage, eventContext_.getLastGoodImgUrl()); + setHref(newImage, svgCanvas.getLastGoodImgUrl()); preventClickDefault(newImage); break; } case 'square': @@ -1147,10 +1142,10 @@ export const mouseDownEvent = function (evt) { // (for resizing purposes this could be important) // Fallthrough case 'rect': - eventContext_.setStarted(true); - eventContext_.setStartX(x); - eventContext_.setStartY(y); - svgCanvas.addSVGElementFromJson({ + svgCanvas.setStarted(true); + svgCanvas.setStartX(x); + svgCanvas.setStartY(y); + svgCanvas.addSVGElemensFromJson({ element: 'rect', curStyles: true, attr: { @@ -1164,9 +1159,9 @@ export const mouseDownEvent = function (evt) { }); break; case 'line': { - eventContext_.setStarted(true); + svgCanvas.setStarted(true); const strokeW = Number(curShape.stroke_width) === 0 ? 1 : curShape.stroke_width; - svgCanvas.addSVGElementFromJson({ + svgCanvas.addSVGElemensFromJson({ element: 'line', curStyles: true, attr: { @@ -1188,8 +1183,8 @@ export const mouseDownEvent = function (evt) { }); break; } case 'circle': - eventContext_.setStarted(true); - svgCanvas.addSVGElementFromJson({ + svgCanvas.setStarted(true); + svgCanvas.addSVGElemensFromJson({ element: 'circle', curStyles: true, attr: { @@ -1202,8 +1197,8 @@ export const mouseDownEvent = function (evt) { }); break; case 'ellipse': - eventContext_.setStarted(true); - svgCanvas.addSVGElementFromJson({ + svgCanvas.setStarted(true); + svgCanvas.addSVGElemensFromJson({ element: 'ellipse', curStyles: true, attr: { @@ -1217,18 +1212,18 @@ export const mouseDownEvent = function (evt) { }); break; case 'text': - eventContext_.setStarted(true); - /* const newText = */ svgCanvas.addSVGElementFromJson({ + svgCanvas.setStarted(true); + /* const newText = */ svgCanvas.addSVGElemensFromJson({ element: 'text', curStyles: true, attr: { x, y, id: svgCanvas.getNextId(), - fill: eventContext_.getCurText('fill'), - 'stroke-width': eventContext_.getCurText('stroke_width'), - 'font-size': eventContext_.getCurText('font_size'), - 'font-family': eventContext_.getCurText('font_family'), + fill: svgCanvas.getCurText('fill'), + 'stroke-width': svgCanvas.getCurText('stroke_width'), + 'font-size': svgCanvas.getCurText('font_size'), + 'font-family': svgCanvas.getCurText('font_family'), 'text-anchor': 'middle', 'xml:space': 'preserve', opacity: curShape.opacity @@ -1239,21 +1234,21 @@ export const mouseDownEvent = function (evt) { case 'path': // Fall through case 'pathedit': - eventContext_.setStartX(eventContext_.getStartX() * currentZoom); - eventContext_.setStartY(eventContext_.getStartY() * currentZoom); - svgCanvas.pathActions.mouseDown(evt, mouseTarget, eventContext_.getStartX(), eventContext_.getStartY()); - eventContext_.setStarted(true); + svgCanvas.setStartX(svgCanvas.getStartX() * zoom); + svgCanvas.setStartY(svgCanvas.getStartY() * zoom); + svgCanvas.pathActions.mouseDown(evt, mouseTarget, svgCanvas.getStartX(), svgCanvas.getStartY()); + svgCanvas.setStarted(true); break; case 'textedit': - eventContext_.setStartX(eventContext_.getStartX() * currentZoom); - eventContext_.setStartY(eventContext_.getStartY() * currentZoom); - svgCanvas.textActions.mouseDown(evt, mouseTarget, eventContext_.getStartX(), eventContext_.getStartY()); - eventContext_.setStarted(true); + svgCanvas.setStartX(svgCanvas.getStartX() * zoom); + svgCanvas.setStartY(svgCanvas.getStartY() * zoom); + svgCanvas.textActions.mouseDown(evt, mouseTarget, svgCanvas.getStartX(), svgCanvas.getStartY()); + svgCanvas.setStarted(true); break; case 'rotate': - eventContext_.setStarted(true); + svgCanvas.setStarted(true); // we are starting an undoable change (a drag-rotation) - svgCanvas.undoMgr.beginUndoableChange('transform', selectedElements()); + svgCanvas.undoMgr.beginUndoableChange('transform', selectedElements); break; default: // This could occur in an extension @@ -1271,14 +1266,14 @@ export const mouseDownEvent = function (evt) { */ const extResult = svgCanvas.runExtensions('mouseDown', { event: evt, - start_x: eventContext_.getStartX(), - start_y: eventContext_.getStartY(), - selectedElements: selectedElements() + start_x: svgCanvas.getStartX(), + start_y: svgCanvas.getStartY(), + selectedElements }, true); - extResult.forEach(function(r){ + extResult.forEach((r) => { if (r && r.started) { - eventContext_.setStarted(true); + svgCanvas.setStarted(true); } }); }; @@ -1288,22 +1283,22 @@ export const mouseDownEvent = function (evt) { * @fires module:event.SvgCanvas#event:zoomDone * @returns {void} */ -export const DOMMouseScrollEvent = function (e) { - const currentZoom = eventContext_.getCurrentZoom(); - const svgCanvas = eventContext_.getCanvas(); +export const DOMMouseScrollEvent = (e) => { + const svgCanvas = this; // svgCanvas was bound to the handler + const zoom = svgCanvas.getZoom(); const { $id } = svgCanvas; if (!e.shiftKey) { return; } e.preventDefault(); - eventContext_.setRootSctm($id('svgcontent').querySelector('g').getScreenCTM().inverse()); + svgCanvas.setRootSctm($id('svgcontent').querySelector('g').getScreenCTM().inverse()); const workarea = document.getElementById('workarea'); const scrbar = 15; - const rulerwidth = eventContext_.getCurConfig().showRulers ? 16 : 0; + const rulerwidth = svgCanvas.getCurConfig().showRulers ? 16 : 0; // mouse relative to content area in content pixels - const pt = transformPoint(e.clientX, e.clientY, eventContext_.getrootSctm()); + const pt = transformPoint(e.clientX, e.clientY, svgCanvas.getrootSctm()); // full work area width in screen pixels const editorFullW = parseFloat(getComputedStyle(workarea, null).width.replace("px", "")); @@ -1314,8 +1309,8 @@ export const DOMMouseScrollEvent = function (e) { const editorH = editorFullH - scrbar - rulerwidth; // work area width in content pixels - const workareaViewW = editorW * eventContext_.getrootSctm().a; - const workareaViewH = editorH * eventContext_.getrootSctm().d; + const workareaViewW = editorW * svgCanvas.getrootSctm().a; + const workareaViewH = editorH * svgCanvas.getrootSctm().d; // content offset from canvas in screen pixels const wOffset = findPos(workarea); @@ -1337,13 +1332,13 @@ export const DOMMouseScrollEvent = function (e) { } let zoomlevel = Math.min(wZoom, hZoom); zoomlevel = Math.min(10, Math.max(0.01, zoomlevel)); - if (zoomlevel === currentZoom) { + if (zoomlevel === zoom) { return; } - factor = zoomlevel / currentZoom; + factor = zoomlevel / zoom; // top left of workarea in content pixels before zoom - const topLeftOld = transformPoint(wOffsetLeft, wOffsetTop, eventContext_.getrootSctm()); + const topLeftOld = transformPoint(wOffsetLeft, wOffsetTop, svgCanvas.getrootSctm()); // top left of workarea in content pixels after zoom const topLeftNew = { diff --git a/src/svgcanvas/json.js b/src/svgcanvas/json.js index 7967ca7f..5fea22ce 100644 --- a/src/svgcanvas/json.js +++ b/src/svgcanvas/json.js @@ -8,7 +8,7 @@ import { getElem, assignAttributes, cleanupElement } from './utilities.js'; import { NS } from './namespaces.js'; -let jsonContext_ = null; +let svgCanvas = null; let svgdoc_ = null; /** @@ -25,9 +25,9 @@ let svgdoc_ = null; * @param {module:json.jsonContext} jsonContext * @returns {void} */ -export const init = function (jsonContext) { - jsonContext_ = jsonContext; - svgdoc_ = jsonContext.getDOMDocument(); +export const init = function (canvas) { + svgCanvas = canvas; + svgdoc_ = canvas.getDOMDocument(); }; /** * @function module:json.getJsonFromSvgElements Iterate element and return json format @@ -61,7 +61,7 @@ export const getJsonFromSvgElements = (data) => { /** * This should really be an intersection implementing all rather than a union. * @name module:json.addSVGElementsFromJson -* @type {module:utilities.EditorContext#addSVGElementsFromJson|module:path.EditorContext#addSVGElementFromJson} +* @type {module:utilities.EditorContext#addSVGElementsFromJson|module:path.EditorContext#addSVGElemensFromJson} */ export const addSVGElementsFromJson = function (data) { @@ -69,7 +69,7 @@ export const addSVGElementsFromJson = function (data) { let shape = getElem(data.attr.id); // if shape is a path but we need to create a rect/ellipse, then remove the path - const currentLayer = jsonContext_.getDrawing().getCurrentLayer(); + const currentLayer = svgCanvas.getDrawing().getCurrentLayer(); if (shape && data.element !== shape.tagName) { shape.remove(); shape = null; @@ -78,10 +78,10 @@ export const addSVGElementsFromJson = function (data) { const ns = data.namespace || NS.SVG; shape = svgdoc_.createElementNS(ns, data.element); if (currentLayer) { - (jsonContext_.getCurrentGroup() || currentLayer).append(shape); + (svgCanvas.getCurrentGroup() || currentLayer).append(shape); } } - const curShape = jsonContext_.getCurShape(); + const curShape = svgCanvas.getCurShape(); if (data.curStyles) { assignAttributes(shape, { fill: curShape.fill, diff --git a/src/svgcanvas/paste-elem.js b/src/svgcanvas/paste-elem.js index b71e94d1..50449f96 100644 --- a/src/svgcanvas/paste-elem.js +++ b/src/svgcanvas/paste-elem.js @@ -7,15 +7,15 @@ const { InsertElementCommand, BatchCommand } = hstry; -let pasteContext_ = null; +let svgCanvas = null; /** * @function module:paste-elem.init * @param {module:paste-elem.pasteContext} pasteContext * @returns {void} */ -export const init = function (pasteContext) { - pasteContext_ = pasteContext; +export const init = function (canvas) { + svgCanvas = canvas; }; /** @@ -28,7 +28,7 @@ export const init = function (pasteContext) { * @returns {void} */ export const pasteElementsMethod = function (type, x, y) { - let clipb = JSON.parse(sessionStorage.getItem(pasteContext_.getClipBoardID())); + let clipb = JSON.parse(sessionStorage.getItem(svgCanvas.getClipBoardID())); if (!clipb) return; let len = clipb.length; if (!len) return; @@ -52,7 +52,7 @@ export const pasteElementsMethod = function (type, x, y) { */ function checkIDs (elem) { if (elem.attr && elem.attr.id) { - changedIDs[elem.attr.id] = pasteContext_.getCanvas().getNextId(); + changedIDs[elem.attr.id] = svgCanvas.getNextId(); elem.attr.id = changedIDs[elem.attr.id]; } if (elem.children) elem.children.forEach((child) => checkIDs(child)); @@ -67,7 +67,7 @@ export const pasteElementsMethod = function (type, x, y) { * @property {module:svgcanvas.SVGAsJSON[]} elems * @property {module:svgcanvas.ChangedIDs} changes Maps past ID (on attribute) to current ID */ - pasteContext_.getCanvas().runExtensions( + svgCanvas.runExtensions( 'IDsUpdated', /** @type {module:svgcanvas.SvgCanvas#event:ext_IDsUpdated} */ { elems: clipb, changes: changedIDs }, @@ -87,21 +87,21 @@ export const pasteElementsMethod = function (type, x, y) { const elem = clipb[len]; if (!elem) { continue; } - const copy = pasteContext_.getCanvas().addSVGElementFromJson(elem); + const copy = svgCanvas.addSVGElemensFromJson(elem); pasted.push(copy); batchCmd.addSubCommand(new InsertElementCommand(copy)); - pasteContext_.restoreRefElems(copy); + svgCanvas.restoreRefElements(copy); } - pasteContext_.getCanvas().selectOnly(pasted); + svgCanvas.selectOnly(pasted); if (type !== 'in_place') { let ctrX; let ctrY; if (!type) { - ctrX = pasteContext_.getLastClickPoint('x'); - ctrY = pasteContext_.getLastClickPoint('y'); + ctrX = svgCanvas.getLastClickPoint('x'); + ctrY = svgCanvas.getLastClickPoint('y'); } else if (type === 'point') { ctrX = x; ctrY = y; @@ -118,10 +118,10 @@ export const pasteElementsMethod = function (type, x, y) { dy.push(cy); }); - const cmd = pasteContext_.getCanvas().moveSelectedElements(dx, dy, false); + const cmd = svgCanvas.moveSelectedElements(dx, dy, false); if (cmd) batchCmd.addSubCommand(cmd); } - pasteContext_.addCommandToHistory(batchCmd); - pasteContext_.getCanvas().call('changed', pasted); + svgCanvas.addCommandToHistory(batchCmd); + svgCanvas.call('changed', pasted); }; diff --git a/src/svgcanvas/path-actions.js b/src/svgcanvas/path-actions.js index d35fee3f..daf911f7 100644 --- a/src/svgcanvas/path-actions.js +++ b/src/svgcanvas/path-actions.js @@ -18,19 +18,16 @@ import { getBBox } from './utilities.js'; -let pathActionsContext_ = null; -let editorContext_ = null; +let svgCanvas = null; let path = null; /** * @function module:path-actions.init -* @param {module:path-actions.pathActionsContext_} pathActionsContext +* @param {module:path-actions.svgCanvas} pathActionsContext * @returns {void} */ -export const init = function (pathActionsContext) { - pathActionsContext_ = pathActionsContext; - // editorContext_ = pathActionsContext_.getEditorContext(); - // path = pathActionsContext_.getPathObj(); +export const init = function (canvas) { + svgCanvas = canvas; }; /** @@ -59,7 +56,7 @@ export const convertPath = function (pth, toRel) { let y2 = seg.y2 || 0; // const type = seg.pathSegType; - // const pathMap = pathActionsContext_.getPathMap(); + // const pathMap = svgCanvas.getPathMap(); // let letter = pathMap[type][toRel ? 'toLowerCase' : 'toUpperCase'](); let letter = seg.pathSegTypeAsLetter; @@ -246,8 +243,8 @@ export const pathActionsMethod = (function () { let currentPath = null; let hasMoved = false; - // No `editorContext_` yet but should be ok as is `null` by default - // editorContext_.setDrawnPath(null); + // No `svgCanvas` yet but should be ok as is `null` by default + // svgCanvas.setDrawnPath(null); /** * This function converts a polyline (created by the fh_path tool) into @@ -286,7 +283,7 @@ export const pathActionsMethod = (function () { // if the previous segment had a control point, we want to smooth out // the control points on both sides if (prevCtlPt) { - const newpts = pathActionsContext_.smoothControlPoints(prevCtlPt, ct1, curpos); + const newpts = svgCanvas.smoothControlPoints(prevCtlPt, ct1, curpos); if (newpts && newpts.length === 2) { const prevArr = d[d.length - 1].split(','); prevArr[2] = newpts[0].x; @@ -310,13 +307,11 @@ export const pathActionsMethod = (function () { } d = d.join(' '); - // create new path element - editorContext_ = pathActionsContext_.getEditorContext(); - element = editorContext_.addSVGElementFromJson({ + element = svgCanvas.addSVGElemensFromJson({ element: 'path', curStyles: true, attr: { - id: editorContext_.getId(), + id: svgCanvas.getId(), d, fill: 'none' } @@ -336,18 +331,17 @@ export const pathActionsMethod = (function () { */ mouseDown (evt, mouseTarget, startX, startY) { let id; - editorContext_ = pathActionsContext_.getEditorContext(); - if (editorContext_.getCurrentMode() === 'path') { + if (svgCanvas.getCurrentMode() === 'path') { let mouseX = startX; // Was this meant to work with the other `mouseX`? (was defined globally so adding `let` to at least avoid a global) let mouseY = startY; // Was this meant to work with the other `mouseY`? (was defined globally so adding `let` to at least avoid a global) - const currentZoom = editorContext_.getCurrentZoom(); - let x = mouseX / currentZoom; - let y = mouseY / currentZoom; + const zoom = svgCanvas.getZoom(); + let x = mouseX / zoom; + let y = mouseY / zoom; let stretchy = getElem('path_stretch_line'); newPoint = [ x, y ]; - if (editorContext_.getGridSnapping()) { + if (svgCanvas.getGridSnapping()) { x = snapToGrid(x); y = snapToGrid(y); mouseX = snapToGrid(mouseX); @@ -369,27 +363,27 @@ export const pathActionsMethod = (function () { let keep = null; let index; // if pts array is empty, create path element with M at current point - const drawnPath = editorContext_.getDrawnPath(); + const drawnPath = svgCanvas.getDrawnPath(); if (!drawnPath) { const dAttr = 'M' + x + ',' + y + ' '; // Was this meant to work with the other `dAttr`? (was defined globally so adding `var` to at least avoid a global) - /* drawnPath = */ editorContext_.setDrawnPath(editorContext_.addSVGElementFromJson({ + /* drawnPath = */ svgCanvas.setDrawnPath(svgCanvas.addSVGElemensFromJson({ element: 'path', curStyles: true, attr: { d: dAttr, - id: editorContext_.getNextId(), - opacity: editorContext_.getOpacity() / 2 + id: svgCanvas.getNextId(), + opacity: svgCanvas.getOpacity() / 2 } })); // set stretchy line to first point stretchy.setAttribute('d', [ 'M', mouseX, mouseY, mouseX, mouseY ].join(' ')); index = subpath ? path.segs.length : 0; - pathActionsContext_.addPointGrip(index, mouseX, mouseY); + svgCanvas.addPointGrip(index, mouseX, mouseY); } else { // determine if we clicked on an existing point const seglist = drawnPath.pathSegList; let i = seglist.numberOfItems; - const FUZZ = 6 / currentZoom; + const FUZZ = 6 / zoom; let clickOnPoint = false; while (i) { i--; @@ -405,10 +399,10 @@ export const pathActionsMethod = (function () { } // get path element that we are in the process of creating - id = editorContext_.getId(); + id = svgCanvas.getId(); // Remove previous path object if previously created - pathActionsContext_.removePath_(id); + svgCanvas.removePath_(id); const newpath = getElem(id); let newseg; @@ -429,7 +423,7 @@ export const pathActionsMethod = (function () { sSeg = stretchy.pathSegList.getItem(1); newseg = sSeg.pathSegType === 4 ? drawnPath.createSVGPathSegLinetoAbs(absX, absY) - : drawnPath.createSVGPathSegCurvetoCubicAbs(absX, absY, sSeg.x1 / currentZoom, sSeg.y1 / currentZoom, absX, absY); + : drawnPath.createSVGPathSegCurvetoCubicAbs(absX, absY, sSeg.x1 / zoom, sSeg.y1 / zoom, absX, absY); const endseg = drawnPath.createSVGPathSegClosePath(); seglist.appendItem(newseg); @@ -442,12 +436,12 @@ export const pathActionsMethod = (function () { // This will signal to commit the path // const element = newpath; // Other event handlers define own `element`, so this was probably not meant to interact with them or one which shares state (as there were none); I therefore adding a missing `var` to avoid a global - /* drawnPath = */ editorContext_.setDrawnPath(null); - editorContext_.setStarted(false); + /* drawnPath = */ svgCanvas.setDrawnPath(null); + svgCanvas.setStarted(false); if (subpath) { if (path.matrix) { - editorContext_.remapElement(newpath, {}, path.matrix.inverse()); + svgCanvas.remapElement(newpath, {}, path.matrix.inverse()); } const newD = newpath.getAttribute('d'); @@ -455,7 +449,7 @@ export const pathActionsMethod = (function () { path.elem.setAttribute('d', origD + newD); newpath.parentNode.removeChild(newpath); if (path.matrix) { - pathActionsContext_.recalcRotatedPath(); + svgCanvas.recalcRotatedPath(); } pathActionsMethod.toEditMode(path.elem); path.selectPt(); @@ -464,8 +458,8 @@ export const pathActionsMethod = (function () { // else, create a new point, update path element } else { // Checks if current target or parents are #svgcontent - if (!(editorContext_.getContainer() !== editorContext_.getMouseTarget(evt) && editorContext_.getContainer().contains( - editorContext_.getMouseTarget(evt) + if (!(svgCanvas.getContainer() !== svgCanvas.getMouseTarget(evt) && svgCanvas.getContainer().contains( + svgCanvas.getMouseTarget(evt) ))) { // Clicked outside canvas, so don't make point return false; @@ -483,26 +477,26 @@ export const pathActionsMethod = (function () { // Use the segment defined by stretchy sSeg = stretchy.pathSegList.getItem(1); newseg = sSeg.pathSegType === 4 - ? drawnPath.createSVGPathSegLinetoAbs(editorContext_.round(x), editorContext_.round(y)) + ? drawnPath.createSVGPathSegLinetoAbs(svgCanvas.round(x), svgCanvas.round(y)) : drawnPath.createSVGPathSegCurvetoCubicAbs( - editorContext_.round(x), - editorContext_.round(y), - sSeg.x1 / currentZoom, - sSeg.y1 / currentZoom, - sSeg.x2 / currentZoom, - sSeg.y2 / currentZoom + svgCanvas.round(x), + svgCanvas.round(y), + sSeg.x1 / zoom, + sSeg.y1 / zoom, + sSeg.x2 / zoom, + sSeg.y2 / zoom ); drawnPath.pathSegList.appendItem(newseg); - x *= currentZoom; - y *= currentZoom; + x *= zoom; + y *= zoom; // set stretchy line to latest point stretchy.setAttribute('d', [ 'M', x, y, x, y ].join(' ')); index = num; if (subpath) { index += path.segs.length; } - pathActionsContext_.addPointGrip(index, x, y); + svgCanvas.addPointGrip(index, x, y); } // keep = true; } @@ -546,16 +540,16 @@ export const pathActionsMethod = (function () { // Start selection box if (!path.dragging) { - let rubberBox = editorContext_.getRubberBox(); + let rubberBox = svgCanvas.getRubberBox(); if (isNullish(rubberBox)) { - rubberBox = editorContext_.setRubberBox( - editorContext_.selectorManager.getRubberBandBox() + rubberBox = svgCanvas.setRubberBox( + svgCanvas.selectorManager.getRubberBandBox() ); } - const currentZoom = editorContext_.getCurrentZoom(); + const zoom = svgCanvas.getZoom(); assignAttributes(rubberBox, { - x: startX * currentZoom, - y: startY * currentZoom, + x: startX * zoom, + y: startY * zoom, width: 0, height: 0, display: 'inline' @@ -569,11 +563,10 @@ export const pathActionsMethod = (function () { * @returns {void} */ mouseMove (mouseX, mouseY) { - editorContext_ = pathActionsContext_.getEditorContext(); - const currentZoom = editorContext_.getCurrentZoom(); + const zoom = svgCanvas.getZoom(); hasMoved = true; - const drawnPath = editorContext_.getDrawnPath(); - if (editorContext_.getCurrentMode() === 'path') { + const drawnPath = svgCanvas.getDrawnPath(); + if (svgCanvas.getCurrentMode() === 'path') { if (!drawnPath) { return; } const seglist = drawnPath.pathSegList; const index = seglist.numberOfItems - 1; @@ -583,8 +576,8 @@ export const pathActionsMethod = (function () { // if (!index) { return; } // Set control points - const pointGrip1 = pathActionsContext_.addCtrlGrip('1c1'); - const pointGrip2 = pathActionsContext_.addCtrlGrip('0c2'); + const pointGrip1 = svgCanvas.addCtrlGrip('1c1'); + const pointGrip2 = svgCanvas.addCtrlGrip('0c2'); // dragging pointGrip1 pointGrip1.setAttribute('cx', mouseX); @@ -596,21 +589,21 @@ export const pathActionsMethod = (function () { // set curve // const seg = seglist.getItem(index); - const curX = mouseX / currentZoom; - const curY = mouseY / currentZoom; + const curX = mouseX / zoom; + const curY = mouseY / zoom; const altX = (ptX + (ptX - curX)); const altY = (ptY + (ptY - curY)); - pointGrip2.setAttribute('cx', altX * currentZoom); - pointGrip2.setAttribute('cy', altY * currentZoom); + pointGrip2.setAttribute('cx', altX * zoom); + pointGrip2.setAttribute('cy', altY * zoom); pointGrip2.setAttribute('display', 'inline'); - const ctrlLine = pathActionsContext_.getCtrlLine(1); + const ctrlLine = svgCanvas.getCtrlLine(1); assignAttributes(ctrlLine, { x1: mouseX, y1: mouseY, - x2: altX * currentZoom, - y2: altY * currentZoom, + x2: altX * zoom, + y2: altY * zoom, display: 'inline' }); @@ -625,10 +618,10 @@ export const pathActionsMethod = (function () { lastX += (lastX - last.x2); lastY += (lastY - last.y2); } else if (firstCtrl) { - lastX = firstCtrl[0] / currentZoom; - lastY = firstCtrl[1] / currentZoom; + lastX = firstCtrl[0] / zoom; + lastY = firstCtrl[1] / zoom; } - pathActionsContext_.replacePathSeg(6, index, [ ptX, ptY, lastX, lastY, altX, altY ], drawnPath); + svgCanvas.replacePathSeg(6, index, [ ptX, ptY, lastX, lastY, altX, altY ], drawnPath); } } else { const stretchy = getElem('path_stretch_line'); @@ -637,16 +630,16 @@ export const pathActionsMethod = (function () { if (prev.pathSegType === 6) { const prevX = prev.x + (prev.x - prev.x2); const prevY = prev.y + (prev.y - prev.y2); - pathActionsContext_.replacePathSeg( + svgCanvas.replacePathSeg( 6, 1, - [ mouseX, mouseY, prevX * currentZoom, prevY * currentZoom, mouseX, mouseY ], + [ mouseX, mouseY, prevX * zoom, prevY * zoom, mouseX, mouseY ], stretchy ); } else if (firstCtrl) { - pathActionsContext_.replacePathSeg(6, 1, [ mouseX, mouseY, firstCtrl[0], firstCtrl[1], mouseX, mouseY ], stretchy); + svgCanvas.replacePathSeg(6, 1, [ mouseX, mouseY, firstCtrl[0], firstCtrl[1], mouseX, mouseY ], stretchy); } else { - pathActionsContext_.replacePathSeg(4, 1, [ mouseX, mouseY ], stretchy); + svgCanvas.replacePathSeg(4, 1, [ mouseX, mouseY ], stretchy); } } } @@ -654,11 +647,11 @@ export const pathActionsMethod = (function () { } // if we are dragging a point, let's move it if (path.dragging) { - const pt = pathActionsContext_.getPointFromGrip({ + const pt = svgCanvas.getPointFromGrip({ x: path.dragging[0], y: path.dragging[1] }, path); - const mpt = pathActionsContext_.getPointFromGrip({ + const mpt = svgCanvas.getPointFromGrip({ x: mouseX, y: mouseY }, path); @@ -678,10 +671,10 @@ export const pathActionsMethod = (function () { if (!seg.next && !seg.prev) { return; } // const {item} = seg; - const rubberBox = editorContext_.getRubberBox(); + const rubberBox = svgCanvas.getRubberBox(); const rbb = getBBox(rubberBox); - const pt = pathActionsContext_.getGripPt(seg); + const pt = svgCanvas.getGripPt(seg); const ptBb = { x: pt.x, y: pt.y, @@ -711,14 +704,13 @@ export const pathActionsMethod = (function () { * @returns {module:path.keepElement|void} */ mouseUp (evt, element, _mouseX, _mouseY) { - editorContext_ = pathActionsContext_.getEditorContext(); - const drawnPath = editorContext_.getDrawnPath(); + const drawnPath = svgCanvas.getDrawnPath(); // Create mode - if (editorContext_.getCurrentMode() === 'path') { + if (svgCanvas.getCurrentMode() === 'path') { newPoint = null; if (!drawnPath) { - element = getElem(editorContext_.getId()); - editorContext_.setStarted(false); + element = getElem(svgCanvas.getId()); + svgCanvas.setStarted(false); firstCtrl = null; } @@ -729,7 +721,7 @@ export const pathActionsMethod = (function () { } // Edit mode - const rubberBox = editorContext_.getRubberBox(); + const rubberBox = svgCanvas.getRubberBox(); if (path.dragging) { const lastPt = path.cur_pt; @@ -764,10 +756,9 @@ export const pathActionsMethod = (function () { * @returns {void} */ toEditMode (element) { - editorContext_ = pathActionsContext_.getEditorContext(); - path = pathActionsContext_.getPath_(element); - editorContext_.setCurrentMode('pathedit'); - editorContext_.clearSelection(); + path = svgCanvas.getPath_(element); + svgCanvas.setCurrentMode('pathedit'); + svgCanvas.clearSelection(); path.setPathContext(); path.show(true).update(); path.oldbbox = getBBox(path.elem); @@ -779,22 +770,21 @@ export const pathActionsMethod = (function () { * @returns {void} */ toSelectMode (elem) { - editorContext_ = pathActionsContext_.getEditorContext(); const selPath = (elem === path.elem); - editorContext_.setCurrentMode('select'); + svgCanvas.setCurrentMode('select'); path.setPathContext(); path.show(false); currentPath = false; - editorContext_.clearSelection(); + svgCanvas.clearSelection(); if (path.matrix) { // Rotated, so may need to re-calculate the center - pathActionsContext_.recalcRotatedPath(); + svgCanvas.recalcRotatedPath(); } if (selPath) { - editorContext_.call('selected', [ elem ]); - editorContext_.addToSelection([ elem ], true); + svgCanvas.call('selected', [ elem ]); + svgCanvas.addToSelection([ elem ], true); } }, /** @@ -802,11 +792,10 @@ export const pathActionsMethod = (function () { * @returns {void} */ addSubPath (on) { - editorContext_ = pathActionsContext_.getEditorContext(); if (on) { // Internally we go into "path" mode, but in the UI it will // still appear as if in "pathedit" mode. - editorContext_.setCurrentMode('path'); + svgCanvas.setCurrentMode('path'); subpath = true; } else { pathActionsMethod.clear(true); @@ -818,10 +807,9 @@ export const pathActionsMethod = (function () { * @returns {void} */ select (target) { - editorContext_ = pathActionsContext_.getEditorContext(); if (currentPath === target) { pathActionsMethod.toEditMode(target); - editorContext_.setCurrentMode('pathedit'); + svgCanvas.setCurrentMode('pathedit'); // going into pathedit mode } else { currentPath = target; @@ -832,8 +820,7 @@ export const pathActionsMethod = (function () { * @returns {void} */ reorient () { - editorContext_ = pathActionsContext_.getEditorContext(); - const elem = editorContext_.getSelectedElements()[0]; + const elem = svgCanvas.getSelectedElements()[0]; if (!elem) { return; } const angl = getRotationAngle(elem); if (angl === 0) { return; } @@ -844,18 +831,18 @@ export const pathActionsMethod = (function () { transform: elem.getAttribute('transform') }; batchCmd.addSubCommand(new ChangeElementCommand(elem, changes)); - editorContext_.clearSelection(); + svgCanvas.clearSelection(); this.resetOrientation(elem); - editorContext_.addCommandToHistory(batchCmd); + svgCanvas.addCommandToHistory(batchCmd); // Set matrix to null - pathActionsContext_.getPath_(elem).show(false).matrix = null; + svgCanvas.getPath_(elem).show(false).matrix = null; this.clear(); - editorContext_.addToSelection([ elem ], true); - editorContext_.call('changed', editorContext_.getSelectedElements()); + svgCanvas.addToSelection([ elem ], true); + svgCanvas.call('changed', svgCanvas.getSelectedElements()); }, /** @@ -863,11 +850,10 @@ export const pathActionsMethod = (function () { * @returns {void} */ clear () { - editorContext_ = pathActionsContext_.getEditorContext(); - const drawnPath = editorContext_.getDrawnPath(); + const drawnPath = svgCanvas.getDrawnPath(); currentPath = null; if (drawnPath) { - const elem = getElem(editorContext_.getId()); + const elem = getElem(svgCanvas.getId()); const psl = getElem('path_stretch_line'); psl.parentNode.removeChild(psl); elem.parentNode.removeChild(elem); @@ -877,9 +863,9 @@ export const pathActionsMethod = (function () { el.setAttribute('display', 'none'); }); firstCtrl = null; - editorContext_.setDrawnPath(null); - editorContext_.setStarted(false); - } else if (editorContext_.getCurrentMode() === 'pathedit') { + svgCanvas.setDrawnPath(null); + svgCanvas.setStarted(false); + } else if (svgCanvas.getCurrentMode() === 'pathedit') { this.toSelectMode(); } if (path) { path.init().show(false); } @@ -921,18 +907,17 @@ export const pathActionsMethod = (function () { pts.splice(pts.length, 0, pt.x, pt.y); } }); - pathActionsContext_.replacePathSeg(type, i, pts, pth); + svgCanvas.replacePathSeg(type, i, pts, pth); } - pathActionsContext_.reorientGrads(pth, m); + svgCanvas.reorientGrads(pth, m); return undefined; }, /** * @returns {void} */ zoomChange () { - editorContext_ = pathActionsContext_.getEditorContext(); - if (editorContext_.getCurrentMode() === 'pathedit') { + if (svgCanvas.getCurrentMode() === 'pathedit') { path.update(); } }, @@ -960,7 +945,7 @@ export const pathActionsMethod = (function () { * @returns {void} */ linkControlPoints (linkPoints) { - pathActionsContext_.setLinkControlPoints(linkPoints); + svgCanvas.setLinkControlPoints(linkPoints); }, /** * @returns {void} @@ -1091,7 +1076,7 @@ export const pathActionsMethod = (function () { const pt = list.getItem(lastM); // Make this point the new "M" - pathActionsContext_.replacePathSeg(2, lastM, [ pt.x, pt.y ]); + svgCanvas.replacePathSeg(2, lastM, [ pt.x, pt.y ]); // i = index; // i is local here, so has no effect; what was the intent for this? @@ -1162,8 +1147,7 @@ export const pathActionsMethod = (function () { // Completely delete a path with 1 or 0 segments if (path.elem.pathSegList.numberOfItems <= 1) { pathActionsMethod.toSelectMode(path.elem); - editorContext_ = pathActionsContext_.getEditorContext(); - editorContext_.canvas.deleteSelectedElements(); + svgCanvas.canvas.deleteSelectedElements(); return; } diff --git a/src/svgcanvas/path-method.js b/src/svgcanvas/path-method.js index 7c1385bc..81114d8c 100644 --- a/src/svgcanvas/path-method.js +++ b/src/svgcanvas/path-method.js @@ -16,16 +16,15 @@ import { getElem } from './utilities.js'; -let pathMethodsContext_ = null; -let editorContext_ = null; +let svgCanvas = null; /** * @function module:path-actions.init -* @param {module:path-actions.pathMethodsContext_} pathMethodsContext +* @param {module:path-actions.svgCanvas} pathMethodsContext * @returns {void} */ -export const init = function (pathMethodsContext) { - pathMethodsContext_ = pathMethodsContext; +export const init = function (canvas) { + svgCanvas = canvas; }; /* eslint-disable max-len */ @@ -38,7 +37,7 @@ export const init = function (pathMethodsContext) { */ /* eslint-enable max-len */ export const ptObjToArrMethod = function (type, segItem) { - const segData = pathMethodsContext_.getSegData(); + const segData = svgCanvas.getSegData(); const props = segData[type]; return props.map((prop) => { return segItem[prop]; @@ -62,10 +61,10 @@ export const getGripPtMethod = function (seg, altPt) { const pt = transformPoint(out.x, out.y, pth.matrix); out = pt; } - editorContext_ = pathMethodsContext_.getEditorContext(); - const currentZoom = editorContext_.getCurrentZoom(); - out.x *= currentZoom; - out.y *= currentZoom; + svgCanvas = svgCanvas.getEditorContext(); + const zoom = svgCanvas.getZoom(); + out.x *= zoom; + out.y *= zoom; return out; }; @@ -86,10 +85,10 @@ export const getPointFromGripMethod = function (pt, pth) { out.x = pt.x; out.y = pt.y; } - editorContext_ = pathMethodsContext_.getEditorContext(); - const currentZoom = editorContext_.getCurrentZoom(); - out.x /= currentZoom; - out.y /= currentZoom; + svgCanvas = svgCanvas.getEditorContext(); + const zoom = svgCanvas.getZoom(); + out.x /= zoom; + out.y /= zoom; return out; }; @@ -134,7 +133,7 @@ export const addPointGripMethod = function (index, x, y) { cursor: 'move', style: 'pointer-events:all' }; - const uiStrings = pathMethodsContext_.getUIStrings(); + const uiStrings = svgCanvas.getUIStrings(); if ('pathNodeTooltip' in uiStrings) { // May be empty if running path.js without svg-editor atts['xlink:title'] = uiStrings.pathNodeTooltip; } @@ -143,7 +142,7 @@ export const addPointGripMethod = function (index, x, y) { const grip = document.getElementById('pathpointgrip_' + index); grip?.addEventListener("dblclick", () => { - const path = pathMethodsContext_.getPathObj(); + const path = svgCanvas.getPathObj(); if (path) { path.setSegType(); } @@ -181,7 +180,7 @@ export const addCtrlGripMethod = function (id) { cursor: 'move', style: 'pointer-events:all' }; - const uiStrings = pathMethodsContext_.getUIStrings(); + const uiStrings = svgCanvas.getUIStrings(); if ('pathCtrlPtTooltip' in uiStrings) { // May be empty if running path.js without svg-editor atts['xlink:title'] = uiStrings.pathCtrlPtTooltip; } @@ -241,7 +240,7 @@ export const getControlPointsMethod = function (seg) { /* const pointGripContainer = */ getGripContainerMethod(); // Note that this is intentionally not seg.prev.item - const path = pathMethodsContext_.getPathObj(); + const path = svgCanvas.getPathObj(); const prev = path.segs[index - 1].item; const segItems = [ prev, item ]; @@ -286,9 +285,9 @@ export const getControlPointsMethod = function (seg) { * @returns {void} */ export const replacePathSegMethod = function (type, index, pts, elem) { - const path = pathMethodsContext_.getPathObj(); + const path = svgCanvas.getPathObj(); const pth = elem || path.elem; - const pathFuncs = pathMethodsContext_.getPathFuncs(); + const pathFuncs = svgCanvas.getPathFuncs(); const func = 'createSVGPathSeg' + pathFuncs[type]; const seg = pth[func](...pts); @@ -435,7 +434,7 @@ export class Segment { if (this.ctrlpts) { if (full) { - const path = pathMethodsContext_.getPathObj(); + const path = svgCanvas.getPathObj(); this.item = path.elem.pathSegList.getItem(this.index); this.type = this.item.pathSegType; } @@ -549,7 +548,7 @@ export class Segment { setType (newType, pts) { replacePathSegMethod(newType, this.index, pts); this.type = newType; - const path = pathMethodsContext_.getPathObj(); + const path = svgCanvas.getPathObj(); this.item = path.elem.pathSegList.getItem(this.index); this.showCtrlPts(newType === 6); this.ctrlpts = getControlPointsMethod(this); @@ -573,14 +572,14 @@ export class Path { this.elem = elem; this.segs = []; this.selected_pts = []; - pathMethodsContext_.setPathObj(this); + svgCanvas.setPathObj(this); // path = this; this.init(); } setPathContext() { - pathMethodsContext_.setPathObj(this); + svgCanvas.setPathObj(this); } /** @@ -828,7 +827,7 @@ export class Path { moveCtrl (dx, dy) { const seg = this.segs[this.selected_pts[0]]; seg.moveCtrl(this.dragctrl, dx, dy); - if (pathMethodsContext_.getLinkControlPts()) { + if (svgCanvas.getLinkControlPts()) { seg.setLinked(this.dragctrl); } } @@ -899,7 +898,7 @@ export class Path { cur.setType(newType, points); } - const path = pathMethodsContext_.getPathObj(); + const path = svgCanvas.getPathObj(); path.endChanges(text); } @@ -922,7 +921,7 @@ export class Path { if (ctrlNum) { this.dragctrl = ctrlNum; - if (pathMethodsContext_.getLinkControlPts()) { + if (svgCanvas.getLinkControlPts()) { this.segs[pt].setLinked(ctrlNum); } } @@ -956,7 +955,7 @@ export class Path { */ endChanges (text) { const cmd = new ChangeElementCommand(this.elem, { d: this.last_d }, text); - editorContext_.endChanges({ cmd, elem: this.elem }); + svgCanvas.endChanges({ cmd, elem: this.elem }); } /** @@ -984,7 +983,7 @@ export class Path { } const closedSubpath = Path.subpathIsClosed(this.selected_pts[0]); - editorContext_.addPtsToSelection({ grips, closedSubpath }); + svgCanvas.addPtsToSelection({ grips, closedSubpath }); } // STATIC @@ -995,7 +994,7 @@ export class Path { static subpathIsClosed (index) { let clsd = false; // Check if subpath is already open - const path = pathMethodsContext_.getPathObj(); + const path = svgCanvas.getPathObj(); path.eachSeg(function (i) { if (i <= index) { return true; } if (this.type === 2) { diff --git a/src/svgcanvas/path.js b/src/svgcanvas/path.js index 3f2bb1f9..87ee96e7 100644 --- a/src/svgcanvas/path.js +++ b/src/svgcanvas/path.js @@ -35,6 +35,7 @@ const segData = { 18: [ 'x', 'y' ] // PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS }; +let svgCanvas; /** * @tutorial LocaleDocs * @typedef {module:locale.LocaleStrings|PlainObject} module:path.uiStrings @@ -75,8 +76,6 @@ export const setLinkControlPoints = function (lcp) { */ export let path = null; -let editorContext_ = null; - /** * @external MouseEvent */ @@ -86,7 +85,7 @@ let editorContext_ = null; * @typedef {PlainObject} module:path.SVGElementJSON * @property {string} element - Tag name of the SVG element to create * @property {PlainObject} attr - Has key-value attributes to assign to the new element. -* An `id` should be set so that {@link module:utilities.EditorContext#addSVGElementFromJson} can later re-identify the element for modification or replacement. +* An `id` should be set so that {@link module:utilities.EditorContext#addSVGElemensFromJson} can later re-identify the element for modification or replacement. * @property {boolean} [curStyles=false] - Indicates whether current style attributes should be applied first * @property {module:path.SVGElementJSON[]} [children] - Data objects to be added recursively as children * @property {string} [namespace="http://www.w3.org/2000/svg"] - Indicate a (non-SVG) namespace @@ -107,7 +106,7 @@ let editorContext_ = null; * Note: This doesn't round to an integer necessarily. * @function module:path.EditorContext#round * @param {Float} val - * @returns {Float} Rounded value to nearest value based on `currentZoom` + * @returns {Float} Rounded value to nearest value based on `zoom` */ /** * @function module:path.EditorContext#clearSelection @@ -133,7 +132,7 @@ let editorContext_ = null; * @returns {void} */ /** - * @function module:path.EditorContext#addSVGElementFromJson + * @function module:path.EditorContext#addSVGElemensFromJson * @param {module:path.SVGElementJSON} data * @returns {Element} The new element */ @@ -182,7 +181,7 @@ let editorContext_ = null; * @returns {void} */ /** - * @function module:path.EditorContext#getCurrentZoom + * @function module:path.EditorContext#getZoom * @returns {Float} The current zoom level */ /** @@ -220,7 +219,7 @@ let editorContext_ = null; * @returns {SVGPathElement|null} The same value as passed in */ /** - * @function module:path.EditorContext#getSVGRoot + * @function module:path.EditorContext#getSvgRoot * @returns {SVGSVGElement} */ @@ -229,9 +228,8 @@ let editorContext_ = null; * @param {module:path.EditorContext} editorContext * @returns {void} */ -export const init = function (editorContext) { - editorContext_ = editorContext; - +export const init = function (canvas) { + svgCanvas = canvas; pathFuncs = [ 0, 'ClosePath' ]; const pathFuncsStrs = [ 'Moveto', 'Lineto', 'CurvetoCubic', 'CurvetoQuadratic', 'Arc', @@ -241,22 +239,22 @@ export const init = function (editorContext) { pathFuncs.push(s + 'Abs'); pathFuncs.push(s + 'Rel'); }); -}; + pathActionsInit(svgCanvas); -pathMethodInit( + pathMethodInit( /** * @implements {module:path-method.pathMethodsContext} */ - { - getEditorContext () { return editorContext_; }, - getSegData () { return segData; }, - getUIStrings () { return uiStrings; }, - getPathObj () { return path; }, - setPathObj (obj) { path = obj; }, - getPathFuncs () { return pathFuncs; }, - getLinkControlPts () { return linkControlPts; } - } -); + { + getSegData () { return segData; }, + getUIStrings () { return uiStrings; }, + getPathObj () { return path; }, + setPathObj (obj) { path = obj; }, + getPathFuncs () { return pathFuncs; }, + getLinkControlPts () { return linkControlPts; } + } + ); +}; /* eslint-disable max-len */ /** @@ -377,8 +375,8 @@ export const smoothControlPoints = function (ct1, ct2, pt) { const r1 = Math.sqrt(x1 * x1 + y1 * y1); const r2 = Math.sqrt(x2 * x2 + y2 * y2); - const nct1 = editorContext_.getSVGRoot().createSVGPoint(); - const nct2 = editorContext_.getSVGRoot().createSVGPoint(); + const nct1 = svgCanvas.getSvgRoot().createSVGPoint(); + const nct2 = svgCanvas.getSvgRoot().createSVGPoint(); let anglea = Math.atan2(y1, x1); let angleb = Math.atan2(y2, x2); if (anglea < 0) { anglea += 2 * Math.PI; } @@ -511,7 +509,7 @@ export const recalcRotatedPath = function () { // selectedBBoxes[0].width = box.width; selectedBBoxes[0].height = box.height; // now we must set the new transform to be rotated around the new center - const Rnc = editorContext_.getSVGRoot().createSVGTransform(); + const Rnc = svgCanvas.getSvgRoot().createSVGTransform(); const tlist = currentPath.transform.baseVal; Rnc.setRotate((angle * 180.0 / Math.PI), newcx, newcy); tlist.replaceItem(Rnc, 0); @@ -570,7 +568,7 @@ export const reorientGrads = function (elem, m) { for (const [ key, value ] of Object.entries(gCoords)) { newgrad.setAttribute(key, value); } - newgrad.id = editorContext_.getNextId(); + newgrad.id = svgCanvas.getNextId(); findDefs().append(newgrad); elem.setAttribute(type, 'url(#' + newgrad.id + ')'); } @@ -774,28 +772,6 @@ function pathDSegment (letter, points, morePoints, lastPoint) { return segment; } -pathActionsInit( - /** -* @implements {module:path-actions.pathActionsContext} -*/ - { - getEditorContext () { return editorContext_; }, - getPathMap () { return pathMap; }, - smoothControlPoints, - addPointGrip, - recalcRotatedPath, - removePath_, - addCtrlGrip, - getCtrlLine, - replacePathSeg, - getPointFromGrip, - getGripPt, - getPath_, - reorientGrads, - setLinkControlPoints - } -); - /** * Group: Path edit functions. * Functions relating to editing path elements. diff --git a/src/svgcanvas/recalculate.js b/src/svgcanvas/recalculate.js index a943244b..cb4685db 100644 --- a/src/svgcanvas/recalculate.js +++ b/src/svgcanvas/recalculate.js @@ -18,13 +18,13 @@ import { mergeDeep } from '../editor/components/jgraduate/Util.js'; -let context_; +let svgCanvas; /** * @interface module:recalculate.EditorContext */ /** - * @function module:recalculate.EditorContext#getSVGRoot + * @function module:recalculate.EditorContext#getSvgRoot * @returns {SVGSVGElement} The root DOM element */ /** @@ -42,8 +42,8 @@ let context_; * @param {module:recalculate.EditorContext} editorContext * @returns {void} */ -export const init = function (editorContext) { - context_ = editorContext; +export const init = function (canvas) { + svgCanvas = canvas; }; /** @@ -57,7 +57,7 @@ export const init = function (editorContext) { export const updateClipPath = function (attr, tx, ty) { const path = getRefElem(attr).firstChild; const cpXform = path.transform.baseVal; - const newxlate = context_.getSVGRoot().createSVGTransform(); + const newxlate = svgCanvas.getSvgRoot().createSVGTransform(); newxlate.setTranslate(tx, ty); cpXform.appendItem(newxlate); @@ -74,8 +74,8 @@ export const updateClipPath = function (attr, tx, ty) { */ export const recalculateDimensions = function (selected) { if (!selected) return null; - const svgroot = context_.getSVGRoot(); - const dataStorage = context_.getDataStorage(); + const svgroot = svgCanvas.getSvgRoot(); + const dataStorage = svgCanvas.getDataStorage(); const tlist = selected.transform?.baseVal; // remove any unnecessary transforms if (tlist && tlist.numberOfItems > 0) { @@ -239,7 +239,7 @@ export const recalculateDimensions = function (selected) { } } // save the start transform value too - initial.transform = context_.getStartTransform() || ''; + initial.transform = svgCanvas.getStartTransform() || ''; let oldcenter; let newcenter; @@ -323,9 +323,9 @@ export const recalculateDimensions = function (selected) { // } const angle = getRotationAngle(child); - oldStartTransform = context_.getStartTransform(); + oldStartTransform = svgCanvas.getStartTransform(); // const childxforms = []; - context_.setStartTransform(child.getAttribute('transform')); + svgCanvas.setStartTransform(child.getAttribute('transform')); if (angle || hasMatrixTransform(childTlist)) { const e2t = svgroot.createSVGTransform(); e2t.setMatrix(matrixMultiply(tm, sm, tmn, m)); @@ -383,7 +383,7 @@ export const recalculateDimensions = function (selected) { // batchCmd.addSubCommand( recalculateDimensions(useElem) ); // } // } - context_.setStartTransform(oldStartTransform); + svgCanvas.setStartTransform(oldStartTransform); } // element } // for each child // Remove these transforms from group @@ -430,8 +430,8 @@ export const recalculateDimensions = function (selected) { } } - oldStartTransform = context_.getStartTransform(); - context_.setStartTransform(child.getAttribute('transform')); + oldStartTransform = svgCanvas.getStartTransform(); + svgCanvas.setStartTransform(child.getAttribute('transform')); const childTlist = child.transform?.baseVal; // some children might not have a transform (, , etc) @@ -459,11 +459,11 @@ export const recalculateDimensions = function (selected) { batchCmd.addSubCommand(recalculateDimensions(useElem)); } } - context_.setStartTransform(oldStartTransform); + svgCanvas.setStartTransform(oldStartTransform); } } } - context_.setStartTransform(oldStartTransform); + svgCanvas.setStartTransform(oldStartTransform); } // else, a matrix imposition from a parent group // keep pushing it down to the children @@ -475,8 +475,8 @@ export const recalculateDimensions = function (selected) { while (c--) { const child = children.item(c); if (child.nodeType === 1) { - oldStartTransform = context_.getStartTransform(); - context_.setStartTransform(child.getAttribute('transform')); + oldStartTransform = svgCanvas.getStartTransform(); + svgCanvas.setStartTransform(child.getAttribute('transform')); const childTlist = child.transform?.baseVal; if (!childTlist) { continue; } @@ -488,7 +488,7 @@ export const recalculateDimensions = function (selected) { childTlist.appendItem(e2m, 0); batchCmd.addSubCommand(recalculateDimensions(child)); - context_.setStartTransform(oldStartTransform); + svgCanvas.setStartTransform(oldStartTransform); // Convert stroke // TODO: Find out if this should actually happen somewhere else @@ -556,8 +556,8 @@ export const recalculateDimensions = function (selected) { while (c--) { const child = children.item(c); if (child.nodeType === 1) { - oldStartTransform = context_.getStartTransform(); - context_.setStartTransform(child.getAttribute('transform')); + oldStartTransform = svgCanvas.getStartTransform(); + svgCanvas.setStartTransform(child.getAttribute('transform')); const childTlist = child.transform?.baseVal; const newxlate = svgroot.createSVGTransform(); newxlate.setTranslate(tx, ty); @@ -568,7 +568,7 @@ export const recalculateDimensions = function (selected) { } batchCmd.addSubCommand(recalculateDimensions(child)); - context_.setStartTransform(oldStartTransform); + svgCanvas.setStartTransform(oldStartTransform); } } } diff --git a/src/svgcanvas/select.js b/src/svgcanvas/select.js index f4596fbf..f0b188c8 100644 --- a/src/svgcanvas/select.js +++ b/src/svgcanvas/select.js @@ -10,7 +10,7 @@ import { isTouch, isWebkit } from '../common/browser.js'; // , isOpera import { getRotationAngle, getBBox, getStrokedBBox, isNullish } from './utilities.js'; import { transformListToTransform, transformBox, transformPoint } from './math.js'; -let svgFactory_; +let svgCanvas; let config_; let selectorManager_; // A Singleton const gripRadius = isTouch() ? 10 : 4; @@ -35,13 +35,13 @@ export class Selector { this.locked = true; // this holds a reference to the element that holds all visual elements of the selector - this.selectorGroup = svgFactory_.createSVGElement({ + this.selectorGroup = svgCanvas.createSVGElement({ element: 'g', attr: { id: ('selectorGroup' + this.id) } }); // this holds a reference to the path rect - this.selectorRect = svgFactory_.createSVGElement({ + this.selectorRect = svgCanvas.createSVGElement({ element: 'path', attr: { id: ('selectedBox' + this.id), @@ -105,13 +105,13 @@ export class Selector { * @returns {void} */ resize(bbox) { - const dataStorage = svgFactory_.getDataStorage(); + const dataStorage = svgCanvas.getDataStorage(); const selectedBox = this.selectorRect; const mgr = selectorManager_; const selectedGrips = mgr.selectorGrips; const selected = this.selectedElement; - const currentZoom = svgFactory_.getCurrentZoom(); - let offset = 1 / currentZoom; + const zoom = svgCanvas.getZoom(); + let offset = 1 / zoom; const sw = selected.getAttribute('stroke-width'); if (selected.getAttribute('stroke') !== 'none' && !isNaN(sw)) { offset += (sw / 2); @@ -119,7 +119,7 @@ export class Selector { const { tagName } = selected; if (tagName === 'text') { - offset += 2 / currentZoom; + offset += 2 / zoom; } // loop and transform our bounding box until we reach our first rotation @@ -128,8 +128,8 @@ export class Selector { // This should probably be handled somewhere else, but for now // it keeps the selection box correctly positioned when zoomed - m.e *= currentZoom; - m.f *= currentZoom; + m.e *= zoom; + m.f *= zoom; if (!bbox) { bbox = getBBox(selected); @@ -153,9 +153,9 @@ export class Selector { // if skewed, get its transformed box, then find its axis-aligned bbox // * - offset *= currentZoom; + offset *= zoom; - const nbox = transformBox(l * currentZoom, t * currentZoom, w * currentZoom, h * currentZoom, m); + const nbox = transformBox(l * zoom, t * zoom, w * zoom, h * zoom, m); const { aabox } = nbox; let nbax = aabox.x - offset; let nbay = aabox.y - offset; @@ -168,7 +168,7 @@ export class Selector { const angle = getRotationAngle(selected); if (angle) { - const rot = svgFactory_.svgRoot().createSVGTransform(); + const rot = svgCanvas.getSvgRoot().createSVGTransform(); rot.setRotate(-angle, cx, cy); const rotm = rot.matrix; nbox.tl = transformPoint(nbox.tl.x, nbox.tl.y, rotm); @@ -297,23 +297,23 @@ export class SelectorManager { * @returns {void} */ initGroup() { - const dataStorage = svgFactory_.getDataStorage(); + const dataStorage = svgCanvas.getDataStorage(); // remove old selector parent group if it existed if (this.selectorParentGroup && this.selectorParentGroup.parentNode) { this.selectorParentGroup.remove(); } // create parent selector group and add it to svgroot - this.selectorParentGroup = svgFactory_.createSVGElement({ + this.selectorParentGroup = svgCanvas.createSVGElement({ element: 'g', attr: { id: 'selectorParentGroup' } }); - this.selectorGripsGroup = svgFactory_.createSVGElement({ + this.selectorGripsGroup = svgCanvas.createSVGElement({ element: 'g', attr: { display: 'none' } }); this.selectorParentGroup.append(this.selectorGripsGroup); - svgFactory_.svgRoot().append(this.selectorParentGroup); + svgCanvas.getSvgRoot().append(this.selectorParentGroup); this.selectorMap = {}; this.selectors = []; @@ -321,7 +321,7 @@ export class SelectorManager { // add the corner grips Object.keys(this.selectorGrips).forEach((dir) => { - const grip = svgFactory_.createSVGElement({ + const grip = svgCanvas.createSVGElement({ element: 'circle', attr: { id: ('selectorGrip_resize_' + dir), @@ -345,7 +345,7 @@ export class SelectorManager { // add rotator elems this.rotateGripConnector = - svgFactory_.createSVGElement({ + svgCanvas.createSVGElement({ element: 'line', attr: { id: ('selectorGrip_rotateconnector'), @@ -356,7 +356,7 @@ export class SelectorManager { this.selectorGripsGroup.append(this.rotateGripConnector); this.rotateGrip = - svgFactory_.createSVGElement({ + svgCanvas.createSVGElement({ element: 'circle', attr: { id: 'selectorGrip_rotate', @@ -373,7 +373,7 @@ export class SelectorManager { if (document.getElementById('canvasBackground')) { return; } const [ width, height ] = config_.dimensions; - const canvasbg = svgFactory_.createSVGElement({ + const canvasbg = svgCanvas.createSVGElement({ element: 'svg', attr: { id: 'canvasBackground', @@ -386,7 +386,7 @@ export class SelectorManager { } }); - const rect = svgFactory_.createSVGElement({ + const rect = svgCanvas.createSVGElement({ element: 'rect', attr: { width: '100%', @@ -399,13 +399,8 @@ export class SelectorManager { style: 'pointer-events:none' } }); - - // Both Firefox and WebKit are too slow with this filter region (especially at higher - // zoom levels) and Opera has at least one bug - // if (!isOpera()) rect.setAttribute('filter', 'url(#canvashadow)'); canvasbg.append(rect); - svgFactory_.svgRoot().insertBefore(canvasbg, svgFactory_.svgContent()); - // Ok to replace above with `svgFactory_.svgContent().before(canvasbg);`? + svgCanvas.getSvgRoot().insertBefore(canvasbg, svgCanvas.getSvgContent()); } /** @@ -476,7 +471,7 @@ export class SelectorManager { getRubberBandBox() { if (!this.rubberBandBox) { this.rubberBandBox = - svgFactory_.createSVGElement({ + svgCanvas.createSVGElement({ element: 'rect', attr: { id: 'selectorRubberBand', @@ -501,7 +496,7 @@ export class SelectorManager { */ /** * @function module:select.SVGFactory#createSVGElement - * @param {module:utilities.EditorContext#addSVGElementFromJson} jsonMap + * @param {module:utilities.EditorContext#addSVGElemensFromJson} jsonMap * @returns {SVGElement} */ /** @@ -513,7 +508,7 @@ export class SelectorManager { * @returns {SVGSVGElement} */ /** - * @function module:select.SVGFactory#getCurrentZoom + * @function module:select.SVGFactory#getZoom * @returns {Float} The current zoom level */ @@ -536,9 +531,9 @@ export class SelectorManager { * @param {module:select.SVGFactory} svgFactory - An object implementing the SVGFactory interface. * @returns {void} */ -export const init = function (config, svgFactory) { +export const init = function (config, canvas) { config_ = config; - svgFactory_ = svgFactory; + svgCanvas = canvas; selectorManager_ = new SelectorManager(); }; diff --git a/src/svgcanvas/selected-elem.js b/src/svgcanvas/selected-elem.js index 93955fc3..5a70c4d4 100644 --- a/src/svgcanvas/selected-elem.js +++ b/src/svgcanvas/selected-elem.js @@ -28,15 +28,15 @@ const { MoveElementCommand, BatchCommand, InsertElementCommand, RemoveElementCommand, ChangeElementCommand } = hstry; -let elementContext_ = null; +let svgCanvas = null; /** * @function module:selected-elem.init * @param {module:selected-elem.elementContext} elementContext * @returns {void} */ -export const init = function (elementContext) { - elementContext_ = elementContext; +export const init = function (canvas) { + svgCanvas = canvas; }; /** @@ -47,7 +47,7 @@ export const init = function (elementContext) { * @returns {void} */ export const moveToTopSelectedElem = function () { - const [ selected ] = elementContext_.getSelectedElements(); + const [ selected ] = svgCanvas.getSelectedElements(); if (!isNullish(selected)) { const t = selected; const oldParent = t.parentNode; @@ -56,8 +56,8 @@ export const moveToTopSelectedElem = function () { // If the element actually moved position, add the command and fire the changed // event handler. if (oldNextSibling !== t.nextSibling) { - elementContext_.addCommandToHistory(new MoveElementCommand(t, oldNextSibling, oldParent, 'top')); - elementContext_.call('changed', [ t ]); + svgCanvas.addCommandToHistory(new MoveElementCommand(t, oldNextSibling, oldParent, 'top')); + svgCanvas.call('changed', [ t ]); } } }; @@ -70,7 +70,7 @@ export const moveToTopSelectedElem = function () { * @returns {void} */ export const moveToBottomSelectedElem = function () { - const [ selected ] = elementContext_.getSelectedElements(); + const [ selected ] = svgCanvas.getSelectedElements(); if (!isNullish(selected)) { let t = selected; const oldParent = t.parentNode; @@ -88,8 +88,8 @@ export const moveToBottomSelectedElem = function () { // If the element actually moved position, add the command and fire the changed // event handler. if (oldNextSibling !== t.nextSibling) { - elementContext_.addCommandToHistory(new MoveElementCommand(t, oldNextSibling, oldParent, 'bottom')); - elementContext_.call('changed', [ t ]); + svgCanvas.addCommandToHistory(new MoveElementCommand(t, oldNextSibling, oldParent, 'bottom')); + svgCanvas.call('changed', [ t ]); } } }; @@ -103,14 +103,14 @@ export const moveToBottomSelectedElem = function () { * @returns {void} */ export const moveUpDownSelected = function (dir) { - const selectedElements = elementContext_.getSelectedElements(); + const selectedElements = svgCanvas.getSelectedElements(); const selected = selectedElements[0]; if (!selected) { return; } - elementContext_.setCurBBoxes([]); + svgCanvas.setCurBBoxes([]); let closest; let foundCur; // jQuery sorts this list - const list = elementContext_.getIntersectionList(getStrokedBBoxDefaultVisible([ selected ])); + const list = svgCanvas.getIntersectionList(getStrokedBBoxDefaultVisible([ selected ])); if (dir === 'Down') { list.reverse(); } Array.prototype.forEach.call(list, function (el) { @@ -136,8 +136,8 @@ export const moveUpDownSelected = function (dir) { // If the element actually moved position, add the command and fire the changed // event handler. if (oldNextSibling !== t.nextSibling) { - elementContext_.addCommandToHistory(new MoveElementCommand(t, oldNextSibling, oldParent, 'Move ' + dir)); - elementContext_.call('changed', [ t ]); + svgCanvas.addCommandToHistory(new MoveElementCommand(t, oldNextSibling, oldParent, 'Move ' + dir)); + svgCanvas.call('changed', [ t ]); } }; @@ -152,19 +152,19 @@ export const moveUpDownSelected = function (dir) { */ export const moveSelectedElements = function (dx, dy, undoable = true) { - const selectedElements = elementContext_.getSelectedElements(); - const currentZoom = elementContext_.getCurrentZoom(); + const selectedElements = svgCanvas.getSelectedElements(); + const zoom = svgCanvas.getZoom(); // if undoable is not sent, default to true // if single values, scale them to the zoom if (!Array.isArray(dx)) { - dx /= currentZoom; - dy /= currentZoom; + dx /= zoom; + dy /= zoom; } const batchCmd = new BatchCommand('position'); selectedElements.forEach((selected, i) => { if (selected) { - const xform = elementContext_.getSVGRoot().createSVGTransform(); + const xform = svgCanvas.getSvgRoot().createSVGTransform(); const tlist = selected.transform?.baseVal; // dx and dy could be arrays @@ -185,14 +185,14 @@ export const moveSelectedElements = function (dx, dy, undoable = true) { batchCmd.addSubCommand(cmd); } - elementContext_.gettingSelectorManager().requestSelector(selected).resize(); + svgCanvas.gettingSelectorManager().requestSelector(selected).resize(); } }); if (!batchCmd.isEmpty()) { if (undoable) { - elementContext_.addCommandToHistory(batchCmd); + svgCanvas.addCommandToHistory(batchCmd); } - elementContext_.call('changed', selectedElements); + svgCanvas.call('changed', selectedElements); return batchCmd; } return undefined; @@ -207,8 +207,8 @@ export const moveSelectedElements = function (dx, dy, undoable = true) { * @returns {void} */ export const cloneSelectedElements = function (x, y) { - const selectedElements = elementContext_.getSelectedElements(); - const currentGroup = elementContext_.getCurrentGroup(); + const selectedElements = svgCanvas.getSelectedElements(); + const currentGroup = svgCanvas.getCurrentGroup(); let i; let elem; const batchCmd = new BatchCommand('Clone Elements'); // find all the elements selected (stop at first null) @@ -239,10 +239,10 @@ export const cloneSelectedElements = function (x, y) { } // use slice to quickly get the subset of elements we need const copiedElements = selectedElements.slice(0, i); - elementContext_.clearSelection(true); + svgCanvas.clearSelection(true); // note that we loop in the reverse way because of the way elements are added // to the selectedElements array (top-first) - const drawing = elementContext_.getDrawing(); + const drawing = svgCanvas.getDrawing(); i = copiedElements.length; while (i--) { // clone each element and replace it within copiedElements @@ -252,9 +252,9 @@ export const cloneSelectedElements = function (x, y) { } if (!batchCmd.isEmpty()) { - elementContext_.addToSelection(copiedElements.reverse()); // Need to reverse for correct selection-adding + svgCanvas.addToSelection(copiedElements.reverse()); // Need to reverse for correct selection-adding moveSelectedElements(x, y, false); - elementContext_.addCommandToHistory(batchCmd); + svgCanvas.addCommandToHistory(batchCmd); } }; /** @@ -265,7 +265,7 @@ export const cloneSelectedElements = function (x, y) { * @returns {void} */ export const alignSelectedElements = function (type, relativeTo) { - const selectedElements = elementContext_.getSelectedElements(); + const selectedElements = svgCanvas.getSelectedElements(); const bboxes = []; // angles = []; const len = selectedElements.length; if (!len) { return; } @@ -319,8 +319,8 @@ export const alignSelectedElements = function (type, relativeTo) { if (relativeTo === 'page') { minx = 0; miny = 0; - maxx = elementContext_.getContentW(); - maxy = elementContext_.getContentH(); + maxx = svgCanvas.getContentW(); + maxy = svgCanvas.getContentH(); } const dx = new Array(len); @@ -369,7 +369,7 @@ export const alignSelectedElements = function (type, relativeTo) { * @returns {void} */ export const deleteSelectedElements = function () { - const selectedElements = elementContext_.getSelectedElements(); + const selectedElements = svgCanvas.getSelectedElements(); const batchCmd = new BatchCommand('Delete Elements'); const len = selectedElements.length; const selectedCopy = []; // selectedElements is being deleted @@ -382,7 +382,7 @@ export const deleteSelectedElements = function () { let t = selected; // this will unselect the element and remove the selectedOutline - elementContext_.gettingSelectorManager().releaseSelector(t); + svgCanvas.gettingSelectorManager().releaseSelector(t); // Remove the path if present. pathModule.removePath_(t.id); @@ -399,11 +399,11 @@ export const deleteSelectedElements = function () { selectedCopy.push(selected); // for the copy batchCmd.addSubCommand(new RemoveElementCommand(elem, nextSibling, parent)); } - elementContext_.getCanvas().setEmptySelectedElements(); + svgCanvas.setEmptySelectedElements(); - if (!batchCmd.isEmpty()) { elementContext_.addCommandToHistory(batchCmd); } - elementContext_.call('changed', selectedCopy); - elementContext_.clearSelection(); + if (!batchCmd.isEmpty()) { svgCanvas.addCommandToHistory(batchCmd); } + svgCanvas.call('changed', selectedCopy); + svgCanvas.clearSelection(); }; /** @@ -412,12 +412,12 @@ export const deleteSelectedElements = function () { * @returns {void} */ export const copySelectedElements = function () { - const selectedElements = elementContext_.getSelectedElements(); + const selectedElements = svgCanvas.getSelectedElements(); const data = - JSON.stringify(selectedElements.map((x) => elementContext_.getJsonFromSvgElement(x))); + JSON.stringify(selectedElements.map((x) => svgCanvas.getJsonFromSvgElements(x))); // Use sessionStorage for the clipboard data. - sessionStorage.setItem(elementContext_.getClipboardID(), data); - elementContext_.flashStorage(); + sessionStorage.setItem(svgCanvas.getClipboardID(), data); + svgCanvas.flashStorage(); // Context menu might not exist (it is provided by editor.js). const canvMenu = document.getElementById('se-cmenu_canvas'); @@ -432,7 +432,7 @@ export const copySelectedElements = function () { * @returns {void} */ export const groupSelectedElements = function (type, urlArg) { - const selectedElements = elementContext_.getSelectedElements(); + const selectedElements = svgCanvas.getSelectedElements(); if (!type) { type = 'g'; } let cmdStr = ''; let url; @@ -452,10 +452,10 @@ export const groupSelectedElements = function (type, urlArg) { const batchCmd = new BatchCommand(cmdStr); // create and insert the group element - const g = elementContext_.addSVGElementFromJson({ + const g = svgCanvas.addSVGElemensFromJson({ element: type, attr: { - id: elementContext_.getNextId() + id: svgCanvas.getNextId() } }); if (type === 'a') { @@ -478,10 +478,10 @@ export const groupSelectedElements = function (type, urlArg) { g.append(elem); batchCmd.addSubCommand(new MoveElementCommand(elem, oldNextSibling, oldParent)); } - if (!batchCmd.isEmpty()) { elementContext_.addCommandToHistory(batchCmd); } + if (!batchCmd.isEmpty()) { svgCanvas.addCommandToHistory(batchCmd); } // update selection - elementContext_.selectOnly([ g ], true); + svgCanvas.selectOnly([ g ], true); }; /** @@ -516,7 +516,7 @@ export const pushGroupProperty = function (g, undoable) { opacity: g.getAttribute('opacity') }; let gfilter; let gblur; let changes; - const drawing = elementContext_.getDrawing(); + const drawing = svgCanvas.getDrawing(); for (let i = 0; i < len; i++) { const elem = children[i]; @@ -526,13 +526,13 @@ export const pushGroupProperty = function (g, undoable) { if (gattrs.opacity !== null && gattrs.opacity !== 1) { // const c_opac = elem.getAttribute('opacity') || 1; const newOpac = Math.round((elem.getAttribute('opacity') || 1) * gattrs.opacity * 100) / 100; - elementContext_.changeSelectedAttribute('opacity', newOpac, [ elem ]); + svgCanvas.changeSelectedAttribute('opacity', newOpac, [ elem ]); } if (gattrs.filter) { - let cblur = elementContext_.getCanvas().getBlur(elem); + let cblur = svgCanvas.getBlur(elem); const origCblur = cblur; - if (!gblur) { gblur = elementContext_.getCanvas().getBlur(g); } + if (!gblur) { gblur = svgCanvas.getBlur(g); } if (cblur) { // Is this formula correct? cblur = Number(gblur) + Number(cblur); @@ -555,7 +555,7 @@ export const pushGroupProperty = function (g, undoable) { // Change this in future for different filters const suffix = (blurElem?.tagName === 'feGaussianBlur') ? 'blur' : 'filter'; gfilter.id = elem.id + '_' + suffix; - elementContext_.changeSelectedAttribute('filter', 'url(#' + gfilter.id + ')', [ elem ]); + svgCanvas.changeSelectedAttribute('filter', 'url(#' + gfilter.id + ')', [ elem ]); } } else { gfilter = getRefElem(elem.getAttribute('filter')); @@ -565,8 +565,8 @@ export const pushGroupProperty = function (g, undoable) { // Update blur value if (cblur) { - elementContext_.changeSelectedAttribute('stdDeviation', cblur, [ blurElem ]); - elementContext_.getCanvas().setBlurOffsets(gfilter, cblur); + svgCanvas.changeSelectedAttribute('stdDeviation', cblur, [ blurElem ]); + svgCanvas.setBlurOffsets(gfilter, cblur); } } @@ -599,7 +599,7 @@ export const pushGroupProperty = function (g, undoable) { const rgm = glist.getItem(0).matrix; // get child's rotation matrix (Rc) - let rcm = elementContext_.getSVGRoot().createSVGMatrix(); + let rcm = svgCanvas.getSvgRoot().createSVGMatrix(); const cangle = getRotationAngle(elem); if (cangle) { rcm = chtlist.getItem(0).matrix; @@ -614,7 +614,7 @@ export const pushGroupProperty = function (g, undoable) { const sangle = gangle + cangle; // get child's rotation at the old center (Rc2_inv) - const r2 = elementContext_.getSVGRoot().createSVGTransform(); + const r2 = svgCanvas.getSvgRoot().createSVGTransform(); r2.setRotate(sangle, coldc.x, coldc.y); // calculate equivalent translate @@ -634,7 +634,7 @@ export const pushGroupProperty = function (g, undoable) { } if (trm.e || trm.f) { - const tr = elementContext_.getSVGRoot().createSVGTransform(); + const tr = svgCanvas.getSvgRoot().createSVGTransform(); tr.setTranslate(trm.e, trm.f); if (chtlist.numberOfItems) { chtlist.insertItemBefore(tr, 0); @@ -649,7 +649,7 @@ export const pushGroupProperty = function (g, undoable) { changes = {}; changes.transform = oldxform || ''; - const newxform = elementContext_.getSVGRoot().createSVGTransform(); + const newxform = svgCanvas.getSvgRoot().createSVGTransform(); // [ gm ] [ chm ] = [ chm ] [ gm' ] // [ gm' ] = [ chmInv ] [ gm ] [ chm ] @@ -687,14 +687,14 @@ export const pushGroupProperty = function (g, undoable) { * @returns {void} */ export const convertToGroup = function (elem) { - const selectedElements = elementContext_.getSelectedElements(); + const selectedElements = svgCanvas.getSelectedElements(); if (!elem) { elem = selectedElements[0]; } const $elem = elem; const batchCmd = new BatchCommand(); let ts; - const dataStorage = elementContext_.getDataStorage(); + const dataStorage = svgCanvas.getDataStorage(); if (dataStorage.has($elem, 'gsvg')) { // Use the gsvg as the new group const svg = elem.firstChild; @@ -712,11 +712,11 @@ export const convertToGroup = function (elem) { dataStorage.remove(elem, 'gsvg'); const tlist = elem.transform.baseVal; - const xform = elementContext_.getSVGRoot().createSVGTransform(); + const xform = svgCanvas.getSvgRoot().createSVGTransform(); xform.setTranslate(pt.x, pt.y); tlist.appendItem(xform); recalculateDimensions(elem); - elementContext_.call('selected', [ elem ]); + svgCanvas.call('selected', [ elem ]); } else if (dataStorage.has($elem, 'symbol')) { elem = dataStorage.get($elem, 'symbol'); @@ -744,12 +744,12 @@ export const convertToGroup = function (elem) { $elem.remove(); // See if other elements reference this symbol - const svgcontent = elementContext_.getSVGContent(); - // const hasMore = svgcontent.querySelectorAll('use:data(symbol)').length; + const svgContent = svgCanvas.getSvgContent(); + // const hasMore = svgContent.querySelectorAll('use:data(symbol)').length; // @todo review this logic - const hasMore = svgcontent.querySelectorAll('use').length; + const hasMore = svgContent.querySelectorAll('use').length; - const g = elementContext_.getDOMDocument().createElementNS(NS.SVG, 'g'); + const g = svgCanvas.getDOMDocument().createElementNS(NS.SVG, 'g'); const childs = elem.childNodes; let i; @@ -772,7 +772,7 @@ export const convertToGroup = function (elem) { const parent = elem.parentNode; - elementContext_.uniquifyElems(g); + svgCanvas.uniquifyElems(g); // Put the dupe gradients back into (after uniquifying them) if (isGecko()) { @@ -784,7 +784,7 @@ export const convertToGroup = function (elem) { } // now give the g itself a new id - g.id = elementContext_.getNextId(); + g.id = svgCanvas.getNextId(); prev.after(g); @@ -798,12 +798,12 @@ export const convertToGroup = function (elem) { batchCmd.addSubCommand(new InsertElementCommand(g)); } - elementContext_.setUseData(g); + svgCanvas.setUseData(g); if (isGecko()) { - elementContext_.convertGradients(findDefs()); + svgCanvas.convertGradients(findDefs()); } else { - elementContext_.convertGradients(g); + svgCanvas.convertGradients(g); } // recalculate dimensions on the top-level children so that unnecessary transforms @@ -817,19 +817,19 @@ export const convertToGroup = function (elem) { }); // Give ID for any visible element missing one - const visElems = g.querySelectorAll(elementContext_.getVisElems()); + const visElems = g.querySelectorAll(svgCanvas.getVisElems()); Array.prototype.forEach.call(visElems, function (el) { - if (!el.id) { el.id = elementContext_.getNextId(); } + if (!el.id) { el.id = svgCanvas.getNextId(); } }); - elementContext_.selectOnly([ g ]); + svgCanvas.selectOnly([ g ]); const cm = pushGroupProperty(g, true); if (cm) { batchCmd.addSubCommand(cm); } - elementContext_.addCommandToHistory(batchCmd); + svgCanvas.addCommandToHistory(batchCmd); } else { console.warn('Unexpected element to ungroup:', elem); } @@ -842,8 +842,8 @@ export const convertToGroup = function (elem) { * @returns {void} */ export const ungroupSelectedElement = function () { - const selectedElements = elementContext_.getSelectedElements(); - const dataStorage = elementContext_.getDataStorage(); + const selectedElements = svgCanvas.getSelectedElements(); + const dataStorage = svgCanvas.getDataStorage(); let g = selectedElements[0]; if (!g) { return; @@ -895,17 +895,17 @@ export const ungroupSelectedElement = function () { } // remove the group from the selection - elementContext_.clearSelection(); + svgCanvas.clearSelection(); // delete the group element (but make undo-able) const gNextSibling = g.nextSibling; g.remove(); batchCmd.addSubCommand(new RemoveElementCommand(g, gNextSibling, parent)); - if (!batchCmd.isEmpty()) { elementContext_.addCommandToHistory(batchCmd); } + if (!batchCmd.isEmpty()) { svgCanvas.addCommandToHistory(batchCmd); } // update selection - elementContext_.addToSelection(children); + svgCanvas.addToSelection(children); } }; /** @@ -917,26 +917,26 @@ export const ungroupSelectedElement = function () { * @returns {module:svgcanvas.CanvasInfo} */ export const updateCanvas = function (w, h) { - elementContext_.getSVGRoot().setAttribute('width', w); - elementContext_.getSVGRoot().setAttribute('height', h); - const currentZoom = elementContext_.getCurrentZoom(); + svgCanvas.getSvgRoot().setAttribute('width', w); + svgCanvas.getSvgRoot().setAttribute('height', h); + const zoom = svgCanvas.getZoom(); const bg = document.getElementById('canvasBackground'); - const oldX = Number(elementContext_.getSVGContent().getAttribute('x')); - const oldY = Number(elementContext_.getSVGContent().getAttribute('y')); - const x = ((w - this.contentW * currentZoom) / 2); - const y = ((h - this.contentH * currentZoom) / 2); + const oldX = Number(svgCanvas.getSvgContent().getAttribute('x')); + const oldY = Number(svgCanvas.getSvgContent().getAttribute('y')); + const x = ((w - this.contentW * zoom) / 2); + const y = ((h - this.contentH * zoom) / 2); - assignAttributes(elementContext_.getSVGContent(), { - width: this.contentW * currentZoom, - height: this.contentH * currentZoom, + assignAttributes(svgCanvas.getSvgContent(), { + width: this.contentW * zoom, + height: this.contentH * zoom, x, y, viewBox: '0 0 ' + this.contentW + ' ' + this.contentH }); assignAttributes(bg, { - width: elementContext_.getSVGContent().getAttribute('width'), - height: elementContext_.getSVGContent().getAttribute('height'), + width: svgCanvas.getSvgContent().getAttribute('width'), + height: svgCanvas.getSvgContent().getAttribute('height'), x, y }); @@ -949,7 +949,7 @@ export const updateCanvas = function (w, h) { }); } - elementContext_.getCanvas().selectorManager.selectorParentGroup.setAttribute('transform', 'translate(' + x + ',' + y + ')'); + svgCanvas.selectorManager.selectorParentGroup.setAttribute('transform', 'translate(' + x + ',' + y + ')'); /** * Invoked upon updates to the canvas. @@ -962,7 +962,7 @@ export const updateCanvas = function (w, h) { * @property {Integer} d_x * @property {Integer} d_y */ - elementContext_.getCanvas().runExtensions( + svgCanvas.runExtensions( 'canvasUpdated', /** * @type {module:svgcanvas.SvgCanvas#event:ext_canvasUpdated} @@ -979,12 +979,12 @@ export const updateCanvas = function (w, h) { * @returns {void} */ export const cycleElement = function (next) { - const selectedElements = elementContext_.getSelectedElements(); - const currentGroup = elementContext_.getCurrentGroup(); + const selectedElements = svgCanvas.getSelectedElements(); + const currentGroup = svgCanvas.getCurrentGroup(); let num; const curElem = selectedElements[0]; let elem = false; - const allElems = getVisibleElements(currentGroup || elementContext_.getCanvas().getCurrentDrawing().getCurrentLayer()); + const allElems = getVisibleElements(currentGroup || svgCanvas.getCurrentDrawing().getCurrentLayer()); if (!allElems.length) { return; } if (isNullish(curElem)) { num = next ? allElems.length - 1 : 0; @@ -1004,6 +1004,6 @@ export const cycleElement = function (next) { } } } - elementContext_.getCanvas().selectOnly([ elem ], true); - elementContext_.call('selected', selectedElements); + svgCanvas.selectOnly([ elem ], true); + svgCanvas.call('selected', selectedElements); }; diff --git a/src/svgcanvas/selection.js b/src/svgcanvas/selection.js index 87d7a088..26897d28 100644 --- a/src/svgcanvas/selection.js +++ b/src/svgcanvas/selection.js @@ -19,7 +19,6 @@ import * as hstry from "./history.js"; import { getClosest } from "../editor/components/jgraduate/Util.js"; const { BatchCommand } = hstry; -let selectionContext_ = null; let svgCanvas = null; /** @@ -27,9 +26,8 @@ let svgCanvas = null; * @param {module:selection.selectionContext} selectionContext * @returns {void} */ -export const init = function (selectionContext) { - selectionContext_ = selectionContext; - svgCanvas = selectionContext_.getCanvas(); +export const init = function (canvas) { + svgCanvas = canvas; }; /** @@ -40,7 +38,7 @@ export const init = function (selectionContext) { * @fires module:selection.SvgCanvas#event:selected */ export const clearSelectionMethod = function (noCall) { - const selectedElements = selectionContext_.getSelectedElements(); + const selectedElements = svgCanvas.getSelectedElements(); selectedElements.forEach((elem) => { if (!elem) { return; @@ -48,7 +46,7 @@ export const clearSelectionMethod = function (noCall) { svgCanvas.selectorManager.releaseSelector(elem); }); - svgCanvas.setEmptySelectedElements(); + svgCanvas?.setEmptySelectedElements(); if (!noCall) { svgCanvas.call("selected", selectedElements); @@ -62,7 +60,7 @@ export const clearSelectionMethod = function (noCall) { * @fires module:selection.SvgCanvas#event:selected */ export const addToSelectionMethod = function (elemsToAdd, showGrips) { - const selectedElements = selectionContext_.getSelectedElements(); + const selectedElements = svgCanvas.getSelectedElements(); if (!elemsToAdd.length) { return; } @@ -156,7 +154,7 @@ export const getMouseTargetMethod = function (evt) { while (mouseTarget.nodeName !== "foreignObject") { mouseTarget = mouseTarget.parentNode; if (!mouseTarget) { - return selectionContext_.getSVGRoot(); + return svgCanvas.getSvgRoot(); } } } @@ -164,11 +162,11 @@ export const getMouseTargetMethod = function (evt) { // Get the desired mouseTarget with jQuery selector-fu // If it's root-like, select the root const currentLayer = svgCanvas.getCurrentDrawing().getCurrentLayer(); - const svgRoot = selectionContext_.getSVGRoot(); - const container = selectionContext_.getDOMContainer(); - const content = selectionContext_.getSVGContent(); + const svgRoot = svgCanvas.getSvgRoot(); + const container = svgCanvas.getDOMContainer(); + const content = svgCanvas.getSvgContent(); if ([ svgRoot, container, content, currentLayer ].includes(mouseTarget)) { - return selectionContext_.getSVGRoot(); + return svgCanvas.getSvgRoot(); } // If it's a selection grip, return the grip parent @@ -180,7 +178,7 @@ export const getMouseTargetMethod = function (evt) { while ( !mouseTarget?.parentNode?.isSameNode( - selectionContext_.getCurrentGroup() || currentLayer + svgCanvas.getCurrentGroup() || currentLayer ) ) { mouseTarget = mouseTarget.parentNode; @@ -221,7 +219,7 @@ export const runExtensionsMethod = function ( nameFilter ) { let result = returnArray ? [] : false; - for (const [ name, ext ] of Object.entries(selectionContext_.getExtensions())) { + for (const [ name, ext ] of Object.entries(svgCanvas.getExtensions())) { if (nameFilter && !nameFilter(name)) { return; } @@ -249,8 +247,8 @@ export const runExtensionsMethod = function ( */ export const getVisibleElementsAndBBoxes = function (parent) { if (!parent) { - const svgcontent = selectionContext_.getSVGContent(); - parent = svgcontent.children; // Prevent layers from being included + const svgContent = svgCanvas.getSvgContent(); + parent = svgContent.children; // Prevent layers from being included } const contentElems = []; const elements = parent.children; @@ -275,28 +273,28 @@ export const getVisibleElementsAndBBoxes = function (parent) { * @returns {Element[]|NodeList} Bbox elements */ export const getIntersectionListMethod = function (rect) { - const currentZoom = selectionContext_.getCurrentZoom(); - if (!selectionContext_.getRubberBox()) { + const zoom = svgCanvas.getZoom(); + if (!svgCanvas.getRubberBox()) { return null; } const parent = - selectionContext_.getCurrentGroup() || + svgCanvas.getCurrentGroup() || svgCanvas.getCurrentDrawing().getCurrentLayer(); let rubberBBox; if (!rect) { - rubberBBox = getBBox(selectionContext_.getRubberBox()); - const bb = selectionContext_.getSVGContent().createSVGRect(); + rubberBBox = getBBox(svgCanvas.getRubberBox()); + const bb = svgCanvas.getSvgContent().createSVGRect(); [ "x", "y", "width", "height", "top", "right", "bottom", "left" ].forEach( (o) => { - bb[o] = rubberBBox[o] / currentZoom; + bb[o] = rubberBBox[o] / zoom; } ); rubberBBox = bb; } else { - rubberBBox = selectionContext_.getSVGContent().createSVGRect(); + rubberBBox = svgCanvas.getSvgContent().createSVGRect(); rubberBBox.x = rect.x; rubberBBox.y = rect.y; rubberBBox.width = rect.width; @@ -304,13 +302,13 @@ export const getIntersectionListMethod = function (rect) { } const resultList = []; - if (selectionContext_.getCurBBoxes().length === 0) { + if (svgCanvas.getCurBBoxes().length === 0) { // Cache all bboxes - selectionContext_.setCurBBoxes(getVisibleElementsAndBBoxes(parent)); + svgCanvas.setCurBBoxes(getVisibleElementsAndBBoxes(parent)); } - let i = selectionContext_.getCurBBoxes().length; + let i = svgCanvas.getCurBBoxes().length; while (i--) { - const curBBoxes = selectionContext_.getCurBBoxes(); + const curBBoxes = svgCanvas.getCurBBoxes(); if (!rubberBBox.width) { continue; } @@ -338,7 +336,7 @@ export const getIntersectionListMethod = function (rect) { * @returns {void} */ export const groupSvgElem = function (elem) { - const dataStorage = selectionContext_.getDataStorage(); + const dataStorage = svgCanvas.getDataStorage(); const g = document.createElementNS(NS.SVG, "g"); elem.replaceWith(g); g.appendChild(elem); @@ -374,7 +372,7 @@ export const prepareSvg = function (newDoc) { * @returns {void} */ export const setRotationAngle = function (val, preventUndo) { - const selectedElements = selectionContext_.getSelectedElements(); + const selectedElements = svgCanvas.getSelectedElements(); // ensure val is the proper type val = Number.parseFloat(val); const elem = selectedElements[0]; @@ -398,7 +396,7 @@ export const setRotationAngle = function (val, preventUndo) { cy, transformListToTransform(tlist).matrix ); - const Rnc = selectionContext_.getSVGRoot().createSVGTransform(); + const Rnc = svgCanvas.getSvgRoot().createSVGTransform(); Rnc.setRotate(val, center.x, center.y); if (tlist.numberOfItems) { tlist.insertItemBefore(Rnc, 0); @@ -433,7 +431,7 @@ export const setRotationAngle = function (val, preventUndo) { selectedElements[0] ); selector.resize(); - selectionContext_.getSelector().updateGripCursors(val); + svgCanvas.getSelector().updateGripCursors(val); }; /** @@ -445,9 +443,9 @@ export const setRotationAngle = function (val, preventUndo) { */ export const recalculateAllSelectedDimensions = function () { const text = - selectionContext_.getCurrentResizeMode() === "none" ? "position" : "size"; + svgCanvas.getCurrentResizeMode() === "none" ? "position" : "size"; const batchCmd = new BatchCommand(text); - const selectedElements = selectionContext_.getSelectedElements(); + const selectedElements = svgCanvas.getSelectedElements(); selectedElements.forEach((elem) => { const cmd = svgCanvas.recalculateDimensions(elem); @@ -457,7 +455,7 @@ export const recalculateAllSelectedDimensions = function () { }); if (!batchCmd.isEmpty()) { - selectionContext_.addCommandToHistory(batchCmd); + svgCanvas.addCommandToHistory(batchCmd); svgCanvas.call("changed", selectedElements); } }; diff --git a/src/svgcanvas/svg-exec.js b/src/svgcanvas/svg-exec.js index 955bfa9f..b2c31195 100644 --- a/src/svgcanvas/svg-exec.js +++ b/src/svgcanvas/svg-exec.js @@ -34,7 +34,6 @@ const { ChangeElementCommand, BatchCommand } = hstry; -let svgContext_ = null; let svgCanvas = null; /** @@ -42,9 +41,8 @@ let svgCanvas = null; * @param {module:svg-exec.SvgCanvas#init} svgContext * @returns {void} */ -export const init = function (svgContext) { - svgContext_ = svgContext; - svgCanvas = svgContext_.getCanvas(); +export const init = function (canvas) { + svgCanvas = canvas; }; /** @@ -59,23 +57,23 @@ export const svgCanvasToString = function () { svgCanvas.pathActions.clear(true); // Keep SVG-Edit comment on top - const childNodesElems = svgContext_.getSVGContent().childNodes; + const childNodesElems = svgCanvas.getSvgContent().childNodes; childNodesElems.forEach(function (node, i) { if (i && node.nodeType === 8 && node.data.includes('Created with')) { - svgContext_.getSVGContent().firstChild.before(node); + svgCanvas.getSvgContent().firstChild.before(node); } }); // Move out of in-group editing mode - if (svgContext_.getCurrentGroup()) { + if (svgCanvas.getCurrentGroup()) { draw.leaveContext(); - svgCanvas.selectOnly([ svgContext_.getCurrentGroup() ]); + svgCanvas.selectOnly([ svgCanvas.getCurrentGroup() ]); } const nakedSvgs = []; // Unwrap gsvg if it has no special attributes (only id and style) - const gsvgElems = svgContext_.getSVGContent().querySelectorAll('g[data-gsvg]'); + const gsvgElems = svgCanvas.getSvgContent().querySelectorAll('g[data-gsvg]'); Array.prototype.forEach.call(gsvgElems, function (element) { const attrs = element.attributes; let len = attrs.length; @@ -91,7 +89,7 @@ export const svgCanvasToString = function () { element.replaceWith(svg); } }); - const output = svgCanvas.svgToString(svgContext_.getSVGContent(), 0); + const output = svgCanvas.svgToString(svgCanvas.getSvgContent(), 0); // Rewrap gsvg if (nakedSvgs.length) { @@ -111,8 +109,8 @@ export const svgCanvasToString = function () { * @returns {string} The given element as an SVG tag */ export const svgToString = function (elem, indent) { - const curConfig = svgContext_.getCurConfig(); - const nsMap = svgContext_.getNsMap(); + const curConfig = svgCanvas.getCurConfig(); + const nsMap = svgCanvas.getNsMap(); const out = []; const unit = curConfig.baseUnit; const unitRe = new RegExp('^-?[\\d\\.]+' + unit + '$'); @@ -218,13 +216,13 @@ export const svgToString = function (elem, indent) { } // Embed images when saving - if (svgContext_.getSvgOptionApply() && + if (svgCanvas.getSvgOptionApply() && elem.nodeName === 'image' && attr.localName === 'href' && - svgContext_.getSvgOptionImages() && - svgContext_.getSvgOptionImages() === 'embed' + svgCanvas.getSvgOptionImages() && + svgCanvas.getSvgOptionImages() === 'embed' ) { - const img = svgContext_.getEncodableImages(attrVal); + const img = svgCanvas.getEncodableImages(attrVal); if (img) { attrVal = img; } } @@ -300,8 +298,8 @@ export const svgToString = function (elem, indent) { * unsuccessful, `true` otherwise. */ export const setSvgString = function (xmlString, preventUndo) { - const curConfig = svgContext_.getCurConfig(); - const dataStorage = svgContext_.getDataStorage(); + const curConfig = svgCanvas.getCurConfig(); + const dataStorage = svgCanvas.getDataStorage(); try { // convert string into XML document const newDoc = text2xml(xmlString); @@ -315,31 +313,31 @@ export const setSvgString = function (xmlString, preventUndo) { const batchCmd = new BatchCommand('Change Source'); // remove old svg document - const { nextSibling } = svgContext_.getSVGContent(); + const { nextSibling } = svgCanvas.getSvgContent(); - svgContext_.getSVGContent().remove(); - const oldzoom = svgContext_.getSVGContent(); - batchCmd.addSubCommand(new RemoveElementCommand(oldzoom, nextSibling, svgContext_.getSVGRoot())); + svgCanvas.getSvgContent().remove(); + const oldzoom = svgCanvas.getSvgContent(); + batchCmd.addSubCommand(new RemoveElementCommand(oldzoom, nextSibling, svgCanvas.getSvgRoot())); // set new svg document // If DOM3 adoptNode() available, use it. Otherwise fall back to DOM2 importNode() - if (svgContext_.getDOMDocument().adoptNode) { - svgContext_.setSVGContent(svgContext_.getDOMDocument().adoptNode(newDoc.documentElement)); + if (svgCanvas.getDOMDocument().adoptNode) { + svgCanvas.setSvgContent(svgCanvas.getDOMDocument().adoptNode(newDoc.documentElement)); } else { - svgContext_.setSVGContent(svgContext_.getDOMDocument().importNode(newDoc.documentElement, true)); + svgCanvas.setSvgContent(svgCanvas.getDOMDocument().importNode(newDoc.documentElement, true)); } - svgContext_.getSVGRoot().append(svgContext_.getSVGContent()); - const content = svgContext_.getSVGContent(); + svgCanvas.getSvgRoot().append(svgCanvas.getSvgContent()); + const content = svgCanvas.getSvgContent(); - svgCanvas.current_drawing_ = new draw.Drawing(svgContext_.getSVGContent(), svgContext_.getIdPrefix()); + svgCanvas.current_drawing_ = new draw.Drawing(svgCanvas.getSvgContent(), svgCanvas.getIdPrefix()); // retrieve or set the nonce const nonce = svgCanvas.getCurrentDrawing().getNonce(); if (nonce) { - svgContext_.call('setnonce', nonce); + svgCanvas.call('setnonce', nonce); } else { - svgContext_.call('unsetnonce'); + svgCanvas.call('unsetnonce'); } // change image href vals if possible @@ -456,7 +454,7 @@ export const setSvgString = function (xmlString, preventUndo) { // Give ID for any visible layer children missing one const chiElems = content.children; Array.prototype.forEach.call(chiElems, function (chiElem) { - const visElems = chiElem.querySelectorAll(svgContext_.getVisElems()); + const visElems = chiElem.querySelectorAll(svgCanvas.getVisElems()); Array.prototype.forEach.call(visElems, function (elem) { if (!elem.id) { elem.id = svgCanvas.getNextId(); } }); @@ -480,22 +478,22 @@ export const setSvgString = function (xmlString, preventUndo) { svgCanvas.contentW = attrs.width; svgCanvas.contentH = attrs.height; - batchCmd.addSubCommand(new InsertElementCommand(svgContext_.getSVGContent())); + batchCmd.addSubCommand(new InsertElementCommand(svgCanvas.getSvgContent())); // update root to the correct size const width = content.getAttribute('width'); const height = content.getAttribute('height'); const changes = { width: width, height: height }; - batchCmd.addSubCommand(new ChangeElementCommand(svgContext_.getSVGRoot(), changes)); + batchCmd.addSubCommand(new ChangeElementCommand(svgCanvas.getSvgRoot(), changes)); // reset zoom - svgContext_.setCurrentZoom(1); + svgCanvas.setZoom(1); svgCanvas.clearSelection(); pathModule.clearData(); - svgContext_.getSVGRoot().append(svgCanvas.selectorManager.selectorParentGroup); + svgCanvas.getSvgRoot().append(svgCanvas.selectorManager.selectorParentGroup); - if (!preventUndo) svgContext_.addCommandToHistory(batchCmd); - svgContext_.call('changed', [ svgContext_.getSVGContent() ]); + if (!preventUndo) svgCanvas.addCommandToHistory(batchCmd); + svgCanvas.call('changed', [ svgCanvas.getSvgContent() ]); } catch (e) { console.error(e); return false; @@ -519,7 +517,7 @@ export const setSvgString = function (xmlString, preventUndo) { * was obtained */ export const importSvgString = function (xmlString) { - const dataStorage = svgContext_.getDataStorage(); + const dataStorage = svgCanvas.getDataStorage(); let j; let ts; let useEl; try { // Get unique ID @@ -527,8 +525,8 @@ export const importSvgString = function (xmlString) { let useExisting = false; // Look for symbol and make sure symbol exists in image - if (svgContext_.getImportIds(uid) && svgContext_.getImportIds(uid).symbol) { - const parents = getParents(svgContext_.getImportIds(uid).symbol, '#svgroot'); + if (svgCanvas.getImportIds(uid) && svgCanvas.getImportIds(uid).symbol) { + const parents = getParents(svgCanvas.getImportIds(uid).symbol, '#svgroot'); if (parents.length) { useExisting = true; } @@ -537,8 +535,8 @@ export const importSvgString = function (xmlString) { const batchCmd = new BatchCommand('Import Image'); let symbol; if (useExisting) { - symbol = svgContext_.getImportIds(uid).symbol; - ts = svgContext_.getImportIds(uid).xform; + symbol = svgCanvas.getImportIds(uid).symbol; + ts = svgCanvas.getImportIds(uid).xform; } else { // convert string into XML document const newDoc = text2xml(xmlString); @@ -547,9 +545,9 @@ export const importSvgString = function (xmlString) { // import new svg document into our document // If DOM3 adoptNode() available, use it. Otherwise fall back to DOM2 importNode() - const svg = svgContext_.getDOMDocument().adoptNode - ? svgContext_.getDOMDocument().adoptNode(newDoc.documentElement) - : svgContext_.getDOMDocument().importNode(newDoc.documentElement, true); + const svg = svgCanvas.getDOMDocument().adoptNode + ? svgCanvas.getDOMDocument().adoptNode(newDoc.documentElement) + : svgCanvas.getDOMDocument().importNode(newDoc.documentElement, true); svgCanvas.uniquifyElems(svg); @@ -563,8 +561,8 @@ export const importSvgString = function (xmlString) { } // TODO: properly handle preserveAspectRatio - const // canvasw = +svgcontent.getAttribute('width'), - canvash = Number(svgContext_.getSVGContent().getAttribute('height')); + const // canvasw = +svgContent.getAttribute('width'), + canvash = Number(svgCanvas.getSvgContent().getAttribute('height')); // imported content should be 1/3 of the canvas on its largest dimension ts = innerh > innerw ? 'scale(' + (canvash / 3) / vb[3] + ')' : 'scale(' + (canvash / 3) / vb[2] + ')'; @@ -572,7 +570,7 @@ export const importSvgString = function (xmlString) { // Hack to make recalculateDimensions understand how to scale ts = 'translate(0) ' + ts + ' translate(0)'; - symbol = svgContext_.getDOMDocument().createElementNS(NS.SVG, 'symbol'); + symbol = svgCanvas.getDOMDocument().createElementNS(NS.SVG, 'symbol'); const defs = findDefs(); if (isGecko()) { @@ -596,7 +594,7 @@ export const importSvgString = function (xmlString) { symbol.id = svgCanvas.getNextId(); // Store data - svgContext_.setImportIds(uid, { + svgCanvas.setImportIds(uid, { symbol, xform: ts }); @@ -605,11 +603,11 @@ export const importSvgString = function (xmlString) { batchCmd.addSubCommand(new InsertElementCommand(symbol)); } - useEl = svgContext_.getDOMDocument().createElementNS(NS.SVG, 'use'); + useEl = svgCanvas.getDOMDocument().createElementNS(NS.SVG, 'use'); useEl.id = svgCanvas.getNextId(); svgCanvas.setHref(useEl, '#' + symbol.id); - (svgContext_.getCurrentGroup() || svgCanvas.getCurrentDrawing().getCurrentLayer()).append(useEl); + (svgCanvas.getCurrentGroup() || svgCanvas.getCurrentDrawing().getCurrentLayer()).append(useEl); batchCmd.addSubCommand(new InsertElementCommand(useEl)); svgCanvas.clearSelection(); @@ -623,8 +621,8 @@ export const importSvgString = function (xmlString) { // if (vb[0] !== 0 || vb[1] !== 0) { // ts = 'translate(' + (-vb[0]) + ',' + (-vb[1]) + ') ' + ts; // } - svgContext_.addCommandToHistory(batchCmd); - svgContext_.call('changed', [ svgContext_.getSVGContent() ]); + svgCanvas.addCommandToHistory(batchCmd); + svgCanvas.call('changed', [ svgCanvas.getSvgContent() ]); } catch (e) { console.error(e); return null; @@ -661,12 +659,12 @@ export const embedImage = function (src) { try { let urldata = ';svgedit_url=' + encodeURIComponent(src); urldata = cvs.toDataURL().replace(';base64', urldata + ';base64'); - svgContext_.setEncodableImages(src, urldata); + svgCanvas.setEncodableImages(src, urldata); } catch (e) { - svgContext_.setEncodableImages(src, false); + svgCanvas.setEncodableImages(src, false); } svgCanvas.setGoodImage(src); - resolve(svgContext_.getEncodableImages(src)); + resolve(svgCanvas.getEncodableImages(src)); }); imgI.addEventListener("error", (e) => { reject(`error loading image: ${e.currentTarget.attributes.src.value}`); @@ -686,7 +684,7 @@ export const embedImage = function (src) { * @returns {module:svgcanvas.IssuesAndCodes} */ function getIssues() { - const uiStrings = svgContext_.getUIStrings(); + const uiStrings = svgCanvas.getUIStrings(); // remove the selected outline before serializing svgCanvas.clearSelection(); @@ -700,7 +698,7 @@ function getIssues() { foreignObject: uiStrings.exportNoforeignObject, '[stroke-dasharray]': uiStrings.exportNoDashArray }; - const content = svgContext_.getSVGContent(); + const content = svgCanvas.getSvgContent(); // Add font/text check if Canvas Text API is not implemented if (!('font' in document.querySelector('CANVAS').getContext('2d'))) { @@ -751,7 +749,7 @@ export const rasterExport = async function (imgType, quality, exportWindowName, const iframe = document.createElement('iframe'); iframe.onload = function() { const iframedoc=iframe.contentDocument||iframe.contentWindow.document; - const ele = svgContext_.getSVGContent(); + const ele = svgCanvas.getSvgContent(); const cln = ele.cloneNode(true); iframedoc.body.appendChild(cln); setTimeout(function(){ @@ -771,7 +769,7 @@ export const rasterExport = async function (imgType, quality, exportWindowName, mimeType, quality, exportWindowName }; if (!opts.avoidEvent) { - svgContext_.call('exported', obj); + svgCanvas.call('exported', obj); } resolve(obj); } @@ -833,7 +831,7 @@ export const exportPDF = async ( const iframe = document.createElement('iframe'); iframe.onload = function() { const iframedoc=iframe.contentDocument||iframe.contentWindow.document; - const ele = svgContext_.getSVGContent(); + const ele = svgCanvas.getSvgContent(); const cln = ele.cloneNode(true); iframedoc.body.appendChild(cln); setTimeout(function(){ @@ -855,7 +853,7 @@ export const exportPDF = async ( outputType = outputType || 'dataurlstring'; const obj = { issues, issueCodes, exportWindowName, outputType }; obj.output = doc.output(outputType, outputType === 'save' ? (exportWindowName || 'svg.pdf') : undefined); - svgContext_.call('exportedPDF', obj); + svgCanvas.call('exportedPDF', obj); return obj; }); }, 1000); @@ -895,7 +893,7 @@ export const uniquifyElemsMethod = function (g) { // now search for all attributes on this element that might refer // to other elements - svgContext_.getrefAttrs().forEach(function(attr){ + svgCanvas.getrefAttrs().forEach(function(attr){ const attrnode = n.getAttributeNode(attr); if (attrnode) { // the incoming file has been sanitized, so we should be able to safely just strip off the leading # @@ -971,7 +969,7 @@ export const setUseDataMethod = function (parent) { } Array.prototype.forEach.call(elems, function (el, _) { - const dataStorage = svgContext_.getDataStorage(); + const dataStorage = svgCanvas.getDataStorage(); const id = svgCanvas.getHref(el).substr(1); const refElem = svgCanvas.getElem(id); if (!refElem) { return; } @@ -990,7 +988,7 @@ export const setUseDataMethod = function (parent) { * @returns {Integer} The number of elements that were removed */ export const removeUnusedDefElemsMethod = function () { - const defs = svgContext_.getSVGContent().getElementsByTagNameNS(NS.SVG, 'defs'); + const defs = svgCanvas.getSvgContent().getElementsByTagNameNS(NS.SVG, 'defs'); if (!defs || !defs.length) { return 0; } // if (!defs.firstChild) { return; } @@ -1000,7 +998,7 @@ export const removeUnusedDefElemsMethod = function () { const attrs = [ 'fill', 'stroke', 'filter', 'marker-start', 'marker-mid', 'marker-end' ]; const alen = attrs.length; - const allEls = svgContext_.getSVGContent().getElementsByTagNameNS(NS.SVG, '*'); + const allEls = svgCanvas.getSvgContent().getElementsByTagNameNS(NS.SVG, '*'); const allLen = allEls.length; let i; let j; @@ -1028,7 +1026,7 @@ export const removeUnusedDefElemsMethod = function () { const { id } = defelem; if (!defelemUses.includes(id)) { // Not found, so remove (but remember) - svgContext_.setRemovedElements(id, defelem); + svgCanvas.setRemovedElements(id, defelem); defelem.remove(); numRemoved++; } @@ -1053,16 +1051,16 @@ export const convertGradientsMethod = function (elem) { } Array.prototype.forEach.call(elems, function (grad) { if (grad.getAttribute('gradientUnits') === 'userSpaceOnUse') { - const svgcontent = svgContext_.getSVGContent(); + const svgContent = svgCanvas.getSvgContent(); // TODO: Support more than one element with this ref by duplicating parent grad - let fillStrokeElems = svgcontent.querySelectorAll('[fill="url(#' + grad.id + ')"],[stroke="url(#' + grad.id + ')"]'); + let fillStrokeElems = svgContent.querySelectorAll('[fill="url(#' + grad.id + ')"],[stroke="url(#' + grad.id + ')"]'); if (!fillStrokeElems.length) { - const tmpFillStrokeElems = svgcontent.querySelectorAll('[*|href="#' + grad.id + '"]'); + const tmpFillStrokeElems = svgContent.querySelectorAll('[*|href="#' + grad.id + '"]'); if (!tmpFillStrokeElems.length) { return; } else { if((tmpFillStrokeElems[0].tagName === "linearGradient" || tmpFillStrokeElems[0].tagName === "radialGradient") && tmpFillStrokeElems[0].getAttribute('gradientUnits') === 'userSpaceOnUse') { - fillStrokeElems = svgcontent.querySelectorAll('[fill="url(#' + tmpFillStrokeElems[0].id + ')"],[stroke="url(#' + tmpFillStrokeElems[0].id + ')"]'); + fillStrokeElems = svgContent.querySelectorAll('[fill="url(#' + tmpFillStrokeElems[0].id + ')"],[stroke="url(#' + tmpFillStrokeElems[0].id + ')"]'); } else { return; } diff --git a/src/svgcanvas/svgcanvas.js b/src/svgcanvas/svgcanvas.js index 44a073b0..b7a6a8a1 100644 --- a/src/svgcanvas/svgcanvas.js +++ b/src/svgcanvas/svgcanvas.js @@ -84,7 +84,7 @@ import { uniquifyElemsMethod, removeUnusedDefElemsMethod, convertGradientsMethod } from './svg-exec.js'; import { - isChrome, isWebkit + isChrome } from '../common/browser.js'; // , supportsEditableText import { remapElement, @@ -115,15 +115,19 @@ const { const visElems = 'a,circle,ellipse,foreignObject,g,image,line,path,polygon,polyline,rect,svg,text,tspan,use'; const refAttrs = [ 'clip-path', 'fill', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'stroke' ]; +const THRESHOLD_DIST = 0.8; +const STEP_COUNT = 10; +const CLIPBOARD_ID = 'svgedit_clipboard'; + if (!window.console) { window.console = {}; - window.console.log = function (_str) { /* empty fn */ }; - window.console.dir = function (_str) { /* empty fn */ }; + window.console.log = (_str) => { /* empty fn */ }; + window.console.dir = (_str) => { /* empty fn */ }; } if (window.opera) { - window.console.log = function (str) { window.opera.postError(str); }; - window.console.dir = function (_str) { /* empty fn */ }; + window.console.log = (str) => { window.opera.postError(str); }; + window.console.dir = (_str) => { /* empty fn */ }; } // Reenable after fixing eslint-plugin-jsdoc to handle @@ -160,10 +164,27 @@ class SvgCanvas { * @param {module:SVGeditor.configObj.curConfig} config - An object that contains configuration data */ constructor(container, config) { - // Alias Namespace constants + // imported methods + this.getJsonFromSvgElements = getJsonFromSvgElements; + this.addSVGElemensFromJson = addSVGElementsFromJson; + this.clearSvgContentElement = clearSvgContentElementInit; + this.textActions = textActionsMethod; + this.undoMgr = getUndoManager(); + this.getIntersectionList = getIntersectionListMethod; + this.getStrokedBBox = getStrokedBBoxDefaultVisible; + this.getVisibleElements = getVisibleElements; + this.uniquifyElems = uniquifyElemsMethod; + this.setUseData = setUseDataMethod; + this.convertGradients = convertGradientsMethod; + this.setSvgString = setSvgString; + this.importSvgString = importSvgString; + this.runExtensions = runExtensionsMethod; + this.clearSelection = clearSelectionMethod; + this.addToSelection = addToSelectionMethod; + // Default configuration options - let curConfig = { + this.curConfig = { show_outside_canvas: true, selectNew: true, dimensions: [ 640, 480 ] @@ -172,13 +193,11 @@ class SvgCanvas { // Update config with new one if given this.mergeDeep = mergeDeep; if (config) { - curConfig = this.mergeDeep(curConfig, config); + this.curConfig = this.mergeDeep(this.curConfig, config); } // Array with width/height of canvas - const { dimensions } = curConfig; - - const canvas = this; + const { dimensions } = this.curConfig; this.$id = $id; this.$qq = $qq; @@ -215,548 +234,153 @@ class SvgCanvas { return ret; } }; - const getDataStorage = this.getDataStorage = function () { return canvas.dataStorage; }; this.isLayer = draw.Layer.isLayer; // "document" element associated with the container (same as window.document using default svg-editor.js) // NOTE: This is not actually a SVG document, but an HTML document. - const svgdoc = window.document; + this.svgdoc = window.document; // This is a container for the document being edited, not the document itself. /** * @name module:svgcanvas~svgroot * @type {SVGSVGElement} */ - const svgroot = svgRootElement(svgdoc, dimensions); - const getSVGRoot = () => svgroot; - container.append(svgroot); + this.svgroot = svgRootElement(this.svgdoc, dimensions); + container.append(this.svgroot); /** * The actual element that represents the final output SVG element. * @name module:svgcanvas~svgcontent * @type {SVGSVGElement} */ - let svgcontent = svgdoc.createElementNS(NS.SVG, 'svg'); + this.svgContent = this.svgdoc.createElementNS(NS.SVG, 'svg'); - /** -* This should really be an intersection implementing all rather than a union. -* @type {module:draw.DrawCanvasInit#getSVGContent|module:utilities.EditorContext#getSVGContent} -*/ - const getSVGContent = () => { return svgcontent; }; - - clearInit( - /** - * @implements {module:utilities.EditorContext} - */ - { - getSVGContent, - getDOMDocument() { return svgdoc; }, - getDOMContainer() { return container; }, - getSVGRoot, - getCurConfig() { return curConfig; } - } - ); - /** -* This function resets the svgcontent element while keeping it in the DOM. -* @function module:svgcanvas.SvgCanvas#clearSvgContentElement -* @returns {void} -*/ - const clearSvgContentElement = canvas.clearSvgContentElement = clearSvgContentElementInit; - clearSvgContentElement(); + clearInit(this); + this.clearSvgContentElement(); // Prefix string for element IDs - let idprefix = 'svg_'; - - /** -* Changes the ID prefix to the given value. -* @function module:svgcanvas.SvgCanvas#setIdPrefix -* @param {string} p - String with the new prefix -* @returns {void} -*/ - canvas.setIdPrefix = function (p) { - idprefix = p; - }; + this.idprefix = 'svg_'; /** * Current `draw.Drawing` object. * @type {module:draw.Drawing} * @name module:svgcanvas.SvgCanvas#current_drawing_ */ - canvas.current_drawing_ = new draw.Drawing(svgcontent, idprefix); - - /** -* Returns the current Drawing. -* @name module:svgcanvas.SvgCanvas#getCurrentDrawing -* @type {module:draw.DrawCanvasInit#getCurrentDrawing} -*/ - const getCurrentDrawing = canvas.getCurrentDrawing = function () { - return canvas.current_drawing_; - }; - + this.current_drawing_ = new draw.Drawing(this.svgContent, this.idprefix); /** * Float displaying the current zoom level (1 = 100%, .5 = 50%, etc.). * @type {Float} */ - let currentZoom = 1; + this.zoom = 1; // pointer to current group (for in-group editing) - let currentGroup = null; + this.currentGroup = null; // Object containing data for the currently selected styles const allProperties = { shape: { - fill: (curConfig.initFill.color === 'none' ? '' : '#') + curConfig.initFill.color, + fill: (this.curConfig.initFill.color === 'none' ? '' : '#') + this.curConfig.initFill.color, fill_paint: null, - fill_opacity: curConfig.initFill.opacity, - stroke: '#' + curConfig.initStroke.color, + fill_opacity: this.curConfig.initFill.opacity, + stroke: '#' + this.curConfig.initStroke.color, stroke_paint: null, - stroke_opacity: curConfig.initStroke.opacity, - stroke_width: curConfig.initStroke.width, + stroke_opacity: this.curConfig.initStroke.opacity, + stroke_width: this.curConfig.initStroke.width, stroke_dasharray: 'none', stroke_linejoin: 'miter', stroke_linecap: 'butt', - opacity: curConfig.initOpacity + opacity: this.curConfig.initOpacity } }; allProperties.text = this.mergeDeep({}, allProperties.shape); allProperties.text = this.mergeDeep(allProperties.text, { fill: '#000000', - stroke_width: curConfig.text && curConfig.text.stroke_width, - font_size: curConfig.text && curConfig.text.font_size, - font_family: curConfig.text && curConfig.text.font_family + stroke_width: this.curConfig.text && this.curConfig.text.stroke_width, + font_size: this.curConfig.text && this.curConfig.text.font_size, + font_family: this.curConfig.text && this.curConfig.text.font_family }); // Current shape style properties - const curShape = allProperties.shape; + this.curShape = allProperties.shape; // Array with all the currently selected elements // default size of 1 until it needs to grow bigger - let selectedElements = []; + this.selectedElements = []; - jsonInit( - /** - * @implements {module:json.jsonContext} - */ - { - getDOMDocument() { return svgdoc; }, - getDrawing() { return getCurrentDrawing(); }, - getCurShape() { return curShape; }, - getCurrentGroup() { return currentGroup; } - } - ); + jsonInit(this); - /** -* @typedef {PlainObject} module:svgcanvas.SVGAsJSON -* @property {string} element -* @property {PlainObject} attr -* @property {module:svgcanvas.SVGAsJSON[]} children -*/ - - /** -* @function module:svgcanvas.SvgCanvas#getContentElem -* @param {Text|Element} data -* @returns {module:svgcanvas.SVGAsJSON} -*/ - const getJsonFromSvgElement = this.getJsonFromSvgElement = getJsonFromSvgElements; - - /** -* This should really be an intersection implementing all rather than a union. -* @name module:svgcanvas.SvgCanvas#addSVGElementFromJson -* @type {module:utilities.EditorContext#addSVGElementFromJson|module:path.EditorContext#addSVGElementFromJson} -*/ - const addSVGElementFromJson = this.addSVGElementFromJson = addSVGElementsFromJson; - - canvas.matrixMultiply = matrixMultiply; - canvas.hasMatrixTransform = hasMatrixTransform; - canvas.transformListToTransform = transformListToTransform; - - /** -* @type {module:utilities.EditorContext#getBaseUnit} -*/ - const getBaseUnit = () => { return curConfig.baseUnit; }; + this.matrixMultiply = matrixMultiply; + this.hasMatrixTransform = hasMatrixTransform; + this.transformListToTransform = transformListToTransform; /** * Initialize from units.js. * Send in an object implementing the ElementContainer interface (see units.js). */ - unitsInit( - /** - * @implements {module:units.ElementContainer} - */ - { - getBaseUnit, - getElement: getElem, - getHeight() { return svgcontent.getAttribute('height') / currentZoom; }, - getWidth() { return svgcontent.getAttribute('width') / currentZoom; }, - getRoundDigits() { return saveOptions.round_digits; } - } - ); - - canvas.convertToNum = convertToNum; - - /** -* Should really be an intersection with all needing to apply rather than a union. -* @name module:svgcanvas.SvgCanvas#getSelectedElements -* @type {module:utilities.EditorContext#getSelectedElements|module:draw.DrawCanvasInit#getSelectedElements|module:path.EditorContext#getSelectedElements} -*/ - const getSelectedElements = this.getSelectedElems = () => ( selectedElements ); - - this.setSelectedElements = (key, value) => { - selectedElements[key] = value; - }; - this.setEmptySelectedElements = () => { - selectedElements = []; - }; - + unitsInit(this); + this.convertToNum = convertToNum; const { pathActions } = pathModule; - - /** -* This should actually be an intersection as all interfaces should be met. -* @type {module:utilities.EditorContext#getSVGRoot|module:recalculate.EditorContext#getSVGRoot|module:coords.EditorContext#getSVGRoot|module:path.EditorContext#getSVGRoot} -*/ - - utilsInit( - /** - * @implements {module:utilities.EditorContext} - */ - { - pathActions, // Ok since not modifying - getSVGContent, - addSVGElementFromJson, - getSelectedElements, - getDOMDocument() { return svgdoc; }, - getDOMContainer() { return container; }, - getSVGRoot, - // TODO: replace this mostly with a way to get the current drawing. - getBaseUnit, - getSnappingStep() { return curConfig.snappingStep; }, - getDataStorage - } - ); - - canvas.findDefs = findDefs; - canvas.getUrlFromAttr = getUrlFromAttr; - canvas.getHref = getHref; - canvas.setHref = setHref; - /* const getBBox = */ canvas.getBBox = utilsGetBBox; - canvas.getRotationAngle = getRotationAngle; - canvas.getElem = getElem; - canvas.getRefElem = getRefElem; - canvas.assignAttributes = assignAttributes; - + utilsInit(this); + this.findDefs = findDefs; + this.getUrlFromAttr = getUrlFromAttr; + this.getHref = getHref; + this.setHref = setHref; + /* const getBBox = */ this.getBBox = utilsGetBBox; + this.getRotationAngle = getRotationAngle; + this.getElem = getElem; + this.getRefElem = getRefElem; + this.assignAttributes = assignAttributes; this.cleanupElement = cleanupElement; - - /** -* This should actually be an intersection not a union as all should apply. -* @type {module:coords.EditorContext#getGridSnapping|module:path.EditorContext#getGridSnapping} -*/ - const getGridSnapping = () => { return curConfig.gridSnapping; }; - - coordsInit( - /** - * @implements {module:coords.EditorContext} - */ - { - getDrawing() { return getCurrentDrawing(); }, - getDataStorage, - getSVGRoot, - getGridSnapping - } - ); + coordsInit(this); this.remapElement = remapElement; - - recalculateInit( - /** - * @implements {module:recalculate.EditorContext} - */ - { - getSVGRoot, - getStartTransform() { return startTransform; }, - setStartTransform(transform) { startTransform = transform; }, - getDataStorage - } - ); + recalculateInit(this); this.recalculateDimensions = recalculateDimensions; - // import from sanitize.js - const nsMap = getReverseNS(); - canvas.sanitizeSvg = sanitizeSvg; - - /** -* This should really be an intersection applying to all types rather than a union. -* @name module:svgcanvas.SvgCanvas#getZoom -* @type {module:path.EditorContext#getCurrentZoom|module:select.SVGFactory#getCurrentZoom} -*/ - const getCurrentZoom = this.getZoom = function () { return currentZoom; }; - - /** -* This method rounds the incoming value to the nearest value based on the `currentZoom` -* @name module:svgcanvas.SvgCanvas#round -* @type {module:path.EditorContext#round} -*/ - const round = this.round = function (val) { - return Number.parseInt(val * currentZoom) / currentZoom; - }; - - selectInit( - curConfig, - /** - * Export to select.js. - * @implements {module:select.SVGFactory} - */ - { - createSVGElement(jsonMap) { return canvas.addSVGElementFromJson(jsonMap); }, - svgRoot() { return svgroot; }, - svgContent() { return svgcontent; }, - getDataStorage, - getCurrentZoom - } - ); - /** -* This object manages selectors for us. -* @name module:svgcanvas.SvgCanvas#selectorManager -* @type {module:select.SelectorManager} -*/ - const selectorManager = this.selectorManager = getSelectorManager(); - - /** -* @name module:svgcanvas.SvgCanvas#getNextId -* @type {module:path.EditorContext#getNextId} -*/ - const getNextId = canvas.getNextId = function () { - return getCurrentDrawing().getNextId(); - }; - - /** -* @name module:svgcanvas.SvgCanvas#getId -* @type {module:path.EditorContext#getId} -*/ - const getId = canvas.getId = function () { - return getCurrentDrawing().getId(); - }; + this.nsMap = getReverseNS(); + this.sanitizeSvg = sanitizeSvg; + selectInit(this.curConfig, this); + this.selectorManager = getSelectorManager(); /** * The "implements" should really be an intersection applying to all types rather than a union. * @name module:svgcanvas.SvgCanvas#call * @type {module:draw.DrawCanvasInit#call|module:path.EditorContext#call} */ - const call = function (ev, arg) { + const call = (ev, arg) => { if (events[ev]) { return events[ev](window, arg); } return undefined; }; - const restoreRefElems = function (elem) { - // Look for missing reference elements, restore any found - const attrs = {}; - refAttrs.forEach(function (item, _) { - attrs[item] = elem.getAttribute(item); - }); - Object.values(attrs).forEach((val) => { - if (val && val.startsWith('url(')) { - const id = getUrlFromAttr(val).substr(1); - const ref = getElem(id); - if (!ref) { - findDefs().append(removedElements[id]); - delete removedElements[id]; - } - } - }); - - const childs = elem.getElementsByTagName('*'); - - if (childs.length) { - for (let i = 0, l = childs.length; i < l; i++) { - restoreRefElems(childs[i]); - } - } - }; - - undoInit( - /** - * @implements {module:undo.undoContext} - */ - { - call, - restoreRefElems, - getSVGContent, - getCanvas() { return canvas; }, - getCurrentMode() { return currentMode; }, - getCurrentZoom, - getSVGRoot, - getSelectedElements - } - ); - - /** -* @name undoMgr -* @memberof module:svgcanvas.SvgCanvas# -* @type {module:history.HistoryEventHandler} -*/ - const undoMgr = canvas.undoMgr = getUndoManager(); - - /** -* This should really be an intersection applying to all types rather than a union. -* @name module:svgcanvas~addCommandToHistory -* @type {module:path.EditorContext#addCommandToHistory|module:draw.DrawCanvasInit#addCommandToHistory} -*/ - const addCommandToHistory = function (cmd) { - canvas.undoMgr.addCommandToHistory(cmd); - }; - selectionInit( - /** - * @implements {module:selection.selectionContext} - */ - { - getCanvas() { return canvas; }, - getDataStorage, - getCurrentGroup() { return currentGroup; }, - getSelectedElements, - getSVGRoot, - getSVGContent, - getDOMContainer() { return container; }, - getExtensions() { return extensions; }, - setExtensions(key, value) { extensions[key] = value; }, - getCurrentZoom, - getRubberBox() { return rubberBox; }, - setCurBBoxes(value) { curBBoxes = value; }, - getCurBBoxes() { return curBBoxes; }, - getCurrentResizeMode() { return currentResizeMode; }, - addCommandToHistory, - getSelector() { return Selector; } - } - ); - - /** -* Clears the selection. The 'selected' handler is then optionally called. -* This should really be an intersection applying to all types rather than a union. -* @name module:svgcanvas.SvgCanvas#clearSelection -* @type {module:draw.DrawCanvasInit#clearSelection|module:path.EditorContext#clearSelection} -* @fires module:svgcanvas.SvgCanvas#event:selected -*/ - const clearSelection = this.clearSelection = clearSelectionMethod; - - /** -* Adds a list of elements to the selection. The 'selected' handler is then called. -* @name module:svgcanvas.SvgCanvas#addToSelection -* @type {module:path.EditorContext#addToSelection} -* @fires module:svgcanvas.SvgCanvas#event:selected -*/ - const addToSelection = this.addToSelection = addToSelectionMethod; - + undoInit(this); + selectionInit(this); /** * @type {module:path.EditorContext#getOpacity} */ const getOpacity = function () { - return curShape.opacity; + return this.curShape.opacity; }; - /** - * @name module:svgcanvas.SvgCanvas#getMouseTarget - * @type {module:path.EditorContext#getMouseTarget} - */ - const getMouseTarget = this.getMouseTarget = getMouseTargetMethod; - - /** -* @namespace {module:path.pathActions} pathActions -* @memberof module:svgcanvas.SvgCanvas# -* @see module:path.pathActions -*/ - canvas.pathActions = pathActions; - pathModule.init( - /** - * @implements {module:path.EditorContext} - */ - { - selectorManager, // Ok since not changing - canvas, // Ok since not changing - call, - round, - clearSelection, - addToSelection, - addCommandToHistory, - remapElement, - addSVGElementFromJson, - getGridSnapping, - getOpacity, - getSelectedElements, - getContainer() { - return container; - }, - setStarted(s) { - started = s; - }, - getRubberBox() { - return rubberBox; - }, - setRubberBox(rb) { - rubberBox = rb; - return rubberBox; - }, - /** - * @param {PlainObject} ptsInfo - * @param {boolean} ptsInfo.closedSubpath - * @param {SVGCircleElement[]} ptsInfo.grips - * @fires module:svgcanvas.SvgCanvas#event:pointsAdded - * @fires module:svgcanvas.SvgCanvas#event:selected - * @returns {void} - */ - addPtsToSelection({ closedSubpath, grips }) { - // TODO: Correct this: - pathActions.canDeleteNodes = true; - pathActions.closed_subpath = closedSubpath; - call('pointsAdded', { closedSubpath, grips }); - call('selected', grips); - }, - /** - * @param {PlainObject} changes - * @param {ChangeElementCommand} changes.cmd - * @param {SVGPathElement} changes.elem - * @fires module:svgcanvas.SvgCanvas#event:changed - * @returns {void} - */ - endChanges({ cmd, elem }) { - addCommandToHistory(cmd); - call('changed', [ elem ]); - }, - getCurrentZoom, - getId, - getNextId, - getMouseTarget, - getCurrentMode() { - return currentMode; - }, - setCurrentMode(cm) { - currentMode = cm; - return currentMode; - }, - getDrawnPath() { - return drawnPath; - }, - setDrawnPath(dp) { - drawnPath = dp; - return drawnPath; - }, - getSVGRoot - } - ); + this.getMouseTarget = getMouseTargetMethod; + this.pathActions = pathActions; + pathModule.init(this); // Interface strings, usually for title elements - const uiStrings = {}; + this.uiStrings = {}; // Animation element to change the opacity of any newly created element - const opacAni = document.createElementNS(NS.SVG, 'animate'); - opacAni.setAttribute('attributeName', 'opacity'); - opacAni.setAttribute('begin', 'indefinite'); - opacAni.setAttribute('dur', 1); - opacAni.setAttribute('fill', 'freeze'); - svgroot.appendChild(opacAni); + this.opacAni = document.createElementNS(NS.SVG, 'animate'); + this.opacAni.setAttribute('attributeName', 'opacity'); + this.opacAni.setAttribute('begin', 'indefinite'); + this.opacAni.setAttribute('dur', 1); + this.opacAni.setAttribute('fill', 'freeze'); + this.svgroot.appendChild(this.opacAni); // (function () { // TODO For Issue 208: this is a start on a thumbnail - // const svgthumb = svgdoc.createElementNS(NS.SVG, 'use'); + // const svgthumb = this.svgdoc.createElementNS(NS.SVG, 'use'); // svgthumb.setAttribute('width', '100'); // svgthumb.setAttribute('height', '100'); // setHref(svgthumb, '#svgcontent'); @@ -771,125 +395,40 @@ class SvgCanvas { */ // Object to contain image data for raster images that were found encodable - const encodableImages = {}; + this.addToSelectionencodableImages = {}; // Object with save options - /** - * @type {module:svgcanvas.SaveOptions} - */ - const saveOptions = { round_digits: 5 }; + this.saveOptions = { round_digits: 5 }; // Object with IDs for imported files, to see if one was already added - const importIds = {}; + this.importIds = {}; // Current text style properties - const curText = allProperties.text; + this.curText = allProperties.text; // Object to contain all included extensions - const extensions = {}; + this.extensions = {}; // Map of deleted reference elements - const removedElements = {}; + this.removedElements = {}; // String with image URL of last loadable image - let lastGoodImgUrl = `${curConfig.imgPath}/logo.svg`; - // Boolean indicating whether or not a draw action has been started - let started = false; + this.lastGoodImgUrl = `${this.curConfig.imgPath}/logo.svg`; + // Boolean indicating whether or not a draw action has been this.started + this.started = false; // String with an element's initial transform attribute value - let startTransform = null; + this.startTransform = null; // String indicating the current editor mode - let currentMode = 'select'; + this.currentMode = 'select'; // String with the current direction in which an element is being resized - let currentResizeMode = 'none'; + this.currentResizeMode = 'none'; // Current general properties - let curProperties = curShape; + this.curProperties = this.curShape; // Array with selected elements' Bounding box object // selectedBBoxes = new Array(1), // The DOM element that was just selected - let justSelected = null; + this.justSelected = null; // DOM element for selection rectangle drawn by the user - let rubberBox = null; + this.rubberBox = null; // Array of current BBoxes, used in getIntersectionList(). - let curBBoxes = []; + this.curBBoxes = []; // Canvas point for the most recent right click - let lastClickPoint = null; - - this.runExtension = function (name, action, vars) { - return this.runExtensions(action, vars, false, (n) => n === name); - }; - /* eslint-disable max-len */ - /** -* @todo Consider: Should this return an array by default, so extension results aren't overwritten? -* @todo Would be easier to document if passing in object with key of action and vars as value; could then define an interface which tied both together -* @function module:svgcanvas.SvgCanvas#runExtensions -* @param {"mouseDown"|"mouseMove"|"mouseUp"|"zoomChanged"|"IDsUpdated"|"canvasUpdated"|"toolButtonStateUpdate"|"selectedChanged"|"elementTransition"|"elementChanged"|"langReady"|"langChanged"|"addLangData"|"onNewDocument"|"workareaResized"} action -* @param {module:svgcanvas.SvgCanvas#event:ext_mouseDown|module:svgcanvas.SvgCanvas#event:ext_mouseMove|module:svgcanvas.SvgCanvas#event:ext_mouseUp|module:svgcanvas.SvgCanvas#event:ext_zoomChanged|module:svgcanvas.SvgCanvas#event:ext_IDsUpdated|module:svgcanvas.SvgCanvas#event:ext_canvasUpdated|module:svgcanvas.SvgCanvas#event:ext_toolButtonStateUpdate|module:svgcanvas.SvgCanvas#event:ext_selectedChanged|module:svgcanvas.SvgCanvas#event:ext_elementTransition|module:svgcanvas.SvgCanvas#event:ext_elementChanged|module:svgcanvas.SvgCanvas#event:ext_langReady|module:svgcanvas.SvgCanvas#event:ext_langChanged|module:svgcanvas.SvgCanvas#event:ext_addLangData|module:svgcanvas.SvgCanvas#event:ext_onNewDocument|module:svgcanvas.SvgCanvas#event:ext_workareaResized|module:svgcanvas.ExtensionVarBuilder} [vars] -* @param {boolean} [returnArray] -* @param {module:svgcanvas.ExtensionNameFilter} nameFilter -* @returns {GenericArray|module:svgcanvas.ExtensionStatus|false} See {@tutorial ExtensionDocs} on the ExtensionStatus. -*/ - /* eslint-enable max-len */ - - this.runExtensions = runExtensionsMethod; - - /** -* Add an extension to the editor. -* @function module:svgcanvas.SvgCanvas#addExtension -* @param {string} name - String with the ID of the extension. Used internally; no need for i18n. -* @param {module:svgcanvas.ExtensionInitCallback} [extInitFunc] - Function supplied by the extension with its data -* @param {module:svgcanvas.ExtensionInitArgs} initArgs -* @fires module:svgcanvas.SvgCanvas#event:extension_added -* @throws {TypeError|Error} `TypeError` if `extInitFunc` is not a function, `Error` -* if extension of supplied name already exists -* @returns {Promise} Resolves to `undefined` -*/ - this.addExtension = async function (name, extInitFunc, { importLocale }) { - if (typeof extInitFunc !== 'function') { - throw new TypeError('Function argument expected for `svgcanvas.addExtension`'); - } - if (name in extensions) { - throw new Error('Cannot add extension "' + name + '", an extension by that name already exists.'); - } - // Provide private vars/funcs here. Is there a better way to do this? - /** - * @typedef {module:svgcanvas.PrivateMethods} module:svgcanvas.ExtensionArgumentObject - * @property {SVGSVGElement} svgroot See {@link module:svgcanvas~svgroot} - * @property {SVGSVGElement} svgcontent See {@link module:svgcanvas~svgcontent} - * @property {!(string|Integer)} nonce See {@link module:draw.Drawing#getNonce} - * @property {module:select.SelectorManager} selectorManager - * @property {module:SVGEditor~ImportLocale} importLocale - */ - /** - * @type {module:svgcanvas.ExtensionArgumentObject} - * @see {@link module:svgcanvas.PrivateMethods} source for the other methods/properties - */ - const argObj = canvas.mergeDeep(canvas.getPrivateMethods(), { - importLocale, - svgroot, - svgcontent, - nonce: getCurrentDrawing().getNonce(), - selectorManager - }); - const extObj = await extInitFunc(argObj); - if (extObj) { - extObj.name = name; - } - extensions[name] = extObj; - return call('extension_added', extObj); - }; - - /** -* This method sends back an array or a NodeList full of elements that -* intersect the multi-select rubber-band-box on the currentLayer only. -* -* We brute-force `getIntersectionList` for browsers that do not support it (Firefox). -* -* Reference: -* Firefox does not implement `getIntersectionList()`, see {@link https://bugzilla.mozilla.org/show_bug.cgi?id=501421}. -* @function module:svgcanvas.SvgCanvas#getIntersectionList -* @param {SVGRect} rect -* @returns {Element[]|NodeList} Bbox elements -*/ - const getIntersectionList = this.getIntersectionList = getIntersectionListMethod; - - this.getStrokedBBox = getStrokedBBoxDefaultVisible; - - this.getVisibleElements = getVisibleElements; + this.lastClickPoint = null; /** * Wrap an SVG element into a group element, mark the group as 'gsvg'. @@ -904,7 +443,7 @@ class SvgCanvas { // Object to contain editor event names and callback functions const events = {}; - canvas.call = call; + this.call = call; /** * Array of what was changed (elements, layers). * @event module:svgcanvas.SvgCanvas#event:changed @@ -1035,7 +574,7 @@ class SvgCanvas { * @returns {module:svgcanvas.EventHandler} The previous event */ /* eslint-enable max-len */ - canvas.bind = function (ev, f) { + this.bind = function (ev, f) { const old = events[ev]; events[ev] = f; return old; @@ -1080,7 +619,7 @@ class SvgCanvas { }; // Root Current Transformation Matrix in user units - let rootSctm = null; + this.rootSctm = null; /** * Group: Selection. @@ -1095,9 +634,9 @@ class SvgCanvas { * @param {boolean} showGrips - Indicates whether the resize grips should be shown * @returns {void} */ - const selectOnly = this.selectOnly = function (elems, showGrips) { - clearSelection(true); - addToSelection(elems, showGrips); + const selectOnly = this.selectOnly = (elems, showGrips) => { + this.clearSelection(true); + this.addToSelection(elems, showGrips); }; // TODO: could use slice here to make this faster? @@ -1110,25 +649,25 @@ class SvgCanvas { * @returns {void} */ /* const removeFromSelection = */ this.removeFromSelection = function (elemsToRemove) { - if (isNullish(selectedElements[0])) { return; } + if (isNullish(this.selectedElements[0])) { return; } if (!elemsToRemove.length) { return; } // find every element and remove it from our array copy const newSelectedItems = []; - const len = selectedElements.length; + const len = this.selectedElements.length; for (let i = 0; i < len; ++i) { - const elem = selectedElements[i]; + const elem = this.selectedElements[i]; if (elem) { // keep the item if (!elemsToRemove.includes(elem)) { newSelectedItems.push(elem); } else { // remove the item and its selector - selectorManager.releaseSelector(elem); + this.selectorManager.releaseSelector(elem); } } } // the copy becomes the master now - selectedElements = newSelectedItems; + this.selectedElements = newSelectedItems; }; /** @@ -1137,130 +676,49 @@ class SvgCanvas { * @returns {void} */ this.selectAllInCurrentLayer = function () { - const currentLayer = getCurrentDrawing().getCurrentLayer(); + const currentLayer = this.getCurrentDrawing().getCurrentLayer(); if (currentLayer) { - currentMode = 'select'; - if (currentGroup) { - selectOnly(currentGroup.children); + this.currentMode = 'select'; + if (this.currentGroup) { + selectOnly(this.currentGroup.children); } else { selectOnly(currentLayer.children); } } }; - let drawnPath = null; + this.drawnPath = null; // Mouse events - (function () { - const freehand = { - minx: null, - miny: null, - maxx: null, - maxy: null - }; - const THRESHOLD_DIST = 0.8; - const STEP_COUNT = 10; - let dAttr = null; - let startX = null; - let startY = null; - let rStartX = null; - let rStartY = null; - let initBbox = {}; - let sumDistance = 0; - const controllPoint2 = { x: 0, y: 0 }; - const controllPoint1 = { x: 0, y: 0 }; - let start = { x: 0, y: 0 }; - const end = { x: 0, y: 0 }; - let bSpline = { x: 0, y: 0 }; - let nextPos = { x: 0, y: 0 }; - let parameter; - let nextParameter; + this.freehand = { + minx: null, + miny: null, + maxx: null, + maxy: null + }; - /** + this.dAttr = null; + this.startX = null; + this.startY = null; + this.rStartX = null; + this.rStartY = null; + this.initBbox = {}; + this.sumDistance = 0; + this.controllPoint2 = { x: 0, y: 0 }; + this.controllPoint1 = { x: 0, y: 0 }; + this.start = { x: 0, y: 0 }; + this.end = { x: 0, y: 0 }; + this.bSpline = { x: 0, y: 0 }; + this.nextPos = { x: 0, y: 0 }; + this.parameter; + this.nextParameter; + + /** * @function eventInit Initialize from event.js * @returns {void} */ - eventInit( - /** - * @implements {module:event.eventContext_} - */ - { - getStarted() { return started; }, - getCanvas() { return canvas; }, - getDataStorage, - getCurConfig() { return curConfig; }, - getCurrentMode() { return currentMode; }, - getrootSctm() { return rootSctm; }, - getStartX() { return startX; }, - setStartX(value) { startX = value; }, - getStartY() { return startY; }, - setStartY(value) { startY = value; }, - getRStartX() { return rStartX; }, - getRStartY() { return rStartY; }, - getRubberBox() { return rubberBox; }, - getInitBbox() { return initBbox; }, - getCurrentResizeMode() { return currentResizeMode; }, - getCurrentGroup() { return currentGroup; }, - getDrawnPath() { return drawnPath; }, - getJustSelected() { return justSelected; }, - getOpacAni() { return opacAni; }, - getParameter() { return parameter; }, - getNextParameter() { return nextParameter; }, - getStepCount() { return STEP_COUNT; }, - getThreSholdDist() { return THRESHOLD_DIST; }, - getSumDistance() { return sumDistance; }, - getStart(key) { return start[key]; }, - getEnd(key) { return end[key]; }, - getbSpline(key) { return bSpline[key]; }, - getNextPos(key) { return nextPos[key]; }, - getControllPoint1(key) { return controllPoint1[key]; }, - getControllPoint2(key) { return controllPoint2[key]; }, - getFreehand(key) { return freehand[key]; }, - getDrawing() { return getCurrentDrawing(); }, - getCurShape() { return curShape; }, - getDAttr() { return dAttr; }, - getLastGoodImgUrl() { return lastGoodImgUrl; }, - getCurText(key) { return curText[key]; }, - setDAttr(value) { dAttr = value; }, - setEnd(key, value) { end[key] = value; }, - setControllPoint1(key, value) { controllPoint1[key] = value; }, - setControllPoint2(key, value) { controllPoint2[key] = value; }, - setJustSelected(value) { justSelected = value; }, - setParameter(value) { parameter = value; }, - setStart(value) { start = value; }, - setRStartX(value) { rStartX = value; }, - setRStartY(value) { rStartY = value; }, - setSumDistance(value) { sumDistance = value; }, - setbSpline(value) { bSpline = value; }, - setNextPos(value) { nextPos = value; }, - setNextParameter(value) { nextParameter = value; }, - setCurProperties(key, value) { curProperties[key] = value; }, - setCurText(key, value) { curText[key] = value; }, - setStarted(s) { started = s; }, - setStartTransform(transform) { startTransform = transform; }, - setCurrentMode(cm) { - currentMode = cm; - return currentMode; - }, - setFreehand(key, value) { freehand[key] = value; }, - setCurBBoxes(value) { curBBoxes = value; }, - setRubberBox(value) { rubberBox = value; }, - setInitBbox(value) { initBbox = value; }, - setRootSctm(value) { rootSctm = value; }, - setCurrentResizeMode(value) { currentResizeMode = value; }, - setLastClickPoint(value) { lastClickPoint = value; }, - getSelectedElements, - getCurrentZoom, - getId, - addCommandToHistory, - getSVGRoot, - getSVGContent, - call, - getIntersectionList - } - ); - - /** + eventInit(this); + /** * Follows these conditions: * - When we are in a create mode, the element is added to the canvas but the * action is not recorded until mousing up. @@ -1270,120 +728,31 @@ class SvgCanvas { * @fires module:svgcanvas.SvgCanvas#event:ext_mouseDown * @returns {void} */ - const mouseDown = mouseDownEvent; - // in this function we do not record any state changes yet (but we do update - // any elements that are still being created, moved or resized on the canvas) - /** - * - * @param {MouseEvent} evt - * @fires module:svgcanvas.SvgCanvas#event:transition - * @fires module:svgcanvas.SvgCanvas#event:ext_mouseMove - * @returns {void} - */ - const mouseMove = mouseMoveEvent; + const mouseUp = mouseUpEvent.bind(this); + const mouseOut = mouseOutEvent.bind(this); + const dblClick = dblClickEvent.bind(this); - // - in create mode, the element's opacity is set properly, we create an InsertElementCommand - // and store it on the Undo stack - // - in move/resize mode, the element's attributes which were affected by the move/resize are - // identified, a ChangeElementCommand is created and stored on the stack for those attrs - // this is done in when we recalculate the selected dimensions() - /** - * - * @param {MouseEvent} evt - * @fires module:svgcanvas.SvgCanvas#event:zoomed - * @fires module:svgcanvas.SvgCanvas#event:changed - * @fires module:svgcanvas.SvgCanvas#event:ext_mouseUp - * @returns {void} - */ - const mouseUp = mouseUpEvent; - const mouseOut = mouseOutEvent; + // prevent links from being followed in the canvas + const handleLinkInCanvas = function (e) { + e.preventDefault(); + return false; + }; + container.addEventListener('mousedown', mouseDownEvent); + container.addEventListener('mousemove', mouseMoveEvent); + container.addEventListener('click', handleLinkInCanvas); + container.addEventListener('dblclick', dblClick); + container.addEventListener('mouseup', mouseUp); + container.addEventListener('mouseleave', mouseOut); + container.addEventListener('mousewheel', DOMMouseScrollEvent); + container.addEventListener('DOMMouseScroll', DOMMouseScrollEvent); - const dblClick = dblClickEvent; + textActionsInit(this); - // prevent links from being followed in the canvas - const handleLinkInCanvas = function (e) { - e.preventDefault(); - return false; - }; + this.getSvgOption = () => { return this.saveOptions; }; + this.setSvgOption = (key, value) => { this.saveOptions[key] = value; }; - // Added mouseup to the container here. - // TODO(codedread): Figure out why after the Closure compiler, the window mouseup is ignored. - container.addEventListener('mousedown', mouseDown); - container.addEventListener('mousemove', mouseMove); - container.addEventListener('click', handleLinkInCanvas); - container.addEventListener('dblclick', dblClick); - container.addEventListener('mouseup', mouseUp); - container.addEventListener('mouseleave', mouseOut); - - // TODO(rafaelcastrocouto): User preference for shift key and zoom factor - container.addEventListener('mousewheel', DOMMouseScrollEvent); - container.addEventListener('DOMMouseScroll', DOMMouseScrollEvent); - - }()); - - textActionsInit( - /** - * @implements {module:text-actions.textActionsContext} - */ - { - getCanvas() { return canvas; }, - getrootSctm() { return rootSctm; }, - getSelectedElements, - getCurrentZoom, - getCurrentMode() { - return currentMode; - }, - setCurrentMode(cm) { - currentMode = cm; - return currentMode; - }, - getSVGRoot, - call - } - ); - - const textActions = canvas.textActions = textActionsMethod; - - /** -* Group: Serialization. -*/ - this.getSvgOption = () => { return saveOptions; }; - this.setSvgOption = (key, value) => { saveOptions[key] = value; }; - - svgInit( - /** - * @implements {module:elem-get-set.elemInit} - */ - { - getCanvas() { return canvas; }, - getDataStorage, - getSVGContent, - getSVGRoot, - getUIStrings() { return uiStrings; }, - getCurrentGroup() { return currentGroup; }, - getCurConfig() { return curConfig; }, - getNsMap() { return nsMap; }, - getSvgOption: this.getSvgOption, - setSvgOption: this.setSvgOption, - getSvgOptionApply() { return saveOptions.apply; }, - getSvgOptionImages() { return saveOptions.images; }, - getEncodableImages(key) { return encodableImages[key]; }, - setEncodableImages(key, value) { encodableImages[key] = value; }, - call, - getDOMDocument() { return svgdoc; }, - getVisElems() { return visElems; }, - getIdPrefix() { return idprefix; }, - setCurrentZoom(value) { currentZoom = value; }, - getImportIds(key) { return importIds[key]; }, - setImportIds(key, value) { importIds[key] = value; }, - setRemovedElements(key, value) { removedElements[key] = value; }, - setSVGContent(value) { svgcontent = value; }, - getrefAttrs() { return refAttrs; }, - getcanvg() { return canvg; }, - addCommandToHistory - } - ); + svgInit(this); /** * Looks at DOM elements inside the `` to see if they are referred to, @@ -1430,7 +799,7 @@ class SvgCanvas { * @returns {void} */ this.setGoodImage = function (val) { - lastGoodImgUrl = val; + this.lastGoodImgUrl = val; }; /** @@ -1511,7 +880,7 @@ class SvgCanvas { * @returns {string} The current drawing as raw SVG XML text. */ this.getSvgString = function () { - saveOptions.apply = false; + this.saveOptions.apply = false; return this.svgCanvasToString(); }; @@ -1527,67 +896,12 @@ class SvgCanvas { */ this.randomizeIds = function (enableRandomization) { if (arguments.length > 0 && enableRandomization === false) { - draw.randomizeIds(false, getCurrentDrawing()); + draw.randomizeIds(false, this.getCurrentDrawing()); } else { - draw.randomizeIds(true, getCurrentDrawing()); + draw.randomizeIds(true, this.getCurrentDrawing()); } }; - /** -* Ensure each element has a unique ID. -* @function module:svgcanvas.SvgCanvas#uniquifyElems -* @param {Element} g - The parent element of the tree to give unique IDs -* @returns {void} -*/ - const uniquifyElems = this.uniquifyElems = uniquifyElemsMethod; - - /** -* Assigns reference data for each use element. -* @function module:svgcanvas.SvgCanvas#setUseData -* @param {Element} parent -* @returns {void} -*/ - const setUseData = this.setUseData = setUseDataMethod; - - /** -* Converts gradients from userSpaceOnUse to objectBoundingBox. -* @function module:svgcanvas.SvgCanvas#convertGradients -* @param {Element} elem -* @returns {void} -*/ - const convertGradients = this.convertGradients = convertGradientsMethod; - - /** -* This function sets the current drawing as the input SVG XML. -* @function module:svgcanvas.SvgCanvas#setSvgString -* @param {string} xmlString - The SVG as XML text. -* @param {boolean} [preventUndo=false] - Indicates if we want to do the -* changes without adding them to the undo stack - e.g. for initializing a -* drawing on page load. -* @fires module:svgcanvas.SvgCanvas#event:setnonce -* @fires module:svgcanvas.SvgCanvas#event:unsetnonce -* @fires module:svgcanvas.SvgCanvas#event:changed -* @returns {boolean} This function returns `false` if the set was -* unsuccessful, `true` otherwise. -*/ - this.setSvgString = setSvgString; - - /** -* This function imports the input SVG XML as a `` in the ``, then adds a -* `` to the current layer. -* @function module:svgcanvas.SvgCanvas#importSvgString -* @param {string} xmlString - The SVG as XML text. -* @fires module:svgcanvas.SvgCanvas#event:changed -* @returns {null|Element} This function returns null if the import was unsuccessful, or the element otherwise. -* @todo -* - properly handle if namespace is introduced by imported content (must add to svgcontent -* and update all prefixes in the imported node) -* - properly handle recalculating dimensions, `recalculateDimensions()` doesn't handle -* arbitrary transform lists, but makes some assumptions about how the transform list -* was obtained -*/ - this.importSvgString = importSvgString; - // Could deprecate, but besides external uses, their usage makes clear that // canvas is a dependency for all of these const dr = { @@ -1597,120 +911,14 @@ class SvgCanvas { leaveContext, setContext }; Object.entries(dr).forEach(([ prop, propVal ]) => { - canvas[prop] = propVal; + this[prop] = propVal; }); - draw.init( - /** - * @implements {module:draw.DrawCanvasInit} - */ - { - pathActions, - getDataStorage, - getCurrentGroup() { - return currentGroup; - }, - setCurrentGroup(cg) { - currentGroup = cg; - }, - getSelectedElements, - getSVGContent, - undoMgr, - getCurrentDrawing, - clearSelection, - call, - addCommandToHistory, - /** - * @fires module:svgcanvas.SvgCanvas#event:changed - * @returns {void} - */ - changeSVGContent() { - call('changed', [ svgcontent ]); - } - } - ); - - /** -* Group: Document functions. -*/ - - /** -* Clears the current document. This is not an undoable action. -* @function module:svgcanvas.SvgCanvas#clear -* @fires module:svgcanvas.SvgCanvas#event:cleared -* @returns {void} -*/ - this.clear = function () { - pathActions.clear(); - - clearSelection(); - - // clear the svgcontent node - canvas.clearSvgContentElement(); - - // create new document - canvas.current_drawing_ = new draw.Drawing(svgcontent); - - // create empty first layer - canvas.createLayer('Layer 1'); - - // clear the undo stack - canvas.undoMgr.resetUndoStack(); - - // reset the selector manager - selectorManager.initGroup(); - - // reset the rubber band box - rubberBox = selectorManager.getRubberBandBox(); - - call('cleared'); - }; + draw.init(this); // Alias function this.linkControlPoints = pathActions.linkControlPoints; - /** -* @function module:svgcanvas.SvgCanvas#getContentElem -* @returns {Element} The content DOM element -*/ - this.getContentElem = function () { return svgcontent; }; - - /** -* @function module:svgcanvas.SvgCanvas#getRootElem -* @returns {SVGSVGElement} The root DOM element -*/ - this.getRootElem = function () { return svgroot; }; - - elemInit( - /** - * @implements {module:elem-get-set.elemInit} - */ - { - addCommandToHistory, - getCurrentZoom, - getSVGContent, - getSelectedElements, - call, - changeSelectedAttributeNoUndoMethod, - getDOMDocument() { return svgdoc; }, - getCanvas() { return canvas; }, - getDataStorage, - setCanvas(key, value) { canvas[key] = value; }, - setCurrentZoom(value) { currentZoom = value; }, - setCurProperties(key, value) { curProperties[key] = value; }, - getCurProperties(key) { return curProperties[key]; }, - setCurShape(key, value) { curShape[key] = value; }, - getCurText(key) { return curText[key]; }, - setCurText(key, value) { curText[key] = value; } - } - ); - - /** -* @typedef {PlainObject} DimensionsAndZoom -* @property {Float} w Width -* @property {Float} h Height -* @property {Float} zoom Zoom -*/ - + elemInit(this); /** * @function module:svgcanvas.SvgCanvas#getResolution * @returns {DimensionsAndZoom} The current dimensions and zoom level in an object @@ -1721,7 +929,7 @@ class SvgCanvas { * @function module:svgcanvas.SvgCanvas#getSnapToGrid * @returns {boolean} The current snap to grid setting */ - this.getSnapToGrid = function () { return curConfig.gridSnapping; }; + this.getSnapToGrid = function () { return this.curConfig.gridSnapping; }; /** * @function module:svgcanvas.SvgCanvas#getVersion @@ -1738,7 +946,7 @@ class SvgCanvas { * @returns {void} */ this.setUiStrings = function (strs) { - Object.assign(uiStrings, strs.notification); + Object.assign(this.uiStrings, strs.notification); pathModule.setUiStrings(strs); }; @@ -1749,7 +957,7 @@ class SvgCanvas { * @returns {void} */ this.setConfig = function (opts) { - Object.assign(curConfig, opts); + Object.assign(this.curConfig, opts); }; /** @@ -1774,7 +982,7 @@ class SvgCanvas { * @returns {string|void} The current document title or an empty string if not found */ this.getDocumentTitle = function () { - return canvas.getTitle(svgcontent); + return this.getTitle(this.svgContent); }; /** @@ -1815,10 +1023,10 @@ class SvgCanvas { /** * @function module:svgcanvas.SvgCanvas#getOffset * @returns {module:svgcanvas.ElementPositionInCanvas} An object with `x`, `y` values indicating the svgcontent element's -* position in the editor's canvas. +* position in the editor's this. */ this.getOffset = function () { - return { x: Number(svgcontent.getAttribute('x')), y: Number(svgcontent.getAttribute('y')) }; + return { x: Number(this.svgContent.getAttribute('x')), y: Number(this.svgContent.getAttribute('y')) }; }; /** @@ -1913,28 +1121,7 @@ class SvgCanvas { * @fires module:svgcanvas.SvgCanvas#event:ext_zoomChanged * @returns {void} */ - this.setZoom = setZoomMethod; - - /** -* @function module:svgcanvas.SvgCanvas#getMode -* @returns {string} The current editor mode string -*/ - this.getMode = function () { - return currentMode; - }; - - /** -* Sets the editor's mode to the given string. -* @function module:svgcanvas.SvgCanvas#setMode -* @param {string} name - String with the new mode to change to -* @returns {void} -*/ - this.setMode = function (name) { - pathActions.clear(true); - textActions.clear(); - curProperties = (selectedElements[0] && selectedElements[0].nodeName === 'text') ? curText : curShape; - currentMode = name; - }; + this.setCurrentZoom = setZoomMethod; /** * Group: Element Styling. @@ -1951,7 +1138,7 @@ class SvgCanvas { * @returns {string|module:svgcanvas.PaintOptions|Float|module:jGraduate~Paint} The current fill/stroke option */ this.getColor = function (type) { - return curProperties[type]; + return this.curProperties[type]; }; /** @@ -2005,7 +1192,7 @@ class SvgCanvas { * @returns {Float|string} The current stroke-width value */ this.getStrokeWidth = function () { - return curProperties.stroke_width; + return this.curProperties.stroke_width; }; /** @@ -2046,7 +1233,7 @@ class SvgCanvas { * @returns {module:svgcanvas.StyleOptions} current style options */ this.getStyle = function () { - return curShape; + return this.curShape; }; /** @@ -2062,7 +1249,7 @@ class SvgCanvas { * @returns {void} */ this.setOpacity = function (val) { - curShape.opacity = val; + this.curShape.opacity = val; changeSelectedAttribute('opacity', val); }; @@ -2071,7 +1258,7 @@ class SvgCanvas { * @returns {Float} the current fill opacity */ this.getFillOpacity = function () { - return curShape.fill_opacity; + return this.curShape.fill_opacity; }; /** @@ -2079,7 +1266,7 @@ class SvgCanvas { * @returns {string} the current stroke opacity */ this.getStrokeOpacity = function () { - return curShape.stroke_opacity; + return this.curShape.stroke_opacity; }; /** @@ -2091,7 +1278,7 @@ class SvgCanvas { * @returns {void} */ this.setPaintOpacity = function (type, val, preventUndo) { - curShape[type + '_opacity'] = val; + this.curShape[type + '_opacity'] = val; if (!preventUndo) { changeSelectedAttribute(type + '-opacity', val); } else { @@ -2117,8 +1304,6 @@ class SvgCanvas { */ this.getBlur = function (elem) { let val = 0; - // const elem = selectedElements[0]; - if (elem) { const filterUrl = elem.getAttribute('filter'); if (filterUrl) { @@ -2137,40 +1322,20 @@ class SvgCanvas { return val; }; - (function () { - let curCommand = null; - let filter = null; - let filterHidden = false; + this.curCommand = null; + this.filter = null; + this.filterHidden = false; - blurInit( - /** - * @implements {module:elem-get-set.elemInit} - */ - { - getCanvas() { return canvas; }, - getCurCommand() { return curCommand; }, - setCurCommand(value) { curCommand = value; }, - getFilter() { return filter; }, - setFilter(value) { filter = value; }, - getFilterHidden() { return filterHidden; }, - setFilterHidden(value) { filterHidden = value; }, - changeSelectedAttributeNoUndoMethod, - changeSelectedAttributeMethod, - isWebkit, - addCommandToHistory, - getSelectedElements - } - ); - - /** + blurInit(this); + /** * Sets the `stdDeviation` blur value on the selected element without being undoable. * @function module:svgcanvas.SvgCanvas#setBlurNoUndo * @param {Float} val - The new `stdDeviation` value * @returns {void} */ - canvas.setBlurNoUndo = setBlurNoUndo; + this.setBlurNoUndo = setBlurNoUndo; - /** + /** * Sets the `x`, `y`, `width`, `height` values of the filter element in order to * make the blur not be clipped. Removes them if not neeeded. * @function module:svgcanvas.SvgCanvas#setBlurOffsets @@ -2178,17 +1343,17 @@ class SvgCanvas { * @param {Float} stdDev - The standard deviation value on which to base the offset size * @returns {void} */ - canvas.setBlurOffsets = setBlurOffsets; + this.setBlurOffsets = setBlurOffsets; - /** + /** * Adds/updates the blur filter to the selected element. * @function module:svgcanvas.SvgCanvas#setBlur * @param {Float} val - Float with the new `stdDeviation` blur value * @param {boolean} complete - Whether or not the action should be completed (to add to the undo manager) * @returns {void} */ - canvas.setBlur = setBlur; - }()); + this.setBlur = setBlur; + /** * Check whether selected element is bold or not. @@ -2347,34 +1512,34 @@ class SvgCanvas { * @returns {void|DOMRect|false|SVGPathElement|null} If the getBBox flag is true, the resulting path's bounding box object. * Otherwise the resulting path element is returned. */ - this.convertToPath = function (elem, getBBox) { + this.convertToPath = (elem, getBBox) => { if (isNullish(elem)) { - const elems = selectedElements; + const elems = this.selectedElements; elems.forEach(function(el){ - if (el) { canvas.convertToPath(el); } + if (el) { this.convertToPath(el); } }); return undefined; } if (getBBox) { - return getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions); + return getBBoxOfElementAsPath(elem, this.addSVGElemensFromJson, pathActions); } - // TODO: Why is this applying attributes from curShape, then inside utilities.convertToPath it's pulling addition attributes from elem? - // TODO: If convertToPath is called with one elem, curShape and elem are probably the same; but calling with multiple is a bug or cool feature. + // TODO: Why is this applying attributes from this.curShape, then inside utilities.convertToPath it's pulling addition attributes from elem? + // TODO: If convertToPath is called with one elem, this.curShape and elem are probably the same; but calling with multiple is a bug or cool feature. const attrs = { - fill: curShape.fill, - 'fill-opacity': curShape.fill_opacity, - stroke: curShape.stroke, - 'stroke-width': curShape.stroke_width, - 'stroke-dasharray': curShape.stroke_dasharray, - 'stroke-linejoin': curShape.stroke_linejoin, - 'stroke-linecap': curShape.stroke_linecap, - 'stroke-opacity': curShape.stroke_opacity, - opacity: curShape.opacity, + fill: this.curShape.fill, + 'fill-opacity': this.curShape.fill_opacity, + stroke: this.curShape.stroke, + 'stroke-width': this.curShape.stroke_width, + 'stroke-dasharray': this.curShape.stroke_dasharray, + 'stroke-linejoin': this.curShape.stroke_linejoin, + 'stroke-linecap': this.curShape.stroke_linecap, + 'stroke-opacity': this.curShape.stroke_opacity, + opacity: this.curShape.opacity, visibility: 'hidden' }; return convertToPath( - elem, attrs, addSVGElementFromJson, pathActions, - clearSelection, addToSelection, hstry, addCommandToHistory + elem, attrs, this.addSVGElemensFromJson, pathActions, + this.clearSelection, this.addToSelection, hstry, this.addCommandToHistory ); }; @@ -2405,42 +1570,7 @@ class SvgCanvas { * Initialize from select-elem.js. * Send in an object implementing the ElementContainer interface (see select-elem.js). */ - selectedElemInit( - /** - * @implements {module:selected-elem.elementContext} - */ - { - getSelectedElements, - addCommandToHistory, - getJsonFromSvgElement, - addSVGElementFromJson, - changeSelectedAttribute, - flashStorage, - call, - getIntersectionList, - setCurBBoxes(value) { curBBoxes = value; }, - getSVGRoot, - gettingSelectorManager() { return selectorManager; }, - getCurrentZoom, - getDrawing() { return getCurrentDrawing(); }, - getCurrentGroup() { return currentGroup; }, - addToSelection, - getContentW() { return canvas.contentW; }, - getContentH() { return canvas.contentH; }, - getClipboardID() { return CLIPBOARD_ID; }, - getDOMDocument() { return svgdoc; }, - clearSelection, - getNextId, - selectOnly, - uniquifyElems, - setUseData, - convertGradients, - getSVGContent, - getCanvas() { return canvas; }, - getDataStorage, - getVisElems() { return visElems; } - } - ); + selectedElemInit(this); /** * Removes all selected elements from the DOM and adds the change to the @@ -2457,13 +1587,11 @@ class SvgCanvas { * @function module:svgcanvas.SvgCanvas#cutSelectedElements * @returns {void} */ - this.cutSelectedElements = function () { - canvas.copySelectedElements(); - canvas.deleteSelectedElements(); + this.cutSelectedElements = () => { + this.copySelectedElements(); + this.deleteSelectedElements(); }; - const CLIPBOARD_ID = 'svgedit_clipboard'; - /** * Flash the clipboard data momentarily on localStorage so all tabs can see. * @returns {void} @@ -2504,33 +1632,7 @@ class SvgCanvas { */ this.copySelectedElements = copySelectedElements; - /** - * @function pasteInit Initialize from paste-elem.js. - * @returns {void} - * paste element functionality - */ - pasteInit( - /** - * @implements {module:event.eventContext_} - */ - { - getCanvas() { return canvas; }, - getClipBoardID() { return CLIPBOARD_ID; }, - getLastClickPoint(key) { return lastClickPoint[key]; }, - addCommandToHistory, - restoreRefElems - } - ); - - /** -* @function module:svgcanvas.SvgCanvas#pasteElements -* @param {"in_place"|"point"|void} type -* @param {Integer|void} x Expected if type is "point" -* @param {Integer|void} y Expected if type is "point" -* @fires module:svgcanvas.SvgCanvas#event:changed -* @fires module:svgcanvas.SvgCanvas#event:ext_IDsUpdated -* @returns {void} -*/ + pasteInit(this); this.pasteElements = pasteElementsMethod; /** @@ -2713,9 +1815,9 @@ class SvgCanvas { * @function module:svgcanvas.SvgCanvas#getPrivateMethods * @returns {module:svgcanvas.PrivateMethods} */ - this.getPrivateMethods = function () { + this.getPrivateMethods = () => { return { - addCommandToHistory, + addCommandToHistory: this.addCommandToHistory, BatchCommand, ChangeElementCommand, decode64, @@ -2744,6 +1846,259 @@ class SvgCanvas { }; }; } // End constructor + getSelectedElements() { return this.selectedElements; } + setSelectedElements(key, value) { + this.selectedElements[key] = value; + } + setEmptySelectedElements() { this.selectedElements = []; } + getSvgRoot() { return this.svgroot; } + getDOMDocument() { return this.svgdoc; } + getDOMContainer() { return this.container; } + getCurConfig() { return this.curConfig; } + setIdPrefix(p) { this.idprefix = p; } + getCurrentDrawing() { return this.current_drawing_;} + getCurShape() { return this.curShape; } + getCurrentGroup() { return this.currentGroup; } + getBaseUnit() { return this.curConfig.baseUnit; } + getHeight() { return this.svgContent.getAttribute('height') / this.zoom; } + getWidth() { return this.svgContent.getAttribute('width') / this.zoom; } + getRoundDigits() { return this.saveOptions.round_digits; } + getSnappingStep() { return this.curConfig.snappingStep; } + getGridSnapping() { return this.curConfig.gridSnapping; } + getStartTransform() { return this.startTransform; } + setStartTransform(transform) { this.startTransform = transform; } + getZoom () { return this.zoom; } + round(val) { return Number.parseInt(val * this.zoom) / this.zoom; } + createSVGElement(jsonMap) { return this.addSVGElemensFromJson(jsonMap); } + getContainer() { return this.container; } + setStarted(s) { this.started = s; } + getRubberBox() { return this.rubberBox; } + setRubberBox(rb) { + this.rubberBox = rb; + return this.rubberBox; + } + addPtsToSelection({ closedSubpath, grips }) { + // TODO: Correct this: + this.pathActions.canDeleteNodes = true; + this.pathActions.closed_subpath = closedSubpath; + this.call('pointsAdded', { closedSubpath, grips }); + this.call('selected', grips); + } + /** + * @param {PlainObject} changes + * @param {ChangeElementCommand} changes.cmd + * @param {SVGPathElement} changes.elem + * @fires module:svgcanvas.SvgCanvas#event:changed + * @returns {void} + */ + endChanges({ cmd, elem }) { + this.addCommandToHistory(cmd); + this.call('changed', [ elem ]); + } + getCurrentMode() { + return this.currentMode; + } + setCurrentMode(cm) { + this.currentMode = cm; + return this.currentMode; + } + getDrawnPath() { + return this.drawnPath; + } + setDrawnPath(dp) { + this.drawnPath = dp; + return this.drawnPath; + } + setCurrentGroup(cg) { + this.currentGroup = cg; + } + changeSvgContent() { + this.call('changed', [ this.svgContent ]); + } + getStarted() { return this.started; } + getCanvas() { return this; } + getrootSctm() { return this.rootSctm; } + getStartX() { return this.startX; } + setStartX(value) { this.startX = value; } + getStartY() { return this.startY; } + setStartY(value) { this.startY = value; } + getRStartX() { return this.rStartX; } + getRStartY() { return this.rStartY; } + getInitBbox() { return this.initBbox; } + getCurrentResizeMode() { return this.currentResizeMode; } + getJustSelected() { return this.justSelected; } + getOpacAni() { return this.opacAni; } + getParameter() { return this.parameter; } + getNextParameter() { return this.nextParameter; } + getStepCount() { return STEP_COUNT; } + getThreSholdDist() { return THRESHOLD_DIST; } + getSumDistance() { return this.sumDistance; } + getStart(key) { return this.start[key]; } + getEnd(key) { return this.end[key]; } + getbSpline(key) { return this.bSpline[key]; } + getNextPos(key) { return this.addToSelection.nextPos[key]; } + getControllPoint1(key) { return this.controllPoint1[key]; } + getControllPoint2(key) { return this.controllPoint2[key]; } + getFreehand(key) { return this.freehand[key]; } + getDrawing() { return this.getCurrentDrawing(); } + getDAttr() { return this.dAttr; } + getLastGoodImgUrl() { return this.lastGoodImgUrl; } + getCurText(key) { return this.curText[key]; } + setDAttr(value) { this.dAttr = value; } + setEnd(key, value) { this.end[key] = value; } + setControllPoint1(key, value) { this.controllPoint1[key] = value; } + setControllPoint2(key, value) { this.controllPoint2[key] = value; } + setJustSelected(value) { this.justSelected = value; } + setParameter(value) { this.parameter = value; } + setStart(value) { this.start = value; } + setRStartX(value) { this.rStartX = value; } + setRStartY(value) { this.rStartY = value; } + setSumDistance(value) { this.sumDistance = value; } + setbSpline(value) { this.bSpline = value; } + setNextPos(value) { this.nextPos = value; } + setNextParameter(value) { this.nextParameter = value; } + setCurProperties(key, value) { this.curProperties[key] = value; } + setCurText(key, value) { this.curText[key] = value; } + setFreehand(key, value) { this.freehand[key] = value; } + setCurBBoxes(value) { this.curBBoxes = value; } + setInitBbox(value) { this.initBbox = value; } + setRootSctm(value) { this.rootSctm = value; } + setCurrentResizeMode(value) { this.currentResizeMode = value; } + setLastClickPoint(value) { this.lastClickPoint = value; } + getId() { + return this.getCurrentDrawing().getId(); + } + getUIStrings() { return this.uiStrings; } + getNsMap() { return this.nsMap; } + getSvgOptionApply() { return this.saveOptions.apply; } + getSvgOptionImages() { return this.saveOptions.images; } + getEncodableImages(key) { return this.encodableImages[key]; } + setEncodableImages(key, value) { this.encodableImages[key] = value; } + getVisElems() { return visElems; } + getIdPrefix() { return this.idprefix; } + getDataStorage() { return this.dataStorage; } + setZoom(value) { this.zoom = value; } + getImportIds(key) { return this.importIds[key]; } + setImportIds(key, value) { this.importIds[key] = value; } + setRemovedElements(key, value) { this.removedElements[key] = value; } + setSvgContent(value) { this.svgContent = value; } + getrefAttrs() { return refAttrs; } + getcanvg() { return canvg; } + setCanvas(key, value) { this[key] = value; } + getCurProperties(key) { return this.curProperties[key]; } + setCurShape(key, value) { this.curShape[key] = value; } + gettingSelectorManager() { return this.selectorManager; } + getContentW() { return this.contentW; } + getContentH() { return this.contentH; } + getClipboardID() { return CLIPBOARD_ID; } + getSvgContent() { return this.svgContent; } + getExtensions() { return this.extensions; } + getSelector() { return Selector; } + + /** + * @function module:svgcanvas.SvgCanvas#getMode + * @returns {string} The current editor mode string + */ + getMode() { + return this.currentMode; + } + getNextId() { + return this.getCurrentDrawing().getNextId(); + } + /** +* Sets the editor's mode to the given string. +* @function module:svgcanvas.SvgCanvas#setMode +* @param {string} name - String with the new mode to change to +* @returns {void} +*/ + setMode(name) { + this.pathActions.clear(true); + this.textActions.clear(); + this.curProperties = (this.selectedElements[0] && this.selectedElements[0].nodeName === 'text') ? this.curText : this.curShape; + this.currentMode = name; + } + /** +* Clears the current document. This is not an undoable action. +* @function module:svgcanvas.SvgCanvas#clear +* @fires module:svgcanvas.SvgCanvas#event:cleared +* @returns {void} +*/ + clear() { + this.pathActions.clear(); + + this.clearSelection(); + + // clear the svgcontent node + this.clearSvgContentElement(); + + // create new document + this.current_drawing_ = new draw.Drawing(this.svgContent); + + // create empty first layer + this.createLayer('Layer 1'); + + // clear the undo stack + this.undoMgr.resetUndoStack(); + + // reset the selector manager + this.selectorManager.initGroup(); + + // reset the rubber band box + this.rubberBox = this.selectorManager.getRubberBandBox(); + + this.call('cleared'); + } + runExtension (name, action, vars) { + return this.runExtensions(action, vars, false, (n) => n === name); + } + async addExtension (name, extInitFunc, { importLocale }) { + if (typeof extInitFunc !== 'function') { + throw new TypeError('Function argument expected for `svgcanvas.addExtension`'); + } + if (name in this.extensions) { + throw new Error('Cannot add extension "' + name + '", an extension by that name already exists.'); + } + const argObj = this.mergeDeep(this.getPrivateMethods(), { + importLocale, + svgroot: this.svgroot, + svgContent: this.svgContent, + nonce: this.getCurrentDrawing().getNonce(), + selectorManager: this.selectorManager + }); + const extObj = await extInitFunc(argObj); + if (extObj) { + extObj.name = name; + } + this.extensions[name] = extObj; + return this.call('extension_added', extObj); + } + addCommandToHistory(cmd) { + this.undoMgr.addCommandToHistory(cmd); + } + restoreRefElements(elem) { + // Look for missing reference elements, restore any found + const attrs = {}; + refAttrs.forEach(function (item, _) { + attrs[item] = elem.getAttribute(item); + }); + Object.values(attrs).forEach((val) => { + if (val && val.startsWith('url(')) { + const id = getUrlFromAttr(val).substr(1); + const ref = getElem(id); + if (!ref) { + findDefs().append(this.removedElements[id]); + delete this.removedElements[id]; + } + } + }); + const childs = elem.getElementsByTagName('*'); + + if (childs.length) { + for (let i = 0, l = childs.length; i < l; i++) { + this.restoreRefElements(childs[i]); + } + } + } } // End class // attach utilities function to the class that are used by SvgEdit so diff --git a/src/svgcanvas/text-actions.js b/src/svgcanvas/text-actions.js index 28fe2928..4849cb2f 100644 --- a/src/svgcanvas/text-actions.js +++ b/src/svgcanvas/text-actions.js @@ -17,15 +17,15 @@ import { supportsGoodTextCharPos } from '../common/browser.js'; -let textActionsContext_ = null; +let svgCanvas = null; /** * @function module:text-actions.init -* @param {module:text-actions.textActionsContext_} textActionsContext +* @param {module:text-actions.svgCanvas} textActionsContext * @returns {void} */ -export const init = function (textActionsContext) { - textActionsContext_ = textActionsContext; +export const init = function (canvas) { + svgCanvas = canvas; }; /** @@ -159,7 +159,7 @@ export const textActionsMethod = (function () { */ function getIndexFromPoint (mouseX, mouseY) { // Position cursor here - const pt = textActionsContext_.getSVGRoot().createSVGPoint(); + const pt = svgCanvas.getSvgRoot().createSVGPoint(); pt.x = mouseX; pt.y = mouseY; @@ -221,9 +221,9 @@ export const textActionsMethod = (function () { x: xIn, y: yIn }; - const currentZoom = textActionsContext_.getCurrentZoom(); - out.x /= currentZoom; - out.y /= currentZoom; + const zoom = svgCanvas.getZoom(); + out.x /= zoom; + out.y /= zoom; if (matrix) { const pt = transformPoint(out.x, out.y, matrix.inverse()); @@ -251,9 +251,9 @@ export const textActionsMethod = (function () { out.x = pt.x; out.y = pt.y; } - const currentZoom = textActionsContext_.getCurrentZoom(); - out.x *= currentZoom; - out.y *= currentZoom; + const zoom = svgCanvas.getZoom(); + out.x *= zoom; + out.y *= zoom; return out; } @@ -275,10 +275,10 @@ export const textActionsMethod = (function () { */ function selectWord (evt) { if (!allowDbl || !curtext) { return; } - const currentZoom = textActionsContext_.getCurrentZoom(); - const ept = transformPoint(evt.pageX, evt.pageY, textActionsContext_.getrootSctm()); - const mouseX = ept.x * currentZoom; - const mouseY = ept.y * currentZoom; + const zoom = svgCanvas.getZoom(); + const ept = transformPoint(evt.pageX, evt.pageY, svgCanvas.getrootSctm()); + const mouseX = ept.x * zoom; + const mouseY = ept.y * zoom; const pt = screenToPt(mouseX, mouseY); const index = getIndexFromPoint(pt.x, pt.y); @@ -305,7 +305,7 @@ export const textActionsMethod = (function () { */ select (target, x, y) { curtext = target; - textActionsContext_.getCanvas().textActions.toEditMode(x, y); + svgCanvas.textActions.toEditMode(x, y); }, /** * @param {Element} elem @@ -313,7 +313,7 @@ export const textActionsMethod = (function () { */ start (elem) { curtext = elem; - textActionsContext_.getCanvas().textActions.toEditMode(); + svgCanvas.textActions.toEditMode(); }, /** * @param {external:MouseEvent} evt @@ -355,7 +355,7 @@ export const textActionsMethod = (function () { // TODO: Find a way to make this work: Use transformed BBox instead of evt.target // if (lastX === mouseX && lastY === mouseY // && !rectsIntersect(transbb, {x: pt.x, y: pt.y, width: 0, height: 0})) { - // textActionsContext_.getCanvas().textActions.toSelectMode(true); + // svgCanvas.textActions.toSelectMode(true); // } if ( @@ -365,7 +365,7 @@ export const textActionsMethod = (function () { mouseY < lastY + 2 && mouseY > lastY - 2 ) { - textActionsContext_.getCanvas().textActions.toSelectMode(true); + svgCanvas.textActions.toSelectMode(true); } }, /** @@ -381,13 +381,13 @@ export const textActionsMethod = (function () { */ toEditMode (x, y) { allowDbl = false; - textActionsContext_.setCurrentMode('textedit'); - textActionsContext_.getCanvas().selectorManager.requestSelector(curtext).showGrips(false); + svgCanvas.setCurrentMode('textedit'); + svgCanvas.selectorManager.requestSelector(curtext).showGrips(false); // Make selector group accept clicks - /* const selector = */ textActionsContext_.getCanvas().selectorManager.requestSelector(curtext); // Do we need this? Has side effect of setting lock, so keeping for now, but next line wasn't being used + /* const selector = */ svgCanvas.selectorManager.requestSelector(curtext); // Do we need this? Has side effect of setting lock, so keeping for now, but next line wasn't being used // const sel = selector.selectorRect; - textActionsContext_.getCanvas().textActions.init(); + svgCanvas.textActions.init(); curtext.style.cursor = 'text'; @@ -413,7 +413,7 @@ export const textActionsMethod = (function () { * @returns {void} */ toSelectMode (selectElem) { - textActionsContext_.setCurrentMode('select'); + svgCanvas.setCurrentMode('select'); clearInterval(blinker); blinker = null; if (selblock) { selblock.setAttribute('display', 'none'); } @@ -421,15 +421,15 @@ export const textActionsMethod = (function () { curtext.style.cursor = 'move'; if (selectElem) { - textActionsContext_.getCanvas().clearSelection(); + svgCanvas.clearSelection(); curtext.style.cursor = 'move'; - textActionsContext_.call('selected', [ curtext ]); - textActionsContext_.getCanvas().addToSelection([ curtext ], true); + svgCanvas.call('selected', [ curtext ]); + svgCanvas.addToSelection([ curtext ], true); } if (curtext && !curtext.textContent.length) { // No content, so delete - textActionsContext_.getCanvas().deleteSelectedElements(); + svgCanvas.deleteSelectedElements(); } textinput.blur(); @@ -451,8 +451,8 @@ export const textActionsMethod = (function () { * @returns {void} */ clear () { - if (textActionsContext_.getCurrentMode() === 'textedit') { - textActionsContext_.getCanvas().textActions.toSelectMode(); + if (svgCanvas.getCurrentMode() === 'textedit') { + svgCanvas.textActions.toSelectMode(); } }, /** @@ -469,9 +469,9 @@ export const textActionsMethod = (function () { if (!curtext.parentNode) { // Result of the ffClone, need to get correct element - const selectedElements = textActionsContext_.getSelectedElements(); + const selectedElements = svgCanvas.getSelectedElements(); curtext = selectedElements[0]; - textActionsContext_.getCanvas().selectorManager.requestSelector(curtext).showGrips(false); + svgCanvas.selectorManager.requestSelector(curtext).showGrips(false); } const str = curtext.textContent; @@ -499,13 +499,13 @@ export const textActionsMethod = (function () { end = curtext.getEndPositionOfChar(i); if (!supportsGoodTextCharPos()) { - const currentZoom = textActionsContext_.getCurrentZoom(); - const offset = textActionsContext_.getCanvas().contentW * currentZoom; + const zoom = svgCanvas.getZoom(); + const offset = svgCanvas.contentW * zoom; start.x -= offset; end.x -= offset; - start.x /= currentZoom; - end.x /= currentZoom; + start.x /= zoom; + end.x /= zoom; } // Get a "bbox" equivalent for each character. Uses the diff --git a/src/svgcanvas/undo.js b/src/svgcanvas/undo.js index 0ee7fb7a..7796bcbe 100644 --- a/src/svgcanvas/undo.js +++ b/src/svgcanvas/undo.js @@ -20,15 +20,15 @@ const { UndoManager, HistoryEventTypes } = hstry; -let undoContext_ = null; +let svgCanvas = null; /** * @function module:undo.init * @param {module:undo.undoContext} undoContext * @returns {void} */ -export const init = function (undoContext) { - undoContext_ = undoContext; +export const init = function (canvas) { + svgCanvas = canvas; }; export const getUndoManager = function () { @@ -43,43 +43,43 @@ export const getUndoManager = function () { const EventTypes = HistoryEventTypes; // TODO: handle setBlurOffsets. if (eventType === EventTypes.BEFORE_UNAPPLY || eventType === EventTypes.BEFORE_APPLY) { - undoContext_.getCanvas().clearSelection(); + svgCanvas.clearSelection(); } else if (eventType === EventTypes.AFTER_APPLY || eventType === EventTypes.AFTER_UNAPPLY) { const elems = cmd.elements(); - undoContext_.getCanvas().pathActions.clear(); - undoContext_.call('changed', elems); + svgCanvas.pathActions.clear(); + svgCanvas.call('changed', elems); const cmdType = cmd.type(); const isApply = (eventType === EventTypes.AFTER_APPLY); if (cmdType === 'MoveElementCommand') { const parent = isApply ? cmd.newParent : cmd.oldParent; - if (parent === undoContext_.getSVGContent()) { + if (parent === svgCanvas.getSvgContent()) { draw.identifyLayers(); } } else if (cmdType === 'InsertElementCommand' || cmdType === 'RemoveElementCommand') { - if (cmd.parent === undoContext_.getSVGContent()) { + if (cmd.parent === svgCanvas.getSvgContent()) { draw.identifyLayers(); } if (cmdType === 'InsertElementCommand') { if (isApply) { - undoContext_.restoreRefElems(cmd.elem); + svgCanvas.restoreRefElements(cmd.elem); } } else if (!isApply) { - undoContext_.restoreRefElems(cmd.elem); + svgCanvas.restoreRefElements(cmd.elem); } if (cmd.elem && cmd.elem.tagName === 'use') { - undoContext_.getCanvas().setUseData(cmd.elem); + svgCanvas.setUseData(cmd.elem); } } else if (cmdType === 'ChangeElementCommand') { // if we are changing layer names, re-identify all layers if (cmd.elem.tagName === 'title' && - cmd.elem.parentNode.parentNode === undoContext_.getSVGContent() + cmd.elem.parentNode.parentNode === svgCanvas.getSvgContent() ) { draw.identifyLayers(); } const values = isApply ? cmd.newValues : cmd.oldValues; // If stdDeviation was changed, update the blur. if (values.stdDeviation) { - undoContext_.getCanvas().setBlurOffsets(cmd.elem.parentNode, values.stdDeviation); + svgCanvas.setBlurOffsets(cmd.elem.parentNode, values.stdDeviation); } if (cmd.elem.tagName === 'text'){ const [ dx, dy ] = [ cmd.newValues.x - cmd.oldValues.x, @@ -120,9 +120,9 @@ export const ffClone = function (elem) { const clone = elem.cloneNode(true); elem.before(clone); elem.remove(); - undoContext_.getCanvas().selectorManager.releaseSelector(elem); - undoContext_.getCanvas().setSelectedElements(0, clone); - undoContext_.getCanvas().selectorManager.requestSelector(clone).showGrips(true); + svgCanvas.selectorManager.releaseSelector(elem); + svgCanvas.setSelectedElements(0, clone); + svgCanvas.selectorManager.requestSelector(clone).showGrips(true); return clone; }; @@ -135,11 +135,11 @@ export const ffClone = function (elem) { * @returns {void} */ export const changeSelectedAttributeNoUndoMethod = function (attr, newValue, elems) { - const selectedElements = undoContext_.getSelectedElements(); - const currentZoom = undoContext_.getCurrentZoom(); - if (undoContext_.getCurrentMode() === 'pathedit') { + const selectedElements = svgCanvas.getSelectedElements(); + const zoom = svgCanvas.getZoom(); + if (svgCanvas.getCurrentMode() === 'pathedit') { // Editing node - undoContext_.getCanvas().pathActions.moveNode(attr, newValue); + svgCanvas.pathActions.moveNode(attr, newValue); } elems = elems || selectedElements; let i = elems.length; @@ -155,7 +155,7 @@ export const changeSelectedAttributeNoUndoMethod = function (attr, newValue, ele const bbox = getStrokedBBoxDefaultVisible([ elem ]); const diffX = attr === 'x' ? newValue - bbox.x : 0; const diffY = attr === 'y' ? newValue - bbox.y : 0; - undoContext_.getCanvas().moveSelectedElements(diffX * currentZoom, diffY * currentZoom, true); + svgCanvas.moveSelectedElements(diffX * zoom, diffY * zoom, true); continue; } @@ -201,8 +201,8 @@ export const changeSelectedAttributeNoUndoMethod = function (attr, newValue, ele // NOTE: Important that this happens AFTER elem.setAttribute() or else attributes like // font-size can get reset to their old value, ultimately by svgEditor.updateContextPanel(), // after calling textActions.toSelectMode() below - if (undoContext_.getCurrentMode() === 'textedit' && attr !== '#text' && elem.textContent.length) { - undoContext_.getCanvas().textActions.toSelectMode(elem); + if (svgCanvas.getCurrentMode() === 'textedit' && attr !== '#text' && elem.textContent.length) { + svgCanvas.textActions.toSelectMode(elem); } // if (i === 0) { @@ -226,7 +226,7 @@ export const changeSelectedAttributeNoUndoMethod = function (attr, newValue, ele // Due to element replacement, this element may no longer // be part of the DOM if (!elem.parentNode) { return; } - undoContext_.getCanvas().selectorManager.requestSelector(elem).resize(); + svgCanvas.selectorManager.requestSelector(elem).resize(); }, 0); } // if this element was rotated, and we changed the position of this element @@ -247,7 +247,7 @@ export const changeSelectedAttributeNoUndoMethod = function (attr, newValue, ele ); const cx = center.x; const cy = center.y; - const newrot = undoContext_.getSVGRoot().createSVGTransform(); + const newrot = svgCanvas.getSvgRoot().createSVGTransform(); newrot.setRotate(angle, cx, cy); tlist.insertItemBefore(newrot, n); break; @@ -270,16 +270,16 @@ export const changeSelectedAttributeNoUndoMethod = function (attr, newValue, ele * @returns {void} */ export const changeSelectedAttributeMethod = function (attr, val, elems) { - const selectedElements = undoContext_.getSelectedElements(); + const selectedElements = svgCanvas.getSelectedElements(); elems = elems || selectedElements; - undoContext_.getCanvas().undoMgr.beginUndoableChange(attr, elems); + svgCanvas.undoMgr.beginUndoableChange(attr, elems); // const i = elems.length; changeSelectedAttributeNoUndoMethod(attr, val, elems); - const batchCmd = undoContext_.getCanvas().undoMgr.finishUndoableChange(); + const batchCmd = svgCanvas.undoMgr.finishUndoableChange(); if (!batchCmd.isEmpty()) { - // undoContext_.addCommandToHistory(batchCmd); - undoContext_.getCanvas().undoMgr.addCommandToHistory(batchCmd); + // svgCanvas.addCommandToHistory(batchCmd); + svgCanvas.undoMgr.addCommandToHistory(batchCmd); } }; diff --git a/src/svgcanvas/utilities.js b/src/svgcanvas/utilities.js index 45993d8e..d09fde1d 100644 --- a/src/svgcanvas/utilities.js +++ b/src/svgcanvas/utilities.js @@ -18,7 +18,7 @@ const visElems = 'a,circle,ellipse,foreignObject,g,image,line,path,polygon,polyl const visElemsArr = visElems.split(','); // const hidElems = 'defs,desc,feGaussianBlur,filter,linearGradient,marker,mask,metadata,pattern,radialGradient,stop,switch,symbol,title,textPath'; -let editorContext_ = null; +let svgCanvas = null; let svgroot_ = null; /** @@ -26,7 +26,7 @@ let svgroot_ = null; * @typedef {PlainObject} module:utilities.SVGElementJSON * @property {string} element - Tag name of the SVG element to create * @property {PlainObject} attr - Has key-value attributes to assign to the new element. -* An `id` should be set so that {@link module:utilities.EditorContext#addSVGElementFromJson} can later re-identify the element for modification or replacement. +* An `id` should be set so that {@link module:utilities.EditorContext#addSVGElemensFromJson} can later re-identify the element for modification or replacement. * @property {boolean} [curStyles=false] - Indicates whether current style attributes should be applied first * @property {module:utilities.SVGElementJSON[]} [children] - Data objects to be added recursively as children * @property {string} [namespace="http://www.w3.org/2000/svg"] - Indicate a (non-SVG) namespace @@ -39,14 +39,14 @@ let svgroot_ = null; * @property {module:path.pathActions} pathActions */ /** - * @function module:utilities.EditorContext#getSVGContent + * @function module:utilities.EditorContext#getSvgContent * @returns {SVGSVGElement} */ /** * Create a new SVG element based on the given object keys/values and add it * to the current layer. * The element will be run through `cleanupElement` before being returned. - * @function module:utilities.EditorContext#addSVGElementFromJson + * @function module:utilities.EditorContext#addSVGElemensFromJson * @param {module:utilities.SVGElementJSON} data * @returns {Element} The new element */ @@ -63,7 +63,7 @@ let svgroot_ = null; * @returns {HTMLElement} */ /** - * @function module:utilities.EditorContext#getSVGRoot + * @function module:utilities.EditorContext#getSvgRoot * @returns {SVGSVGElement} */ /** @@ -77,12 +77,12 @@ let svgroot_ = null; /** * @function module:utilities.init -* @param {module:utilities.EditorContext} editorContext +* @param {module:utilities.EditorContext} canvas * @returns {void} */ -export const init = function (editorContext) { - editorContext_ = editorContext; - svgroot_ = editorContext.getSVGRoot(); +export const init = function (canvas) { + svgCanvas = canvas; + svgroot_ = canvas.getSvgRoot(); }; /** @@ -366,7 +366,7 @@ export let setHref = function (elem, val) { * @returns {SVGDefsElement} The document's `` element, creating it first if necessary */ export const findDefs = function () { - const svgElement = editorContext_.getSVGContent(); + const svgElement = svgCanvas.getSvgContent(); let defs = svgElement.getElementsByTagNameNS(NS.SVG, 'defs'); if (defs.length > 0) { defs = defs[0]; @@ -472,7 +472,7 @@ export const getPathBBox = function (path) { * @returns {module:utilities.BBoxObject} Bounding box object */ export const getBBox = function (elem) { - const selected = elem || editorContext_.getSelectedElements()[0]; + const selected = elem || svgCanvas.getSelectedElements()[0]; if (elem.nodeType !== 1) { return null; } const elname = selected.nodeName; @@ -667,12 +667,12 @@ export const getExtraAttributesForConvertToPath = function (elem) { * Get the BBox of an element-as-path. * @function module:utilities.getBBoxOfElementAsPath * @param {Element} elem - The DOM element to be probed -* @param {module:utilities.EditorContext#addSVGElementFromJson} addSVGElementFromJson - Function to add the path element to the current layer. See canvas.addSVGElementFromJson +* @param {module:utilities.EditorContext#addSVGElemensFromJson} addSVGElemensFromJson - Function to add the path element to the current layer. See canvas.addSVGElemensFromJson * @param {module:path.pathActions} pathActions - If a transform exists, `pathActions.resetOrientation()` is used. See: canvas.pathActions. * @returns {DOMRect|false} The resulting path's bounding box object. */ -export const getBBoxOfElementAsPath = function (elem, addSVGElementFromJson, pathActions) { - const path = addSVGElementFromJson({ +export const getBBoxOfElementAsPath = function (elem, addSVGElemensFromJson, pathActions) { + const path = addSVGElemensFromJson({ element: 'path', attr: getExtraAttributesForConvertToPath(elem) }); @@ -713,7 +713,7 @@ export const getBBoxOfElementAsPath = function (elem, addSVGElementFromJson, pat * @function module:utilities.convertToPath * @param {Element} elem - The DOM element to be converted * @param {module:utilities.SVGElementJSON} attrs - Apply attributes to new path. see canvas.convertToPath -* @param {module:utilities.EditorContext#addSVGElementFromJson} addSVGElementFromJson - Function to add the path element to the current layer. See canvas.addSVGElementFromJson +* @param {module:utilities.EditorContext#addSVGElemensFromJson} addSVGElemensFromJson - Function to add the path element to the current layer. See canvas.addSVGElemensFromJson * @param {module:path.pathActions} pathActions - If a transform exists, pathActions.resetOrientation() is used. See: canvas.pathActions. * @param {module:draw.DrawCanvasInit#clearSelection|module:path.EditorContext#clearSelection} clearSelection - see [canvas.clearSelection]{@link module:svgcanvas.SvgCanvas#clearSelection} * @param {module:path.EditorContext#addToSelection} addToSelection - see [canvas.addToSelection]{@link module:svgcanvas.SvgCanvas#addToSelection} @@ -722,7 +722,7 @@ export const getBBoxOfElementAsPath = function (elem, addSVGElementFromJson, pat * @returns {SVGPathElement|null} The converted path element or null if the DOM element was not recognized. */ export const convertToPath = function ( - elem, attrs, addSVGElementFromJson, pathActions, + elem, attrs, addSVGElemensFromJson, pathActions, clearSelection, addToSelection, hstry, addCommandToHistory ) { const batchCmd = new hstry.BatchCommand('Convert element to Path'); @@ -730,7 +730,7 @@ export const convertToPath = function ( // Any attribute on the element not covered by the passed-in attributes attrs = mergeDeep(attrs, getExtraAttributesForConvertToPath(elem)); - const path = addSVGElementFromJson({ + const path = addSVGElemensFromJson({ element: 'path', attr: attrs }); @@ -812,11 +812,11 @@ function bBoxCanBeOptimizedOverNativeGetBBox(angle, hasAMatrixTransform) { * Get bounding box that includes any transforms. * @function module:utilities.getBBoxWithTransform * @param {Element} elem - The DOM element to be converted -* @param {module:utilities.EditorContext#addSVGElementFromJson} addSVGElementFromJson - Function to add the path element to the current layer. See canvas.addSVGElementFromJson +* @param {module:utilities.EditorContext#addSVGElemensFromJson} addSVGElemensFromJson - Function to add the path element to the current layer. See canvas.addSVGElemensFromJson * @param {module:path.pathActions} pathActions - If a transform exists, pathActions.resetOrientation() is used. See: canvas.pathActions. * @returns {module:utilities.BBoxObject|module:math.TransformedBox|DOMRect} A single bounding box object */ -export const getBBoxWithTransform = function (elem, addSVGElementFromJson, pathActions) { +export const getBBoxWithTransform = function (elem, addSVGElemensFromJson, pathActions) { // TODO: Fix issue with rotated groups. Currently they work // fine in FF, but not in other browsers (same problem mentioned // in Issue 339 comment #2). @@ -838,14 +838,14 @@ export const getBBoxWithTransform = function (elem, addSVGElementFromJson, pathA // TODO: why ellipse and not circle const elemNames = [ 'ellipse', 'path', 'line', 'polyline', 'polygon' ]; if (elemNames.includes(elem.tagName)) { - goodBb = getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions); + goodBb = getBBoxOfElementAsPath(elem, addSVGElemensFromJson, pathActions); bb = goodBb; } else if (elem.tagName === 'rect') { // Look for radius const rx = Number(elem.getAttribute('rx')); const ry = Number(elem.getAttribute('ry')); if (rx || ry) { - goodBb = getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions); + goodBb = getBBoxOfElementAsPath(elem, addSVGElemensFromJson, pathActions); bb = goodBb; } } @@ -882,18 +882,18 @@ function getStrokeOffsetForBBox(elem) { * Get the bounding box for one or more stroked and/or transformed elements. * @function module:utilities.getStrokedBBox * @param {Element[]} elems - Array with DOM elements to check -* @param {module:utilities.EditorContext#addSVGElementFromJson} addSVGElementFromJson - Function to add the path element to the current layer. See canvas.addSVGElementFromJson +* @param {module:utilities.EditorContext#addSVGElemensFromJson} addSVGElemensFromJson - Function to add the path element to the current layer. See canvas.addSVGElemensFromJson * @param {module:path.pathActions} pathActions - If a transform exists, pathActions.resetOrientation() is used. See: canvas.pathActions. * @returns {module:utilities.BBoxObject|module:math.TransformedBox|DOMRect} A single bounding box object */ -export const getStrokedBBox = function (elems, addSVGElementFromJson, pathActions) { +export const getStrokedBBox = function (elems, addSVGElemensFromJson, pathActions) { if (!elems || !elems.length) { return false; } let fullBb; elems.forEach(function(elem){ if (fullBb) { return; } if (!elem.parentNode) { return; } - fullBb = getBBoxWithTransform(elem, addSVGElementFromJson, pathActions); + fullBb = getBBoxWithTransform(elem, addSVGElemensFromJson, pathActions); }); // This shouldn't ever happen... @@ -916,7 +916,7 @@ export const getStrokedBBox = function (elems, addSVGElementFromJson, pathAction maxY += offset; } else { elems.forEach(function(elem){ - const curBb = getBBoxWithTransform(elem, addSVGElementFromJson, pathActions); + const curBb = getBBoxWithTransform(elem, addSVGElemensFromJson, pathActions); if (curBb) { const offset = getStrokeOffsetForBBox(elem); minX = Math.min(minX, curBb.x - offset); @@ -947,8 +947,8 @@ export const getStrokedBBox = function (elems, addSVGElementFromJson, pathAction */ export const getVisibleElements = function (parentElement) { if (!parentElement) { - const svgcontent = editorContext_.getSVGContent(); - parentElement = svgcontent.children[0]; // Prevent layers from being included + const svgContent = svgCanvas.getSvgContent(); + parentElement = svgContent.children[0]; // Prevent layers from being included } const contentElems = []; @@ -971,8 +971,8 @@ export const getStrokedBBoxDefaultVisible = function (elems) { if (!elems) { elems = getVisibleElements(); } return getStrokedBBox( elems, - editorContext_.addSVGElementFromJson, - editorContext_.pathActions + svgCanvas.addSVGElemensFromJson, + svgCanvas.pathActions ); }; @@ -1002,7 +1002,7 @@ export const getRotationAngleFromTransformList = (tlist, toRad) => { * @returns {Float} The angle in degrees or radians */ export let getRotationAngle = function (elem, toRad) { - const selected = elem || editorContext_.getSelectedElements()[0]; + const selected = elem || svgCanvas.getSelectedElements()[0]; // find the rotation transform (if any) and set it const tlist = selected.transform?.baseVal; return getRotationAngleFromTransformList(tlist, toRad); @@ -1122,8 +1122,8 @@ export const cleanupElement = function (element) { * @returns {Integer} */ export const snapToGrid = function (value) { - const unit = editorContext_.getBaseUnit(); - let stepSize = editorContext_.getSnappingStep(); + const unit = svgCanvas.getBaseUnit(); + let stepSize = svgCanvas.getSnappingStep(); if (unit !== 'px') { stepSize *= getTypeMap()[unit]; }