Skip to content

Commit 5e27388

Browse files
Merge pull request #82 from jeff-phillips-18/layout-end-event
fix(event): Fix firing of GRAPH_LAYOUT_END_EVENT
2 parents d63d21c + de5f843 commit 5e27388

9 files changed

Lines changed: 56 additions & 14 deletions

File tree

packages/demo-app-ts/src/demos/TopologyPackage.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,15 @@ import * as React from 'react';
22
import { action } from 'mobx';
33
import * as _ from 'lodash';
44
import {
5+
Controller,
56
createTopologyControlButtons,
67
defaultControlButtonsOptions,
78
EdgeModel,
89
EventListener,
910
GRAPH_POSITION_CHANGE_EVENT,
11+
GRAPH_LAYOUT_END_EVENT,
12+
isNode,
13+
Node,
1014
NodeModel,
1115
SELECTION_EVENT,
1216
SelectionEventListener,
@@ -67,6 +71,14 @@ const graphPositionChangeListener: EventListener = ({ graph }): void => {
6771
}, 1000);
6872
};
6973

74+
const layoutEndListener: EventListener = ({ graph }): void => {
75+
const controller: Controller = graph.getController();
76+
const positions = controller.getElements().filter(e => isNode(e)).map((node) => `Node: ${node.getLabel()}: ${Math.round((node as Node).getPosition().x)},${Math.round((node as Node).getPosition().y)}`);
77+
78+
// eslint-disable-next-line no-console
79+
console.log(`Layout Complete:\n${positions.join('\n')}`);
80+
};
81+
7082

7183
const TopologyViewComponent: React.FunctionComponent<TopologyViewComponentProps> = ({
7284
useSidebar,
@@ -118,9 +130,12 @@ const TopologyViewComponent: React.FunctionComponent<TopologyViewComponentProps>
118130
React.useEffect(() => {
119131

120132
controller.addEventListener(GRAPH_POSITION_CHANGE_EVENT, graphPositionChangeListener);
133+
controller.addEventListener(GRAPH_LAYOUT_END_EVENT, layoutEndListener);
134+
121135
return () => {
122136
controller.removeEventListener(GRAPH_POSITION_CHANGE_EVENT, graphPositionChangeListener);
123-
}
137+
controller.removeEventListener(GRAPH_LAYOUT_END_EVENT, layoutEndListener);
138+
};
124139
}, [controller]);
125140

126141
React.useEffect(() => {

packages/module/src/layouts/BaseLayout.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -477,10 +477,11 @@ export class BaseLayout implements Layout {
477477
// Reset the force simulation
478478
this.stopSimulation();
479479

480-
this.startLayout(this.graph, initialRun, addingNodes);
480+
this.startLayout(this.graph, initialRun, addingNodes, () => {
481+
this.graph.getController().fireEvent(GRAPH_LAYOUT_END_EVENT, { graph: this.graph });
482+
});
481483
} else if (restart && this.options.layoutOnDrag) {
482484
this.updateLayout();
483485
}
484-
this.graph.getController().fireEvent(GRAPH_LAYOUT_END_EVENT, { graph: this.graph });
485486
}
486487
}

packages/module/src/layouts/BreadthFirstLayout.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Edge, Graph, Layout, Node } from '../types';
1+
import { Edge, Graph, GRAPH_LAYOUT_END_EVENT, Layout, Node } from '../types';
22
import { BaseLayout } from './BaseLayout';
33
import { LayoutOptions } from './LayoutOptions';
44
import { LayoutNode } from './LayoutNode';
@@ -119,5 +119,6 @@ export class BreadthFirstLayout extends BaseLayout implements Layout {
119119
x = 0;
120120
}
121121
}
122+
this.graph.getController().fireEvent(GRAPH_LAYOUT_END_EVENT, { graph: this.graph });
122123
}
123124
}

packages/module/src/layouts/ColaGroupsLayout.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class ColaGroupsLayout extends ColaLayout implements Layout {
5252
this.simulationRunning = false;
5353
action(() => {
5454
if (this.destroyed) {
55-
this.onEnd && this.onEnd();
55+
this.handleLayoutEnd();
5656
return;
5757
}
5858
this.layoutNodes.forEach(d => {
@@ -68,15 +68,18 @@ class ColaGroupsLayout extends ColaLayout implements Layout {
6868
this.simulationStopped = false;
6969
if (this.restartOnEnd !== undefined) {
7070
this.startColaLayout(false, this.restartOnEnd);
71-
this.startLayout(graph, false, this.restartOnEnd, this.onEnd);
71+
this.startLayout(graph, false, this.restartOnEnd, this.handleLayoutEnd);
7272
delete this.restartOnEnd;
73+
} else {
74+
this.handleLayoutEnd();
7375
}
7476
} else if (this.addingNodes) {
7577
// One round of simulation to adjust for new nodes
7678
this.forceSimulation.useForceSimulation(this.nodes, this.edges, this.getFixedNodeDistance);
7779
this.forceSimulation.restart();
80+
} else {
81+
this.handleLayoutEnd();
7882
}
79-
this.onEnd && this.onEnd();
8083
})();
8184
});
8285
}
@@ -124,7 +127,7 @@ class ColaGroupsLayout extends ColaLayout implements Layout {
124127
edges: LayoutLink[],
125128
groups: LayoutGroup[]
126129
): BaseLayout {
127-
const layout = new ColaGroupsLayout(graph, { ...this.options, listenForChanges: false });
130+
const layout = new ColaGroupsLayout(graph, { ...this.options, onSimulationEnd: undefined, listenForChanges: false });
128131
layout.setupLayout(graph, nodes, edges, groups);
129132
return layout;
130133
}

packages/module/src/layouts/ColaLayout.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { LayoutNode } from './LayoutNode';
1010
import { ColaNode } from './ColaNode';
1111
import { ColaGroup } from './ColaGroup';
1212
import { ColaLink } from './ColaLink';
13+
import { ForceSimulation } from './ForceSimulation';
1314

1415
export interface ColaLayoutOptions {
1516
maxTicks: number;
@@ -52,6 +53,10 @@ class ColaLayout extends BaseLayout implements Layout {
5253
...COLA_LAYOUT_DEFAULTS,
5354
...options
5455
};
56+
this.forceSimulation = new ForceSimulation({
57+
...this.options,
58+
onSimulationEnd: options?.onSimulationEnd ?? this.onSimulationEnd
59+
});
5560
this.initializeLayout();
5661
}
5762

@@ -74,7 +79,7 @@ class ColaLayout extends BaseLayout implements Layout {
7479
this.simulationRunning = false;
7580
action(() => {
7681
if (this.destroyed) {
77-
this.onEnd && this.onEnd();
82+
this.handleLayoutEnd();
7883
return;
7984
}
8085
this.nodes.forEach(d => {
@@ -91,24 +96,36 @@ class ColaLayout extends BaseLayout implements Layout {
9196
if (this.restartOnEnd !== undefined) {
9297
this.startColaLayout(false, this.restartOnEnd);
9398
delete this.restartOnEnd;
99+
} else {
100+
this.handleLayoutEnd();
94101
}
95102
} else if (this.addingNodes) {
96103
// One round of simulation to adjust for new nodes
97104
this.forceSimulation.useForceSimulation(this.nodes, this.edges, this.getFixedNodeDistance);
98105
this.forceSimulation.restart();
106+
} else {
107+
this.handleLayoutEnd();
99108
}
100-
this.onEnd && this.onEnd();
101109
})();
102110
});
103111
}
104112

113+
protected handleLayoutEnd = () => {
114+
if (this.onEnd) {
115+
// Only call on end once, then clear it so that it doesn't get called again on simulations
116+
this.onEnd();
117+
this.onEnd = undefined;
118+
}
119+
}
120+
105121
protected onSimulationEnd = () => {
106122
if (this.addingNodes) {
107123
if (!this.options.layoutOnDrag) {
108124
this.forceSimulation.stopSimulation();
109125
}
110126
this.addingNodes = false;
111127
}
128+
this.handleLayoutEnd();
112129
};
113130

114131
destroy(): void {

packages/module/src/layouts/ConcentricLayout.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Edge, Graph, Layout, Node } from '../types';
1+
import { Edge, Graph, GRAPH_LAYOUT_END_EVENT, Layout, Node } from '../types';
22
import { BaseLayout } from './BaseLayout';
33
import { LayoutOptions } from './LayoutOptions';
44
import { LayoutNode } from './LayoutNode';
@@ -103,5 +103,6 @@ export class ConcentricLayout extends BaseLayout implements Layout {
103103
r += maxWH + padding;
104104
}
105105
}
106+
this.graph.getController().fireEvent(GRAPH_LAYOUT_END_EVENT, { graph: this.graph });
106107
}
107108
}

packages/module/src/layouts/DagreLayout.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as dagre from 'dagre';
22
import * as _ from 'lodash';
3-
import { Edge, Graph, Layout, Node } from '../types';
3+
import { Edge, Graph, GRAPH_LAYOUT_END_EVENT, Layout, Node } from '../types';
44
import { BaseLayout, LAYOUT_DEFAULTS } from './BaseLayout';
55
import { LayoutOptions } from './LayoutOptions';
66
import { LayoutLink } from './LayoutLink';
@@ -88,6 +88,8 @@ export class DagreLayout extends BaseLayout implements Layout {
8888

8989
if (this.dagreOptions.layoutOnDrag) {
9090
this.forceSimulation.useForceSimulation(this.nodes, this.edges, this.getFixedNodeDistance);
91+
} else {
92+
this.graph.getController().fireEvent(GRAPH_LAYOUT_END_EVENT, { graph: this.graph });
9193
}
9294
}
9395
}

packages/module/src/layouts/ForceLayout.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Graph, Layout } from '../types';
1+
import { Graph, GRAPH_LAYOUT_END_EVENT, Layout } from '../types';
22
import { getGroupPadding } from '../utils/element-utils';
33
import { ForceSimulationNode } from './ForceSimulation';
44
import { BaseLayout } from '.';
@@ -12,6 +12,7 @@ export class ForceLayout extends BaseLayout implements Layout {
1212
layoutOnDrag: true,
1313
onSimulationEnd: () => {
1414
this.nodes.forEach(n => n.setFixed(false));
15+
this.graph.getController().fireEvent(GRAPH_LAYOUT_END_EVENT, { graph: this.graph });
1516
}
1617
});
1718
}

packages/module/src/layouts/GridLayout.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Edge, Graph, Layout, Node } from '../types';
1+
import { Edge, Graph, GRAPH_LAYOUT_END_EVENT, Layout, Node } from '../types';
22
import { BaseLayout } from './BaseLayout';
33
import { LayoutOptions } from './LayoutOptions';
44
import { LayoutNode } from './LayoutNode';
@@ -67,5 +67,6 @@ export class GridLayout extends BaseLayout implements Layout {
6767
}
6868
}
6969
}
70+
this.graph.getController().fireEvent(GRAPH_LAYOUT_END_EVENT, { graph: this.graph });
7071
}
7172
}

0 commit comments

Comments
 (0)