@@ -16,7 +16,8 @@ import {
1616 PartitionCellId ,
1717 PartitionGrid ,
1818 PartitionGridData ,
19- PolylineEdgeStyle
19+ PolylineEdgeStyle ,
20+ Rect
2021} from 'yfiles'
2122import {
2223 GridPositioningFunction ,
@@ -37,7 +38,8 @@ export class LayoutSupport<TSupplyChainItem extends SupplyChainItem> {
3738 this . workerPromise = null
3839 }
3940 }
40- private executor : LayoutExecutorAsync | null = null
41+ private executorAsync : LayoutExecutorAsync | null = null
42+ private executor : LayoutExecutor | null = null
4143
4244 private hiddenEdgeStyle = new PolylineEdgeStyle ( { stroke : 'transparent' } )
4345 private hiddenLabelStyle = new DefaultLabelStyle ( {
@@ -182,28 +184,53 @@ export class LayoutSupport<TSupplyChainItem extends SupplyChainItem> {
182184 }
183185 }
184186
185- private createLayoutExecutor (
187+ /**
188+ * When a layout animation is already running, it might have started
189+ * with now obsolete node sizes - stop the running animation and restore
190+ * the latest measured node sizes.
191+ */
192+ private async maybeCancel ( ) {
193+ const syncRunning = this . executor && this . executor . running
194+ const asyncRunning = this . executorAsync && this . executorAsync . running
195+ if ( syncRunning || asyncRunning ) {
196+ const layouts = new Map < INode , Rect > ( )
197+ for ( const node of this . graphComponent . graph . nodes ) {
198+ layouts . set ( node , node . layout . toRect ( ) )
199+ }
200+ await this . executor ?. stop ( )
201+ await this . executorAsync ?. cancel ( )
202+ for ( const node of this . graphComponent . graph . nodes ) {
203+ if ( layouts . has ( node ) ) {
204+ this . graphComponent . graph . setNodeLayout ( node , layouts . get ( node ) ! )
205+ }
206+ }
207+ }
208+ }
209+
210+ private async createLayoutExecutor (
186211 incremental : boolean ,
187212 incrementalNodes : INode [ ] ,
188213 fixedNode : INode | null = null ,
189214 fitViewport : boolean
190215 ) : Promise < LayoutExecutor > {
191- return Promise . resolve (
192- new LayoutExecutor ( {
193- graphComponent : this . graphComponent ,
194- layout : createLayout ( incremental , this . layoutOptions ) ,
195- layoutData : this . createLayoutData (
196- this . graphComponent . graph ,
197- incremental ,
198- incrementalNodes ,
199- fixedNode
200- ) ,
201- duration : '300ms' ,
202- animateViewport : fitViewport ,
203- updateContentRect : true ,
204- targetBoundsInsets : defaultGraphFitInsets
205- } )
206- )
216+ await this . maybeCancel ( )
217+
218+ this . executor = new LayoutExecutor ( {
219+ graphComponent : this . graphComponent ,
220+ layout : createLayout ( incremental , this . layoutOptions ) ,
221+ layoutData : this . createLayoutData (
222+ this . graphComponent . graph ,
223+ incremental ,
224+ incrementalNodes ,
225+ fixedNode
226+ ) ,
227+ duration : '300ms' ,
228+ animateViewport : fitViewport ,
229+ updateContentRect : true ,
230+ targetBoundsInsets : defaultGraphFitInsets
231+ } )
232+
233+ return Promise . resolve ( this . executor )
207234 }
208235
209236 private async createLayoutExecutorAsync (
@@ -212,9 +239,8 @@ export class LayoutSupport<TSupplyChainItem extends SupplyChainItem> {
212239 fixedNode : INode | null = null ,
213240 fitViewport : boolean
214241 ) : Promise < LayoutExecutorAsync > {
215- if ( this . executor ) {
216- await this . executor . cancel ( )
217- }
242+ await this . maybeCancel ( )
243+
218244 const worker = await this . workerPromise !
219245
220246 // helper function that performs the actual message passing to the web worker
@@ -239,7 +265,7 @@ export class LayoutSupport<TSupplyChainItem extends SupplyChainItem> {
239265 } )
240266 }
241267
242- this . executor = new LayoutExecutorAsync ( {
268+ this . executorAsync = new LayoutExecutorAsync ( {
243269 messageHandler : webWorkerMessageHandler ,
244270 graphComponent : this . graphComponent ,
245271 layoutData : this . createLayoutData (
@@ -253,6 +279,6 @@ export class LayoutSupport<TSupplyChainItem extends SupplyChainItem> {
253279 updateContentRect : true ,
254280 targetBoundsInsets : defaultGraphFitInsets
255281 } )
256- return this . executor
282+ return this . executorAsync
257283 }
258284}
0 commit comments