Skip to content

Commit d275640

Browse files
committed
[6342] Remove bending points and custom handles after arrangeAll
Bug: #6342 Signed-off-by: Florian ROUËNÉ <florian.rouene@obeosoft.com>
1 parent 0d70fbd commit d275640

File tree

4 files changed

+74
-44
lines changed

4 files changed

+74
-44
lines changed

CHANGELOG.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
=== Bug fixes
3131

3232
- https://github.com/eclipse-sirius/sirius-web/issues/5436[#5436] [diagram] Prevent custom handles from being lost after importing a project with a diagram representation.
33+
- https://github.com/eclipse-sirius/sirius-web/issues/6342[#6342] [diagram] Remove bending points and custom handles after an `arrangeAll`
3334

3435

3536
=== New Features

integration-tests-playwright/playwright/e2e/diagrams/arrange-all.spec.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
* Obeo - initial API and implementation
1212
*******************************************************************************/
1313
import { expect, test } from '@playwright/test';
14+
import { PlaywrightEdge } from '../../helpers/PlaywrightEdge';
1415
import { PlaywrightExplorer } from '../../helpers/PlaywrightExplorer';
1516
import { PlaywrightNode } from '../../helpers/PlaywrightNode';
1617
import { PlaywrightProject } from '../../helpers/PlaywrightProject';
@@ -117,3 +118,44 @@ test.describe('diagram - arrange all', () => {
117118
await expect(page.locator('#notistack-snackbar')).not.toBeAttached({ timeout: 2000 }); // no error
118119
});
119120
});
121+
122+
test.describe('diagram - arrange all', () => {
123+
let projectId;
124+
test.beforeEach(async ({ page, request }) => {
125+
await new PlaywrightProject(request).uploadProject(page, 'projectEdgeWithBendingPointsAndCustomHandles.zip');
126+
const playwrightExplorer = new PlaywrightExplorer(page);
127+
await playwrightExplorer.expand('Flow');
128+
await playwrightExplorer.expand('NewSystem');
129+
const url = page.url();
130+
const parts = url.split('/');
131+
const projectsIndex = parts.indexOf('projects');
132+
projectId = parts[projectsIndex + 1];
133+
});
134+
135+
test.afterEach(async ({ request }) => {
136+
await new PlaywrightProject(request).deleteProject(projectId);
137+
});
138+
139+
test('when a edge has some bending points and custom handles, then after triggering an arrangeAll they are reset', async ({
140+
page,
141+
}) => {
142+
const playwrightExplorer = new PlaywrightExplorer(page);
143+
await playwrightExplorer.select('Topography');
144+
await expect(page.getByTestId('rf__wrapper')).toBeAttached();
145+
146+
const playwrightEdge = new PlaywrightEdge(page);
147+
148+
await playwrightEdge.openPalette();
149+
await expect(page.getByTestId('Reset handles positions - Tool')).toBeAttached();
150+
await expect(page.getByTestId('Reset bending points - Tool')).toBeAttached();
151+
await playwrightEdge.closePalette();
152+
153+
await page.getByTestId('arrange-all-menu').click();
154+
await page.getByTestId('arrange-all-elk-layered').click();
155+
156+
await playwrightEdge.openPalette();
157+
await expect(page.getByTestId('Reset handles positions - Tool')).not.toBeAttached();
158+
await expect(page.getByTestId('Reset bending points - Tool')).not.toBeAttached();
159+
await playwrightEdge.closePalette();
160+
});
161+
});

packages/diagrams/frontend/sirius-components-diagrams/src/renderer/layout/arrange-all/useArrangeAll.ts

Lines changed: 31 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,10 @@
1010
* Contributors:
1111
* Obeo - initial API and implementation
1212
*******************************************************************************/
13-
import { Edge, Node, useReactFlow } from '@xyflow/react';
13+
import { Edge, Node, useReactFlow, useUpdateNodeInternals } from '@xyflow/react';
1414
import { LayoutOptions } from 'elkjs/lib/elk-api';
1515
import { EdgeData, NodeData } from '../../DiagramRenderer.types';
1616
import { useFitView } from '../../fit-to-screen/useFitView';
17-
import { DiagramNodeType } from '../../node/NodeTypes.types';
18-
import { useOverlap } from '../../overlap/useOverlap';
1917
import { useElkLayout } from '../elk/useElkLayout';
2018
import { RawDiagram } from '../layout.types';
2119
import { useLayout } from '../useLayout';
@@ -26,60 +24,49 @@ export const useArrangeAll = (): UseArrangeAllValue => {
2624
const { getNodes, getEdges, setNodes, setEdges } = useReactFlow<Node<NodeData>, Edge<EdgeData>>();
2725
const { layout } = useLayout();
2826
const { synchronizeLayoutData } = useSynchronizeLayoutData();
29-
const { resolveNodeOverlap } = useOverlap();
27+
const updateNodeInternals = useUpdateNodeInternals();
3028
const { fitView } = useFitView();
3129
const { elkLayout } = useElkLayout();
3230

3331
const arrangeAll = async (layoutOptions: LayoutOptions): Promise<void> => {
3432
await elkLayout(getNodes(), getEdges(), layoutOptions).then(
3533
async (laidOutNodesWithElk: Node<NodeData, string>[]) => {
36-
const laidOutMovedNodeIds = laidOutNodesWithElk
37-
.filter((node) => !node.data.isBorderNode && !node.data.pinned)
38-
.map((node) => node.id);
39-
const edges = getEdges();
40-
edges
41-
.filter((edge) => laidOutMovedNodeIds.includes(edge.source) || laidOutMovedNodeIds.includes(edge.target))
42-
.forEach((edge: Edge<EdgeData, string>) => {
43-
if (edge.data?.bendingPoints) {
44-
edge.data.bendingPoints = null;
45-
}
34+
//Removed bending point
35+
const edges = getEdges().map((edge: Edge<EdgeData, string>) => {
36+
if (edge.data?.bendingPoints) {
37+
edge.data.bendingPoints = null;
38+
}
39+
return edge;
40+
});
41+
//Removed custom handles for edges
42+
const laidOutNodesWithElkWithoutCustomHandles = laidOutNodesWithElk.map((node) => {
43+
const handles = node.data.connectionHandles.map((handle) => {
44+
return {
45+
...handle,
46+
XYPosition: null,
47+
};
4648
});
4749

50+
return {
51+
...node,
52+
data: {
53+
...node.data,
54+
connectionHandles: handles,
55+
},
56+
};
57+
});
58+
4859
const diagramToLayout: RawDiagram = {
49-
nodes: laidOutNodesWithElk,
50-
edges: edges,
60+
nodes: laidOutNodesWithElkWithoutCustomHandles,
61+
edges,
5162
};
5263
const layoutPromise = new Promise<void>((resolve) => {
5364
layout(diagramToLayout, diagramToLayout, null, 'UNDEFINED', (laidOutDiagram) => {
54-
const overlapFreeLaidOutNodes: Node<NodeData, string>[] = resolveNodeOverlap(
55-
laidOutDiagram.nodes.filter((n) => !n.data.isBorderNode),
56-
'horizontal'
57-
) as Node<NodeData, DiagramNodeType>[];
58-
laidOutNodesWithElk.map((node) => {
59-
const existingNode = overlapFreeLaidOutNodes.find((laidOutNode) => laidOutNode.id === node.id);
60-
if (existingNode) {
61-
return {
62-
...node,
63-
position: existingNode.position,
64-
width: existingNode.width,
65-
height: existingNode.height,
66-
style: {
67-
...node.style,
68-
width: `${existingNode.width}px`,
69-
height: `${existingNode.height}px`,
70-
},
71-
};
72-
}
73-
return node;
74-
});
75-
setNodes(laidOutNodesWithElk);
65+
setNodes(laidOutDiagram.nodes);
7666
setEdges(laidOutDiagram.edges);
77-
const finalDiagram: RawDiagram = {
78-
nodes: laidOutNodesWithElk,
79-
edges: laidOutDiagram.edges,
80-
};
81-
fitView({ duration: 200, nodes: laidOutNodesWithElk });
82-
synchronizeLayoutData(crypto.randomUUID(), 'layout', finalDiagram);
67+
fitView({ duration: 200, nodes: laidOutDiagram.nodes });
68+
updateNodeInternals(laidOutDiagram.nodes.map((node) => node.id));
69+
synchronizeLayoutData(crypto.randomUUID(), 'layout', laidOutDiagram);
8370
resolve();
8471
});
8572
});

0 commit comments

Comments
 (0)