diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 683134fa6c..3c0ed4732e 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -46,6 +46,7 @@ - https://github.com/eclipse-sirius/sirius-web/issues/3441[#3441] [gantt] Use a DateTime widget for AbstractTask entity - https://github.com/eclipse-sirius/sirius-web/issues/3539[#3539] [diagram] Add editing context variable in diagram delete tool - https://github.com/eclipse-sirius/sirius-web/issues/3529[#3529] [diagram] Improve edge path when a layout direction is defined +- https://github.com/eclipse-sirius/sirius-web/issues/3489[#3489] [diagram] Apply a fit to screen after an arrange all == v2024.5.0 diff --git a/integration-tests/cypress/e2e/project/diagrams/edges.cy.ts b/integration-tests/cypress/e2e/project/diagrams/edges.cy.ts index 24205e396c..14afff8bc7 100644 --- a/integration-tests/cypress/e2e/project/diagrams/edges.cy.ts +++ b/integration-tests/cypress/e2e/project/diagrams/edges.cy.ts @@ -152,7 +152,6 @@ describe('Diagram - edges', () => { details.getReferenceWidgetSelectedValue('Linked To', 'Entity2.bis').should('exist'); diagram.getEdgePaths('diagram').should('have.length', 2); diagram.arrangeAll(); - diagram.fitToScreen(); diagram.getEdgePaths('diagram').should('have.length', 2); diagram .getEdgePaths('diagram') @@ -252,7 +251,6 @@ describe('Diagram - edges', () => { details.selectReferenceWidgetOption('Entity2'); explorer.createRepresentation('Root', `${domainName} Diagram Description`, 'diagram'); diagram.arrangeAll(); - diagram.fitToScreen(); diagram.getEdgePaths('diagram').should('have.length', 1); diagram .getEdgePaths('diagram') @@ -272,8 +270,6 @@ describe('Diagram - edges', () => { details.openReferenceWidgetOptions('Entity2'); details.selectReferenceWidgetOption('Child'); explorer.createRepresentation('Root', `${domainName} Diagram Description`, 'diagram'); - diagram.arrangeAll(); - diagram.fitToScreen(); diagram.getEdgePaths('diagram').should('have.length', 1); diagram .getEdgePaths('diagram') diff --git a/integration-tests/cypress/workbench/Diagram.ts b/integration-tests/cypress/workbench/Diagram.ts index 3b679ea121..0ae0e932bc 100644 --- a/integration-tests/cypress/workbench/Diagram.ts +++ b/integration-tests/cypress/workbench/Diagram.ts @@ -25,6 +25,8 @@ export class Diagram { public arrangeAll() { cy.getByTestId('arrange-all').click(); + /* eslint-disable-next-line cypress/no-unnecessary-waiting */ + cy.wait(4000); } public getNodes(diagramLabel: string, nodeLabel: string): Cypress.Chainable> { diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/layout/useArrangeAll.ts b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/layout/useArrangeAll.ts index af053531df..2f5fa754ce 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/layout/useArrangeAll.ts +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/layout/useArrangeAll.ts @@ -226,10 +226,10 @@ export const useArrangeAll = (reactFlowWrapper: React.MutableRefObject { + const arrangeAll = async (): Promise => { const nodes: Node[] = [...getNodes()] as Node[]; const subNodes: Map[]> = reverseOrdreMap(getSubNodes(nodes)); - applyElkOnSubNodes(subNodes, nodes).then((nodes: Node[]) => { + await applyElkOnSubNodes(subNodes, nodes).then(async (nodes: Node[]) => { const laidOutNodesWithElk: Node[] = nodes.reverse(); laidOutNodesWithElk.filter((laidOutNode) => { const parentNode = nodes.find((node) => node.id === laidOutNode.parentNode); @@ -240,37 +240,40 @@ export const useArrangeAll = (reactFlowWrapper: React.MutableRefObject { - laidOutNodesWithElk.map((node) => { - const overlapFreeLaidOutNodes: Node[] = resolveNodeOverlap( - laidOutDiagram.nodes, - 'horizontal' - ) as Node[]; - const existingNode = overlapFreeLaidOutNodes.find((laidOutNode) => laidOutNode.id === node.id); - if (existingNode) { - return { - ...node, - position: existingNode.position, - width: existingNode.width, - height: existingNode.height, - style: { - ...node.style, - width: `${existingNode.width}px`, - height: `${existingNode.height}px`, - }, - }; - } - return node; + const layoutPromise = new Promise((resolve) => { + layout(diagramToLayout, diagramToLayout, null, (laidOutDiagram) => { + laidOutNodesWithElk.map((node) => { + const overlapFreeLaidOutNodes: Node[] = resolveNodeOverlap( + laidOutDiagram.nodes, + 'horizontal' + ) as Node[]; + const existingNode = overlapFreeLaidOutNodes.find((laidOutNode) => laidOutNode.id === node.id); + if (existingNode) { + return { + ...node, + position: existingNode.position, + width: existingNode.width, + height: existingNode.height, + style: { + ...node.style, + width: `${existingNode.width}px`, + height: `${existingNode.height}px`, + }, + }; + } + return node; + }); + setNodes(laidOutNodesWithElk); + setEdges(laidOutDiagram.edges); + const finalDiagram: RawDiagram = { + nodes: laidOutNodesWithElk, + edges: laidOutDiagram.edges, + }; + synchronizeLayoutData(refreshEventPayloadId, finalDiagram); + resolve(); }); - setNodes(laidOutNodesWithElk); - setEdges(laidOutDiagram.edges); - const finalDiagram: RawDiagram = { - nodes: laidOutNodesWithElk, - edges: laidOutDiagram.edges, - }; - synchronizeLayoutData(refreshEventPayloadId, finalDiagram); }); + await layoutPromise; }); }; diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/layout/useArrangeAll.types.ts b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/layout/useArrangeAll.types.ts index d57b88f060..da3c6b8f3b 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/layout/useArrangeAll.types.ts +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/layout/useArrangeAll.types.ts @@ -12,5 +12,5 @@ *******************************************************************************/ export interface UseArrangeAllValue { - arrangeAll: () => void; + arrangeAll: () => Promise; } diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/panel/DiagramPanel.tsx b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/panel/DiagramPanel.tsx index ef4682be11..a56673c964 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/panel/DiagramPanel.tsx +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/panel/DiagramPanel.tsx @@ -27,8 +27,8 @@ import TonalityIcon from '@material-ui/icons/Tonality'; import VisibilityOffIcon from '@material-ui/icons/VisibilityOff'; import ZoomInIcon from '@material-ui/icons/ZoomIn'; import ZoomOutIcon from '@material-ui/icons/ZoomOut'; -import { memo, useContext, useState } from 'react'; -import { Panel, useReactFlow } from 'reactflow'; +import { memo, useContext, useEffect, useState } from 'react'; +import { Panel, useNodesInitialized, useReactFlow } from 'reactflow'; import { DiagramContext } from '../../contexts/DiagramContext'; import { DiagramContextValue } from '../../contexts/DiagramContext.types'; import { HelperLinesIcon } from '../../icons/HelperLinesIcon'; @@ -47,6 +47,7 @@ export const DiagramPanel = memo( ({ snapToGrid, onSnapToGrid, helperLines, onHelperLines, reactFlowWrapper }: DiagramPanelProps) => { const [state, setState] = useState({ dialogOpen: null, + arrangeAllDone: false, }); const { readOnly } = useContext(DiagramContext); @@ -58,6 +59,13 @@ export const DiagramPanel = memo( const { fullscreen, onFullscreen } = useFullscreen(); const { arrangeAll } = useArrangeAll(reactFlowWrapper); + const nodesInitialized = useNodesInitialized(); + useEffect(() => { + if (nodesInitialized && state.arrangeAllDone) { + fitView({ duration: 400 }); + setState((prevState) => ({ ...prevState, arrangeAllDone: false })); + } + }, [nodesInitialized, state.arrangeAllDone]); const handleFitToScreen = () => fitView({ duration: 200, nodes: getSelectedNodes() }); const handleZoomIn = () => zoomIn({ duration: 200 }); @@ -164,7 +172,14 @@ export const DiagramPanel = memo( arrangeAll()} + onClick={() => + arrangeAll().then(() => + setState((prevState) => ({ + ...prevState, + arrangeAllDone: true, + })) + ) + } data-testid={'arrange-all'} disabled={readOnly}> diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/panel/DiagramPanel.types.ts b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/panel/DiagramPanel.types.ts index b2d54532dc..a6f8149543 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/panel/DiagramPanel.types.ts +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/panel/DiagramPanel.types.ts @@ -21,6 +21,7 @@ export interface DiagramPanelProps { export interface DiagramPanelState { dialogOpen: DiagramPanelDialog | null; + arrangeAllDone: boolean; } export type DiagramPanelDialog = 'Share';