From 76046248d2cdbef6915e78d0b09a7b8d8ce6c080 Mon Sep 17 00:00:00 2001 From: Guillaume Fontorbe Date: Mon, 29 Apr 2024 12:09:49 +0200 Subject: [PATCH 1/4] Fix Junction points post processor Signed-off-by: Guillaume Fontorbe --- .../src/features/edge-junction/di.config.ts | 1 + .../edge-junction/junction-postprocessor.ts | 15 +++++++++++---- packages/sprotty/src/index.ts | 1 + 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/sprotty/src/features/edge-junction/di.config.ts b/packages/sprotty/src/features/edge-junction/di.config.ts index 370ff64..bb14a3e 100644 --- a/packages/sprotty/src/features/edge-junction/di.config.ts +++ b/packages/sprotty/src/features/edge-junction/di.config.ts @@ -24,6 +24,7 @@ const edgeJunctionModule = new ContainerModule(bind => { bind(TYPES.IEdgeRoutePostprocessor).toService(JunctionFinder); bind(JunctionPostProcessor).toSelf().inSingletonScope(); bind(TYPES.IVNodePostprocessor).toService(JunctionPostProcessor); + bind(TYPES.HiddenVNodePostprocessor).toService(JunctionPostProcessor); }); export default edgeJunctionModule; diff --git a/packages/sprotty/src/features/edge-junction/junction-postprocessor.ts b/packages/sprotty/src/features/edge-junction/junction-postprocessor.ts index a15b2ae..eb2e8e6 100644 --- a/packages/sprotty/src/features/edge-junction/junction-postprocessor.ts +++ b/packages/sprotty/src/features/edge-junction/junction-postprocessor.ts @@ -17,7 +17,7 @@ import { injectable, inject } from "inversify"; import { IVNodePostprocessor } from "../../base/views/vnode-postprocessor"; import { VNode } from "snabbdom"; -import { Action } from "sprotty-protocol"; +import { Action, RequestBoundsAction } from "sprotty-protocol"; import { SModelElementImpl } from "../../base/model/smodel"; import { TYPES } from "../../base/types"; import { ViewerOptions } from "../../base/views/viewer-options"; @@ -34,10 +34,17 @@ export class JunctionPostProcessor implements IVNodePostprocessor { return vnode; } postUpdate(cause?: Action | undefined): void { - const baseDiv = this.viewerOptions.baseDiv; - const svg = document.querySelector(`#${baseDiv} > svg > g`); + let targetDiv: string = this.viewerOptions.baseDiv; + let junctionSelector = `#${targetDiv} > svg > g > g.sprotty-junction`; + + if (cause?.kind === RequestBoundsAction.KIND) { + targetDiv = this.viewerOptions.hiddenDiv; + junctionSelector = `#${targetDiv} > svg > g > g > g.sprotty-junction`; + } + + const svg = document.querySelector(`#${targetDiv} > svg > g`); if (svg) { - const junctionGroups = Array.from(document.querySelectorAll('g.sprotty-junction')); + const junctionGroups = Array.from(document.querySelectorAll(junctionSelector)); junctionGroups.forEach(junctionGroup => { junctionGroup.remove(); diff --git a/packages/sprotty/src/index.ts b/packages/sprotty/src/index.ts index 675a89c..89ac96e 100644 --- a/packages/sprotty/src/index.ts +++ b/packages/sprotty/src/index.ts @@ -113,6 +113,7 @@ export * from './features/edge-intersection/intersection-finder'; export * from './features/edge-intersection/sweepline'; export * from './features/edge-junction/junction-finder'; +export * from './features/edge-junction/junction-postprocessor'; export * from './features/move/model'; export * from './features/move/move'; From e059fc2e0e444ae31c032209c99921481cce3088 Mon Sep 17 00:00:00 2001 From: Guillaume Fontorbe Date: Mon, 29 Apr 2024 13:36:56 +0200 Subject: [PATCH 2/4] Fix selector Signed-off-by: Guillaume Fontorbe --- .../src/features/edge-junction/junction-postprocessor.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/sprotty/src/features/edge-junction/junction-postprocessor.ts b/packages/sprotty/src/features/edge-junction/junction-postprocessor.ts index eb2e8e6..620f8b5 100644 --- a/packages/sprotty/src/features/edge-junction/junction-postprocessor.ts +++ b/packages/sprotty/src/features/edge-junction/junction-postprocessor.ts @@ -35,13 +35,11 @@ export class JunctionPostProcessor implements IVNodePostprocessor { } postUpdate(cause?: Action | undefined): void { let targetDiv: string = this.viewerOptions.baseDiv; - let junctionSelector = `#${targetDiv} > svg > g > g.sprotty-junction`; - if (cause?.kind === RequestBoundsAction.KIND) { targetDiv = this.viewerOptions.hiddenDiv; - junctionSelector = `#${targetDiv} > svg > g > g > g.sprotty-junction`; } + const junctionSelector = `#${targetDiv} > svg > g > g > g.sprotty-junction`; const svg = document.querySelector(`#${targetDiv} > svg > g`); if (svg) { const junctionGroups = Array.from(document.querySelectorAll(junctionSelector)); From bcd169ba3e791c36047dfd8eb8e41c5e0cb728c3 Mon Sep 17 00:00:00 2001 From: Guillaume Fontorbe Date: Tue, 30 Apr 2024 11:31:27 +0200 Subject: [PATCH 3/4] Fix junction points not being removed when a new model is set Signed-off-by: Guillaume Fontorbe --- .../edge-junction/junction-postprocessor.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/sprotty/src/features/edge-junction/junction-postprocessor.ts b/packages/sprotty/src/features/edge-junction/junction-postprocessor.ts index 620f8b5..9947058 100644 --- a/packages/sprotty/src/features/edge-junction/junction-postprocessor.ts +++ b/packages/sprotty/src/features/edge-junction/junction-postprocessor.ts @@ -28,6 +28,8 @@ import { ViewerOptions } from "../../base/views/viewer-options"; */ @injectable() export class JunctionPostProcessor implements IVNodePostprocessor { + isFirstRender = true; + @inject(TYPES.ViewerOptions) private viewerOptions: ViewerOptions; decorate(vnode: VNode, element: SModelElementImpl): VNode { @@ -36,19 +38,28 @@ export class JunctionPostProcessor implements IVNodePostprocessor { postUpdate(cause?: Action | undefined): void { let targetDiv: string = this.viewerOptions.baseDiv; if (cause?.kind === RequestBoundsAction.KIND) { + this.isFirstRender = true; targetDiv = this.viewerOptions.hiddenDiv; } + // remove moved junction points only if it is the first render cycle + if (this.isFirstRender) { + const outsideJunctionPoints = document.querySelectorAll(`#${targetDiv} > svg > g > g.sprotty-junction`); + outsideJunctionPoints.forEach(e => e.remove()); + } + const junctionSelector = `#${targetDiv} > svg > g > g > g.sprotty-junction`; const svg = document.querySelector(`#${targetDiv} > svg > g`); if (svg) { + // find all nested junction points and move them down in the hierarchy so they are always rendered on top const junctionGroups = Array.from(document.querySelectorAll(junctionSelector)); - junctionGroups.forEach(junctionGroup => { junctionGroup.remove(); }); - svg.append(...junctionGroups); + + // if we are not rendering the hidden model, set the flag to false to prevent incorrect handling of junction points when updating/setting a new model + this.isFirstRender = targetDiv === this.viewerOptions.hiddenDiv; } } } From 15195a990160a5ae231ee7477a031c36752bbfb9 Mon Sep 17 00:00:00 2001 From: Guillaume Fontorbe Date: Tue, 30 Apr 2024 12:30:29 +0200 Subject: [PATCH 4/4] Fixed wrong behavior on update and set model Signed-off-by: Guillaume Fontorbe --- .../edge-junction/junction-postprocessor.ts | 56 +++++++++++++------ 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/packages/sprotty/src/features/edge-junction/junction-postprocessor.ts b/packages/sprotty/src/features/edge-junction/junction-postprocessor.ts index 9947058..b2ca306 100644 --- a/packages/sprotty/src/features/edge-junction/junction-postprocessor.ts +++ b/packages/sprotty/src/features/edge-junction/junction-postprocessor.ts @@ -14,13 +14,14 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ -import { injectable, inject } from "inversify"; -import { IVNodePostprocessor } from "../../base/views/vnode-postprocessor"; +import { inject, injectable } from "inversify"; import { VNode } from "snabbdom"; -import { Action, RequestBoundsAction } from "sprotty-protocol"; +import { Action, RequestBoundsAction, SModelRoot } from "sprotty-protocol"; import { SModelElementImpl } from "../../base/model/smodel"; import { TYPES } from "../../base/types"; import { ViewerOptions } from "../../base/views/viewer-options"; +import { IVNodePostprocessor } from "../../base/views/vnode-postprocessor"; +import { ModelSource } from "../../model-source/model-source"; /** * Finds all junction points in the first SVG group element (diagram root level) and moves them to the end of the SVG. @@ -28,38 +29,57 @@ import { ViewerOptions } from "../../base/views/viewer-options"; */ @injectable() export class JunctionPostProcessor implements IVNodePostprocessor { + currentModel: SModelRoot; isFirstRender = true; @inject(TYPES.ViewerOptions) private viewerOptions: ViewerOptions; + @inject(TYPES.ModelSource) private modelSource: ModelSource; decorate(vnode: VNode, element: SModelElementImpl): VNode { return vnode; } postUpdate(cause?: Action | undefined): void { - let targetDiv: string = this.viewerOptions.baseDiv; - if (cause?.kind === RequestBoundsAction.KIND) { + + // if the model has changed, we need to remove the junction points from the previous model + if (this.currentModel !== this.modelSource.model) { this.isFirstRender = true; - targetDiv = this.viewerOptions.hiddenDiv; } - // remove moved junction points only if it is the first render cycle - if (this.isFirstRender) { - const outsideJunctionPoints = document.querySelectorAll(`#${targetDiv} > svg > g > g.sprotty-junction`); - outsideJunctionPoints.forEach(e => e.remove()); + // if the cause of the update is a RequestBoundsAction (from the hidden model) + // and we are rendering the diagram for the first time (not from an update or setting the same model again) + // we need to remove the junction points from the previous model + if (cause?.kind === RequestBoundsAction.KIND && this.isFirstRender) { + const junctionPointsInHiddenDiv = document.querySelectorAll(`#${this.viewerOptions.hiddenDiv} > svg > g > g.sprotty-junction`); + junctionPointsInHiddenDiv.forEach(e => e.remove()); + + const junctionPointsInBaseDiv = document.querySelectorAll(`#${this.viewerOptions.baseDiv} > svg > g > g.sprotty-junction`); + junctionPointsInBaseDiv.forEach(e => e.remove()); } - const junctionSelector = `#${targetDiv} > svg > g > g > g.sprotty-junction`; - const svg = document.querySelector(`#${targetDiv} > svg > g`); - if (svg) { - // find all nested junction points and move them down in the hierarchy so they are always rendered on top - const junctionGroups = Array.from(document.querySelectorAll(junctionSelector)); + const hiddenSvg = document.querySelector(`#${this.viewerOptions.hiddenDiv} > svg > g`); + const baseSvg = document.querySelector(`#${this.viewerOptions.baseDiv} > svg > g`); + + // move junction points to the end of the SVG in the hidden div + if (hiddenSvg) { + const junctionGroups = Array.from(document.querySelectorAll(`#${this.viewerOptions.hiddenDiv} > svg > g > g > g.sprotty-junction`)); junctionGroups.forEach(junctionGroup => { junctionGroup.remove(); }); - svg.append(...junctionGroups); + hiddenSvg.append(...junctionGroups); + } - // if we are not rendering the hidden model, set the flag to false to prevent incorrect handling of junction points when updating/setting a new model - this.isFirstRender = targetDiv === this.viewerOptions.hiddenDiv; + // move junction points to the end of the SVG in the base div + if (baseSvg) { + const junctionGroups = Array.from(document.querySelectorAll(`#${this.viewerOptions.baseDiv} > svg > g > g > g.sprotty-junction`)); + junctionGroups.forEach(junctionGroup => { + junctionGroup.remove(); + }); + baseSvg.append(...junctionGroups); } + + // update the current model + this.currentModel = this.modelSource.model; + // after the first render, we don't need to remove the junction points anymore + this.isFirstRender = false; } }