Skip to content

Commit 654e88f

Browse files
committed
[6118] Support auto_until_change layout option
Bug: #6118 Signed-off-by: Florian ROUËNÉ <florian.rouene@obeosoft.com>
1 parent b46b683 commit 654e88f

File tree

114 files changed

+954
-350
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

114 files changed

+954
-350
lines changed

CHANGELOG.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ A key binding needs to contain at least one of `Control`, `Alt`, or `Meta` to be
116116
- https://github.com/eclipse-sirius/sirius-web/issues/5982[#5982] [tree] Add the ability to trigger context menu entries using key bindings.
117117
As for diagram tools, it is now possible to add `KeyBinding` instances to context menu entries in trees.
118118
Note that for the moment, only entries that aren't overridden in the frontend can be triggered with key bindings, although it is possible to define key bindings for any entry.
119+
- https://github.com/eclipse-sirius/sirius-web/issues/6118[#6118] [diagram] Add support for auto layout until change
119120

120121

121122
=== Improvements

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,20 @@ test.describe('diagram - arrange all', () => {
3535

3636
test('when a arrange all is triggered, then a fit to screen is applied', async ({ page }) => {
3737
await expect(page.getByTestId('rf__wrapper')).toBeAttached();
38-
await expect(page.getByTestId('FreeForm - Wifi')).toBeInViewport();
38+
const wifiNode = new PlaywrightNode(page, 'Wifi');
39+
await expect(wifiNode.nodeLocator).toBeInViewport();
3940
//move view port to hide some nodes
4041
await page.getByTestId('rf__wrapper').hover({ position: { x: 10, y: 10 } });
4142
await page.mouse.down();
4243
await page.mouse.move(10, 10, { steps: 2 });
4344
await page.mouse.up();
4445

45-
await expect(page.getByTestId('FreeForm - Wifi')).not.toBeInViewport();
46+
await expect(wifiNode.nodeLocator).not.toBeInViewport();
4647

4748
await page.getByTestId('arrange-all-menu').click();
4849
await page.getByTestId('arrange-all-elk-layered').click();
4950

50-
await expect(page.getByTestId('FreeForm - Wifi')).toBeInViewport();
51+
await expect(wifiNode.nodeLocator).toBeInViewport();
5152
});
5253
});
5354

integration-tests-playwright/playwright/e2e/diagrams/auto-layout.spec.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,40 @@ test.describe('diagram - auto-layout', () => {
8282
);
8383
});
8484
});
85+
86+
test.describe('diagram - auto-until-manual', () => {
87+
let projectId;
88+
test.beforeEach(async ({ page, request }) => {
89+
const project = await new PlaywrightProject(request).createProject('Studio', 'studio-template');
90+
projectId = project.projectId;
91+
92+
await page.goto(`/projects/${projectId}/edit/`);
93+
});
94+
95+
test.afterEach(async ({ request }) => {
96+
await new PlaywrightProject(request).deleteProject(projectId);
97+
});
98+
99+
test('when a diagram with auto-until-manual is opened, then all nodes are positioned according to the elk layout', async ({
100+
page,
101+
}) => {
102+
await expect(page.getByTestId('rf__wrapper')).toBeAttached();
103+
104+
const node = new PlaywrightNode(page, 'Entity1', 'List');
105+
const position = await node.getReactFlowXYPosition();
106+
expect(position.x).toBe(12);
107+
expect(position.y).toBe(242);
108+
});
109+
110+
test('when moving a node on an auto-until-manual diagram, then move is not reset', async ({ page }) => {
111+
await expect(page.getByTestId('rf__wrapper')).toBeAttached();
112+
113+
const rootNode = new PlaywrightNode(page, 'Entity1', 'List');
114+
const rootPositionBefore = await rootNode.getDOMXYPosition();
115+
await rootNode.move({ x: 100, y: 100 });
116+
117+
const rootPositionAfter = await rootNode.getDOMXYPosition();
118+
expect(rootPositionAfter.x).not.toBe(rootPositionBefore.x);
119+
expect(rootPositionAfter.y).not.toBe(rootPositionBefore.y);
120+
});
121+
});

integration-tests-playwright/playwright/e2e/diagrams/edge-on-edge.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ test.describe('edge on edge', () => {
7474
await page.mouse.up();
7575
await expect(edges).toHaveCount(2);
7676
//Create node to edge
77-
playwrightNode2b.click();
77+
await playwrightNode2b.click();
7878
await page.getByTestId('creationhandle-bottom').hover();
7979
await page.mouse.down();
8080
const playwrightEdge = new PlaywrightEdge(page);

integration-tests-playwright/playwright/e2e/diagrams/key-bindings.spec.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,6 @@ import { PlaywrightProject } from '../../helpers/PlaywrightProject';
1818
test.describe('diagram - key bindings', () => {
1919
let projectId;
2020
test.beforeEach(async ({ page, request }) => {
21-
await page.addInitScript(() => {
22-
// @ts-expect-error: we use a variable in the DOM to disable `fitView` functionality for Cypress tests.
23-
window.document.DEACTIVATE_FIT_VIEW_FOR_CYPRESS_TESTS = true;
24-
});
2521
const project = await new PlaywrightProject(request).createProject('Studio', 'blank-studio-template');
2622
projectId = project.projectId;
2723

integration-tests-playwright/playwright/e2e/diagrams/multi-dnd.spec.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* Contributors:
1111
* Obeo - initial API and implementation
1212
*******************************************************************************/
13-
import { expect, test } from '@playwright/test';
13+
import { expect, test, Page } from '@playwright/test';
1414
import { PlaywrightExplorer } from '../../helpers/PlaywrightExplorer';
1515
import { PlaywrightNode } from '../../helpers/PlaywrightNode';
1616
import { PlaywrightProject } from '../../helpers/PlaywrightProject';
@@ -87,12 +87,17 @@ test.describe('diagram - drag and drop of multiple elements', () => {
8787
// Now, inside the diagram, select both attributes from the 'Source' entity
8888
const attr1NodeBefore = new PlaywrightNode(page, 'attr1', 'IconLabel');
8989
await attr1NodeBefore.click();
90+
// Hide Node Panel Info to avoid overlap in diagram
91+
const panel = page.locator('.react-flow__panel.bottom.left').first();
92+
await panel.evaluate((node) => {
93+
node.style.visibility = 'hidden';
94+
});
9095

9196
const attr2NodeBefore = new PlaywrightNode(page, 'attr2', 'IconLabel');
9297
await attr2NodeBefore.controlClick();
9398

9499
// And move them inside the 'Target' entity
95-
await attr2NodeBefore.move({ x: 400, y: 0 });
100+
await attr2NodeBefore.move({ x: 10, y: -300 });
96101

97102
await page.waitForFunction(
98103
() => {
@@ -148,12 +153,17 @@ test.describe('diagram - drag and drop of multiple elements', () => {
148153
// Now, inside the diagram, select both attributes from the 'Source' entity
149154
const attr1NodeBefore = new PlaywrightNode(page, 'attr1', 'IconLabel');
150155
await attr1NodeBefore.click();
156+
// Hide Node Panel Info to avoid overlap in diagram
157+
const panel = page.locator('.react-flow__panel.bottom.left').first();
158+
await panel.evaluate((node) => {
159+
node.style.visibility = 'hidden';
160+
});
151161

152162
const attr2NodeBefore = new PlaywrightNode(page, 'attr2', 'IconLabel');
153163
await attr2NodeBefore.controlClick();
154164

155165
// And move them directly on the diagram area (not on an entity)
156-
await attr2NodeBefore.move({ x: 200, y: 200 });
166+
await attr2NodeBefore.move({ x: 400, y: 100 });
157167

158168
await page.waitForFunction(
159169
() => {

integration-tests-playwright/playwright/e2e/diagrams/tool.spec.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,6 @@ test.describe('diagram - tool', () => {
5252
test.describe('diagram - tool key bindings', () => {
5353
let projectId;
5454
test.beforeEach(async ({ page, request }) => {
55-
await page.addInitScript(() => {
56-
// @ts-expect-error: we use a variable in the DOM to disable `fitView` functionality for Cypress tests.
57-
window.document.DEACTIVATE_FIT_VIEW_FOR_CYPRESS_TESTS = true;
58-
});
5955
const project = await new PlaywrightProject(request).createProject('Studio', 'blank-studio-template');
6056
projectId = project.projectId;
6157

packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/DiagramCreationService.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import org.eclipse.sirius.components.diagrams.components.DiagramComponentProps;
3939
import org.eclipse.sirius.components.diagrams.components.DiagramComponentProps.Builder;
4040
import org.eclipse.sirius.components.diagrams.description.DiagramDescription;
41+
import org.eclipse.sirius.components.diagrams.description.DiagramLayoutOption;
4142
import org.eclipse.sirius.components.diagrams.events.IDiagramEvent;
4243
import org.eclipse.sirius.components.diagrams.events.undoredo.DiagramEdgeLayoutEvent;
4344
import org.eclipse.sirius.components.diagrams.events.undoredo.DiagramLabelLayoutEvent;
@@ -186,7 +187,8 @@ private Diagram doRender(Object targetObject, IEditingContext editingContext, Di
186187
.filter(DiagramEdgeLayoutEvent.class::isInstance)
187188
.map(DiagramEdgeLayoutEvent.class::cast).toList();
188189

189-
var newLayoutData = optionalPreviousDiagram.map(Diagram::getLayoutData).orElse(new DiagramLayoutData(Map.of(), Map.of(), Map.of()));
190+
var newLayoutData = optionalPreviousDiagram.map(Diagram::getLayoutData).orElse(new DiagramLayoutData(Map.of(), Map.of(), Map.of(),
191+
!diagramDescription.getLayoutOption().equals(DiagramLayoutOption.NONE)));
190192

191193
diagramNodeLayoutEvents.forEach(nodeLayoutDataEvent ->
192194
newLayoutData.nodeLayoutData().put(nodeLayoutDataEvent.nodeId(), nodeLayoutDataEvent.nodeLayoutData()));
@@ -230,7 +232,13 @@ public Diagram updateLayout(IEditingContext editingContext, Diagram diagram, Lay
230232
(oldValue, newValue) -> newValue
231233
));
232234

233-
var layoutData = new DiagramLayoutData(nodeLayoutData, edgeLayoutData, labelLayoutData);
235+
boolean autoLaidOut = switch (layoutDiagramInput.diagramLayoutData().autoLayoutState()) {
236+
case ACTIVATE -> true;
237+
case DEACTIVATE -> false;
238+
case UNCHANGED -> diagram.getLayoutData().autoLaidOut();
239+
};
240+
241+
var layoutData = new DiagramLayoutData(nodeLayoutData, edgeLayoutData, labelLayoutData, autoLaidOut);
234242
var laidOutDiagram = Diagram.newDiagram(diagram)
235243
.layoutData(layoutData)
236244
.build();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2026 Obeo.
3+
* This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License v2.0
5+
* which accompanies this distribution, and is available at
6+
* https://www.eclipse.org/legal/epl-2.0/
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
* Contributors:
11+
* Obeo - initial API and implementation
12+
*******************************************************************************/
13+
package org.eclipse.sirius.components.collaborative.diagrams.dto;
14+
15+
/**
16+
* Defines the possible actions for managing the autoLayout state.
17+
*
18+
* @author frouene
19+
*/
20+
public enum AutoLayoutState {
21+
UNCHANGED,
22+
ACTIVATE,
23+
DEACTIVATE
24+
}

packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/dto/DiagramLayoutDataInput.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2023, 2025 Obeo.
2+
* Copyright (c) 2023, 2026 Obeo.
33
* This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v2.0
55
* which accompanies this distribution, and is available at
@@ -19,6 +19,9 @@
1919
*
2020
* @author sbegaudeau
2121
*/
22-
public record DiagramLayoutDataInput(List<NodeLayoutDataInput> nodeLayoutData, List<EdgeLayoutDataInput> edgeLayoutData, List<LabelLayoutDataInput> labelLayoutData) {
22+
public record DiagramLayoutDataInput(List<NodeLayoutDataInput> nodeLayoutData,
23+
List<EdgeLayoutDataInput> edgeLayoutData,
24+
List<LabelLayoutDataInput> labelLayoutData,
25+
AutoLayoutState autoLayoutState) {
2326

2427
}

0 commit comments

Comments
 (0)