From 829764e4599c9e0189b9a620e428a49043e30ffd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Frischeisen-K=C3=B6hler?= Date: Fri, 12 Apr 2024 14:30:48 +0200 Subject: [PATCH 1/3] REA-340: Fix concurrent layouts applying obsolete node sizes --- src/core/LayoutSupport.ts | 74 ++++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 24 deletions(-) diff --git a/src/core/LayoutSupport.ts b/src/core/LayoutSupport.ts index 535eebe..d54807d 100644 --- a/src/core/LayoutSupport.ts +++ b/src/core/LayoutSupport.ts @@ -16,7 +16,8 @@ import { PartitionCellId, PartitionGrid, PartitionGridData, - PolylineEdgeStyle + PolylineEdgeStyle, + Rect } from 'yfiles' import { GridPositioningFunction, @@ -37,7 +38,8 @@ export class LayoutSupport { this.workerPromise = null } } - private executor: LayoutExecutorAsync | null = null + private executorAsync: LayoutExecutorAsync | null = null + private executor: LayoutExecutor | null = null private hiddenEdgeStyle = new PolylineEdgeStyle({ stroke: 'transparent' }) private hiddenLabelStyle = new DefaultLabelStyle({ @@ -182,28 +184,53 @@ export class LayoutSupport { } } - private createLayoutExecutor( + /** + * When a layout animation is already running, it might have started + * with now obsolete node sizes - stop the running animation and restore + * the latest measured node sizes. + */ + private async maybeCancel() { + const syncRunning = this.executor && this.executor.running + const asyncRunning = this.executorAsync && this.executorAsync.running + if (syncRunning || asyncRunning) { + const layouts = new Map() + for (const node of this.graphComponent.graph.nodes) { + layouts.set(node, node.layout.toRect()) + } + await this.executor?.stop() + await this.executorAsync?.cancel() + for (const node of this.graphComponent.graph.nodes) { + if (layouts.has(node)) { + this.graphComponent.graph.setNodeLayout(node, layouts.get(node)!) + } + } + } + } + + private async createLayoutExecutor( incremental: boolean, incrementalNodes: INode[], fixedNode: INode | null = null, fitViewport: boolean ): Promise { - return Promise.resolve( - new LayoutExecutor({ - graphComponent: this.graphComponent, - layout: createLayout(incremental, this.layoutOptions), - layoutData: this.createLayoutData( - this.graphComponent.graph, - incremental, - incrementalNodes, - fixedNode - ), - duration: '300ms', - animateViewport: fitViewport, - updateContentRect: true, - targetBoundsInsets: defaultGraphFitInsets - }) - ) + await this.maybeCancel() + + this.executor = new LayoutExecutor({ + graphComponent: this.graphComponent, + layout: createLayout(incremental, this.layoutOptions), + layoutData: this.createLayoutData( + this.graphComponent.graph, + incremental, + incrementalNodes, + fixedNode + ), + duration: '300ms', + animateViewport: fitViewport, + updateContentRect: true, + targetBoundsInsets: defaultGraphFitInsets + }) + + return Promise.resolve(this.executor) } private async createLayoutExecutorAsync( @@ -212,9 +239,8 @@ export class LayoutSupport { fixedNode: INode | null = null, fitViewport: boolean ): Promise { - if (this.executor) { - await this.executor.cancel() - } + await this.maybeCancel() + const worker = await this.workerPromise! // helper function that performs the actual message passing to the web worker @@ -239,7 +265,7 @@ export class LayoutSupport { }) } - this.executor = new LayoutExecutorAsync({ + this.executorAsync = new LayoutExecutorAsync({ messageHandler: webWorkerMessageHandler, graphComponent: this.graphComponent, layoutData: this.createLayoutData( @@ -253,6 +279,6 @@ export class LayoutSupport { updateContentRect: true, targetBoundsInsets: defaultGraphFitInsets }) - return this.executor + return this.executorAsync } } From 2127c620193aebac695ae23d25b8acea722f1d10 Mon Sep 17 00:00:00 2001 From: Sebastian Niedworok Date: Fri, 12 Apr 2024 17:19:45 +0200 Subject: [PATCH 2/3] REA-340: Update demo for measured node sizes. --- .../src/examples/custom-item-style/index.css | 9 ++++++--- .../src/examples/custom-item-style/index.tsx | 16 +++++++++++----- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/examples/src/examples/custom-item-style/index.css b/examples/src/examples/custom-item-style/index.css index b58e580..914998f 100644 --- a/examples/src/examples/custom-item-style/index.css +++ b/examples/src/examples/custom-item-style/index.css @@ -1,6 +1,7 @@ .item-name { margin-top: 10px; margin-left: 20px; + margin-right: 20px; font-family: Arial, Helvetica, sans-serif; font-size: 20px; font-weight: bold; @@ -9,17 +10,19 @@ .item-price { margin-top: 10px; margin-left: 20px; + margin-right: 20px; font-family: Arial, Helvetica, sans-serif; font-size: 16px; } .item-summary { - display: grid; + display: flex; + justify-content: center; align-items: center; + text-align: center; height: 100%; - margin-left: 20px; font-family: Arial, Helvetica, sans-serif; - font-size: 42px; + font-size: 30px; font-weight: bold; } diff --git a/examples/src/examples/custom-item-style/index.tsx b/examples/src/examples/custom-item-style/index.tsx index 4ec6540..3a86067 100644 --- a/examples/src/examples/custom-item-style/index.tsx +++ b/examples/src/examples/custom-item-style/index.tsx @@ -8,13 +8,13 @@ import { import './index.css' -type MetalItem = UserSupplyChainItem & { price: string } +type MetalItem = UserSupplyChainItem & { name: string; price: string } const data = { items: [ - { name: 'Copper', id: 1, price: 'USD 8500/t', className: 'copper', width: 180, height: 70 }, - { name: 'Zinc', id: 2, price: 'USD 2500/t', className: 'zinc', width: 180, height: 70 }, - { name: 'Brass', id: 3, price: 'USD 6500/t', className: 'brass', width: 180, height: 70 } + { name: 'Copper', id: 1, price: 'USD 8500/t', className: 'copper' }, + { name: 'Zinc', id: 2, price: 'USD 2500/t', className: 'zinc' }, + { name: 'Brass', id: 3, price: 'USD 6500/t', className: 'brass' } ], connections: [ { sourceId: 1, targetId: 3 }, @@ -22,6 +22,12 @@ const data = { ] } satisfies SupplyChainData +const abbreviations = new Map([ + ['Copper', 'Cu'], + ['Zinc', 'Zn'], + ['Brass', 'Brass'] +]) + export function CustomSupplyChainItem({ dataItem, detail, @@ -53,7 +59,7 @@ export function CustomSupplyChainItem({
{customSupplyChainItem.price}
) : ( -
{customSupplyChainItem.name}
+
{abbreviations.get(customSupplyChainItem.name)}
)} ) From 48c995130d9cf2c4d2bdf869c5e6a45be09612ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Frischeisen-K=C3=B6hler?= Date: Mon, 15 Apr 2024 11:34:41 +0200 Subject: [PATCH 3/3] Update package.json: 1.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f4b79c2..64357dd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@yworks/react-yfiles-supply-chain", - "version": "1.0.0", + "version": "1.0.1", "author": { "name": "yFiles for HTML team @ yWorks GmbH", "email": "yfileshtml@yworks.com"