From e986c8ea310b4728bb7e3854bc50fc1b15f7f49e Mon Sep 17 00:00:00 2001 From: Junsik Shim Date: Sat, 24 Sep 2022 10:58:41 +0900 Subject: [PATCH 1/3] Fixes null checks in SvgCanvas2D #107 --- packages/core/src/view/canvas/SvgCanvas2D.ts | 75 +++++++------------- 1 file changed, 26 insertions(+), 49 deletions(-) diff --git a/packages/core/src/view/canvas/SvgCanvas2D.ts b/packages/core/src/view/canvas/SvgCanvas2D.ts index c4a6e64838..65f3d4ac43 100644 --- a/packages/core/src/view/canvas/SvgCanvas2D.ts +++ b/packages/core/src/view/canvas/SvgCanvas2D.ts @@ -562,13 +562,11 @@ class SvgCanvas2D extends AbstractCanvas2D { alpha2: number, direction: DirectionValue ) { - if (!this.root) return; - const id = this.createGradientId(start, end, alpha1, alpha2, direction); let gradient: Gradient | null = this.gradients[id]; if (!gradient) { - const svg = this.root.ownerSVGElement; + const svg = this.root!.ownerSVGElement; let counter = 0; let tmpId = `${id}-${counter}`; @@ -649,8 +647,6 @@ class SvgCanvas2D extends AbstractCanvas2D { * Private helper function to create SVG elements */ addNode(filled: boolean, stroked: boolean) { - if (!this.root) return; - const { node } = this; const s = this.state; @@ -689,12 +685,12 @@ class SvgCanvas2D extends AbstractCanvas2D { } if (s.shadow) { - this.root.appendChild(this.createShadow(node)); + this.root!.appendChild(this.createShadow(node)); } // Adds stroke tolerance if (this.strokeTolerance > 0 && !filled) { - this.root.appendChild(this.createTolerance(node)); + this.root!.appendChild(this.createTolerance(node)); } // Adds pointer events @@ -717,7 +713,7 @@ class SvgCanvas2D extends AbstractCanvas2D { node.getAttribute('pointer-events') !== NONE ) { // LATER: Update existing DOM for performance - this.root.appendChild(node); + this.root!.appendChild(node); } this.node = null; @@ -728,12 +724,10 @@ class SvgCanvas2D extends AbstractCanvas2D { * Transfers the stroke attributes from to . */ updateFill() { - if (!this.node) return; - const s = this.state; if (s.alpha < 1 || s.fillAlpha < 1) { - this.node.setAttribute('fill-opacity', String(s.alpha * s.fillAlpha)); + this.node!.setAttribute('fill-opacity', String(s.alpha * s.fillAlpha)); } if (s.fillColor !== NONE) { @@ -749,12 +743,12 @@ class SvgCanvas2D extends AbstractCanvas2D { if (this.root?.ownerDocument === document && useAbsoluteIds) { // Workaround for no fill with base tag in page (escape brackets) const base = this.getBaseUrl().replace(/([\(\)])/g, '\\$1'); - this.node.setAttribute('fill', `url(${base}#${id})`); + this.node!.setAttribute('fill', `url(${base}#${id})`); } else { - this.node.setAttribute('fill', `url(#${id})`); + this.node!.setAttribute('fill', `url(#${id})`); } } else { - this.node.setAttribute('fill', s.fillColor.toLowerCase()); + this.node!.setAttribute('fill', s.fillColor.toLowerCase()); } } } @@ -774,29 +768,27 @@ class SvgCanvas2D extends AbstractCanvas2D { * Transfers the stroke attributes from {@link mxAbstractCanvas2D.state} to {@link node}. */ updateStroke() { - if (!this.node) return; - const s = this.state; if (s.strokeColor && s.strokeColor !== NONE) { - this.node.setAttribute('stroke', s.strokeColor.toLowerCase()); + this.node!.setAttribute('stroke', s.strokeColor.toLowerCase()); } if (s.alpha < 1 || s.strokeAlpha < 1) { - this.node.setAttribute('stroke-opacity', String(s.alpha * s.strokeAlpha)); + this.node!.setAttribute('stroke-opacity', String(s.alpha * s.strokeAlpha)); } const sw = this.getCurrentStrokeWidth(); if (sw !== 1) { - this.node.setAttribute('stroke-width', String(sw)); + this.node!.setAttribute('stroke-width', String(sw)); } - if (this.node.nodeName === 'path') { + if (this.node!.nodeName === 'path') { this.updateStrokeAttributes(); } if (s.dashed) { - this.node.setAttribute( + this.node!.setAttribute( 'stroke-dasharray', this.createDashPattern((s.fixDash ? 1 : s.strokeWidth) * s.scale) ); @@ -807,13 +799,11 @@ class SvgCanvas2D extends AbstractCanvas2D { * Transfers the stroke attributes from {@link mxAbstractCanvas2D.state} to {@link node}. */ updateStrokeAttributes() { - if (!this.node) return; - const s = this.state; // Linejoin miter is default in SVG if (s.lineJoin && s.lineJoin !== 'miter') { - this.node.setAttribute('stroke-linejoin', s.lineJoin); + this.node!.setAttribute('stroke-linejoin', s.lineJoin); } if (s.lineCap) { @@ -826,13 +816,13 @@ class SvgCanvas2D extends AbstractCanvas2D { // Linecap butt is default in SVG if (value !== 'butt') { - this.node.setAttribute('stroke-linecap', value); + this.node!.setAttribute('stroke-linecap', value); } } // Miterlimit 10 is default in our document if (s.miterLimit != null && (!this.styleEnabled || s.miterLimit !== 10)) { - this.node.setAttribute('stroke-miterlimit', String(s.miterLimit)); + this.node!.setAttribute('stroke-miterlimit', String(s.miterLimit)); } } @@ -909,8 +899,6 @@ class SvgCanvas2D extends AbstractCanvas2D { * Experimental implementation for hyperlinks. */ setLink(link: string) { - if (!this.root) return; - if (!link) { this.root = this.originalRoot; } else { @@ -920,13 +908,13 @@ class SvgCanvas2D extends AbstractCanvas2D { // Workaround for implicit namespace handling in HTML5 export, IE adds NS1 namespace so use code below // in all IE versions except quirks mode. KNOWN: Adds xlink namespace to each image tag in output. - if (node.setAttributeNS == null || this.root.ownerDocument !== document) { + if (node.setAttributeNS == null || this.root!.ownerDocument !== document) { node.setAttribute('xlink:href', link); } else { node.setAttributeNS(NS_XLINK, 'xlink:href', link); } - this.root.appendChild(node); + this.root!.appendChild(node); this.root = node; } } @@ -1005,16 +993,14 @@ class SvgCanvas2D extends AbstractCanvas2D { * Private helper function to create SVG elements */ roundrect(x: number, y: number, w: number, h: number, dx: number, dy: number) { - if (!this.node) return; - this.rect(x, y, w, h); if (dx > 0) { - this.node.setAttribute('rx', String(this.format(dx * this.state.scale))); + this.node!.setAttribute('rx', String(this.format(dx * this.state.scale))); } if (dy > 0) { - this.node.setAttribute('ry', String(this.format(dy * this.state.scale))); + this.node!.setAttribute('ry', String(this.format(dy * this.state.scale))); } } @@ -1045,8 +1031,6 @@ class SvgCanvas2D extends AbstractCanvas2D { flipH = false, flipV = false ) { - if (!this.root) return; - src = this.converter.convert(src); const s = this.state; @@ -1104,7 +1088,7 @@ class SvgCanvas2D extends AbstractCanvas2D { node.setAttribute('pointer-events', 'none'); } - this.root.appendChild(node); + this.root!.appendChild(node); } /** @@ -1134,8 +1118,6 @@ class SvgCanvas2D extends AbstractCanvas2D { * Note: signature changed in mxgraph 4.1.0 */ createDiv(str: string | HTMLElement) { - if (!this.root) return; - let val = str; if (!isNode(val)) { @@ -1152,7 +1134,7 @@ class SvgCanvas2D extends AbstractCanvas2D { const div3 = div2.cloneNode(false); // Creates a copy for export - if (this.root.ownerDocument !== document) { + if (this.root!.ownerDocument !== document) { div2.appendChild(n.cloneNode(true)); } else { div2.appendChild(n); @@ -1390,7 +1372,6 @@ class SvgCanvas2D extends AbstractCanvas2D { /** * Private helper function to create SVG elements */ - // getTextCss(): string; getTextCss() { const s = this.state; const lh = ABSOLUTE_LINE_HEIGHT @@ -1450,8 +1431,6 @@ class SvgCanvas2D extends AbstractCanvas2D { rotation = 0, dir: TextDirectionValue ) { - if (!this.root) return; - if (this.textEnabled && str != null) { rotation = rotation != null ? rotation : 0; @@ -1479,7 +1458,7 @@ class SvgCanvas2D extends AbstractCanvas2D { rotation, dir, div, - this.root + this.root! ); } } else { @@ -1552,8 +1531,6 @@ class SvgCanvas2D extends AbstractCanvas2D { rotation = 0, dir: TextDirectionValue ) { - if (!this.root) return; - const s = this.state; const size = s.fontSize; const node = this.createElement('g'); @@ -1604,13 +1581,13 @@ class SvgCanvas2D extends AbstractCanvas2D { this.defs.appendChild(c); } else { // Makes sure clip is removed with referencing node - this.root.appendChild(c); + this.root!.appendChild(c); } if ( !Client.IS_CHROMEAPP && !Client.IS_EDGE && - this.root.ownerDocument === document + this.root!.ownerDocument === document ) { // Workaround for potential base tag const base = this.getBaseUrl().replace(/([\(\)])/g, '\\$1'); @@ -1684,7 +1661,7 @@ class SvgCanvas2D extends AbstractCanvas2D { cy += lh; } - this.root.appendChild(node); + this.root!.appendChild(node); this.addTextBackground( node, str, From 8c29223b98d2094a6be8e99d34b05dfa63bba148 Mon Sep 17 00:00:00 2001 From: Thomas Bouffard <27200110+tbouffard@users.noreply.github.com> Date: Sat, 24 Sep 2022 11:10:04 +0200 Subject: [PATCH 2/3] Remove remaining commented method signatures including types (dated from the JS to TS migration) --- packages/core/src/view/canvas/SvgCanvas2D.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/core/src/view/canvas/SvgCanvas2D.ts b/packages/core/src/view/canvas/SvgCanvas2D.ts index 65f3d4ac43..06cbec5c4c 100644 --- a/packages/core/src/view/canvas/SvgCanvas2D.ts +++ b/packages/core/src/view/canvas/SvgCanvas2D.ts @@ -508,7 +508,6 @@ class SvgCanvas2D extends AbstractCanvas2D { /** * Private helper function to create SVG elements */ - // createGradientId(start: string, end: string, alpha1: string, alpha2: string, direction: string): string; createGradientId( start: string, end: string, @@ -756,7 +755,6 @@ class SvgCanvas2D extends AbstractCanvas2D { /** * Returns the current stroke width (>= 1), ie. max(1, this.format(this.state.strokeWidth * this.state.scale)). */ - // getCurrentStrokeWidth(): number; getCurrentStrokeWidth() { return Math.max( this.minStrokeWidth, @@ -848,7 +846,6 @@ class SvgCanvas2D extends AbstractCanvas2D { /** * Creates a hit detection tolerance shape for the given node. */ - // createTolerance(node: Element): Element; createTolerance(node: SVGElement) { const tol = node.cloneNode(true) as SVGElement; const sw = parseFloat(tol.getAttribute('stroke-width') || '1') + this.strokeTolerance; @@ -969,7 +966,6 @@ class SvgCanvas2D extends AbstractCanvas2D { /** * Extends superclass to create path. */ - // begin(): void; begin() { super.begin(); this.node = this.createElement('path'); @@ -1076,7 +1072,7 @@ class SvgCanvas2D extends AbstractCanvas2D { dy = -h - 2 * y; } - // Adds image tansformation to existing transform + // Adds image transformation to existing transform tr += `scale(${sx},${sy})translate(${dx * s.scale},${dy * s.scale})`; } From b7cfeebd23ebc0c93f70e4ed1235734866cbcec7 Mon Sep 17 00:00:00 2001 From: Thomas Bouffard <27200110+tbouffard@users.noreply.github.com> Date: Sat, 24 Sep 2022 11:16:26 +0200 Subject: [PATCH 3/3] ts-example: restore the rounded shape in the custom rectangle --- packages/ts-example/README.md | 9 ++++++++- packages/ts-example/src/custom-shapes.ts | 3 +-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/ts-example/README.md b/packages/ts-example/README.md index dcbdb3fbf4..1623a973ba 100644 --- a/packages/ts-example/README.md +++ b/packages/ts-example/README.md @@ -2,8 +2,15 @@ Initialized from https://github.com/vitejs/vite/tree/v2.9.8/packages/create-vite/template-vanilla-ts -Do not forget to initialize all packages (you may also need to build the maxgraph@core package) +## Setup + +Initialize all packages > From the repository root, run `npm install`. + +Build maxgraph@core +> From the `packages/core` directory, run `npm run generate-esm`. + +## Run Run `npm run dev` and go to http://localhost:5173/ diff --git a/packages/ts-example/src/custom-shapes.ts b/packages/ts-example/src/custom-shapes.ts index 690aa039e7..fefc8a7c5e 100644 --- a/packages/ts-example/src/custom-shapes.ts +++ b/packages/ts-example/src/custom-shapes.ts @@ -29,8 +29,7 @@ class CustomRectangleShape extends RectangleShape { constructor(bounds: Rectangle, fill: ColorValue, stroke: ColorValue) { super(bounds, fill, stroke, 3); - // TODO if set, the shape is not painted - // this.isRounded = true; // force rounded shape + this.isRounded = true; // force rounded shape } paintBackground(c: AbstractCanvas2D, x: number, y: number, w: number, h: number): void {