Skip to content

Commit

Permalink
[2532] Allows border to move on all parent node sizes
Browse files Browse the repository at this point in the history
Bug: #2532
Signed-off-by: Florian ROUËNÉ <florian.rouene@obeosoft.com>
  • Loading branch information
frouene committed Nov 6, 2023
1 parent f714a74 commit c64c55e
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 32 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.adoc
Expand Up @@ -58,6 +58,7 @@ Note that double-clicking no longer triggers a direct edit.
- https://github.com/eclipse-sirius/sirius-web/issues/2509[#2509] [diagram] Fix an issue that prevents using graphical DnD in deep node in some cases.
- https://github.com/eclipse-sirius/sirius-web/issues/2453[#2453] [diagram] Add support for feedback messages on following actions: DropOnDiagram, DeleteFromDiagram, ReconnectEdge and EditLabel
- https://github.com/eclipse-sirius/sirius-web/issues/2513[#2513] [diagram] Fix the double node border displayed when node list was containing compartments.
- https://github.com/eclipse-sirius/sirius-web/issues/2532[#2532] [diagram] Fix the limitation on borders that prevent movement on all sides of their node parent.

=== New Features

Expand Down
Expand Up @@ -31,11 +31,14 @@ import {
useReactFlow,
useStoreApi,
} from 'reactflow';

import 'reactflow/dist/style.css';
import { convertDiagram } from '../converter/convertDiagram';
import { Diagram, DiagramRendererProps, DiagramRendererState, EdgeData, NodeData } from './DiagramRenderer.types';
import { useBorderChange } from './border/useBorderChange';
import { ConnectorContextualMenu } from './connector/ConnectorContextualMenu';
import { useConnector } from './connector/useConnector';
import { useDiagramDelete } from './delete/useDiagramDelete';
import { Diagram, DiagramRendererProps, DiagramRendererState, EdgeData, NodeData } from './DiagramRenderer.types';
import { useDiagramDirectEdit } from './direct-edit/useDiagramDirectEdit';
import { useDrop } from './drop/useDrop';
import { useDropNode } from './dropNode/useDropNode';
Expand All @@ -50,8 +53,6 @@ import { useDiagramPalette } from './palette/useDiagramPalette';
import { DiagramPanel } from './panel/DiagramPanel';
import { useReconnectEdge } from './reconnect-edge/useReconnectEdge';

import 'reactflow/dist/style.css';

const GRID_STEP: number = 10;

const isNodeSelectChange = (change: NodeChange): change is NodeSelectionChange => change.type === 'select';
Expand All @@ -76,6 +77,7 @@ export const DiagramRenderer = ({ diagramRefreshedEventPayload, selection, setSe
const { onConnect, onConnectStart, onConnectEnd } = useConnector();
const { reconnectEdge } = useReconnectEdge();
const { onDrop, onDragOver } = useDrop();
const { onBorderChange } = useBorderChange();

const [nodes, setNodes, onNodesChange] = useNodesState<NodeData>([]);
const [edges, setEdges, onEdgesChange] = useEdgesState<MultiLabelEdgeData>([]);
Expand Down Expand Up @@ -145,7 +147,7 @@ export const DiagramRenderer = ({ diagramRefreshedEventPayload, selection, setSe
}, [selection]);

const handleNodesChange: OnNodesChange = (changes: NodeChange[]) => {
onNodesChange(changes);
onNodesChange(onBorderChange(changes));

const selectionEntries: SelectionEntry[] = changes
.filter(isNodeSelectChange)
Expand Down
@@ -0,0 +1,50 @@
/*******************************************************************************
* Copyright (c) 2023 Obeo.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
import { useCallback } from 'react';
import { Node, NodeChange, useReactFlow, XYPosition } from 'reactflow';
import { UseBorderChangeValue } from './useBorderChange.types';

const isNewPositionInsideIsParent = (newNodePosition: XYPosition, movedNode: Node, parentNode: Node): boolean => {
if (movedNode.width && movedNode.height && parentNode?.positionAbsolute && parentNode.width && parentNode.height) {
return (
parentNode.positionAbsolute.x < newNodePosition.x + movedNode.width &&
parentNode.positionAbsolute.x + parentNode.width > newNodePosition.x &&
parentNode.positionAbsolute.y < newNodePosition.y + movedNode.height &&
parentNode.positionAbsolute.y + parentNode.height > newNodePosition.y
);
}
return false;
};

export const useBorderChange = (): UseBorderChangeValue => {
const { getNodes } = useReactFlow();

const onBorderChange = useCallback((changes: NodeChange[]): NodeChange[] => {
return changes.map((change) => {
if (change.type === 'position' && change.positionAbsolute) {
const movedNode = getNodes().find((node) => change.id === node.id);
if (movedNode?.data.isBorderNode) {
const parentNode = getNodes().find((node) => movedNode?.parentNode === node.id);
if (parentNode && isNewPositionInsideIsParent(change.positionAbsolute, movedNode, parentNode)) {
//Invalid position, reset to the initial one
change.position = movedNode.position;
change.positionAbsolute = movedNode.positionAbsolute;
}
}
}
return change;
});
}, []);

return { onBorderChange };
};
@@ -0,0 +1,17 @@
/*******************************************************************************
* Copyright (c) 2023 Obeo.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
import { NodeChange } from 'reactflow';

export interface UseBorderChangeValue {
onBorderChange: (changes: NodeChange[]) => NodeChange[];
}
Expand Up @@ -32,34 +32,10 @@ export const getBorderNodeExtent = (
): CoordinateExtent | 'parent' => {
let coordinateExtent: CoordinateExtent | 'parent' = 'parent';
if (nodeParent.width && nodeParent.height && borderNorde.height && borderNorde.width) {
switch (borderNorde.data.borderNodePosition) {
case BorderNodePositon.EAST:
coordinateExtent = [
[nodeParent.width, 0],
[nodeParent.width, nodeParent.height - borderNorde.height],
];
break;
case BorderNodePositon.NORTH:
coordinateExtent = [
[0 - borderNorde.width * 0.8, 0 - borderNorde.height],
[nodeParent.width - borderNorde.width * 0.3, 0 - borderNorde.height],
];
break;
case BorderNodePositon.SOUTH:
coordinateExtent = [
[0 - borderNorde.width * 0.8, nodeParent.height],
[nodeParent.width - borderNorde.width * 0.3, nodeParent.height],
];
break;
case BorderNodePositon.WEST:
coordinateExtent = [
[0 - borderNorde.width, 0],
[0 - borderNorde.width, nodeParent.height - borderNorde.height],
];
break;
default:
coordinateExtent = 'parent';
}
coordinateExtent = [
[0 - borderNorde.width, 0 - borderNorde.height],
[nodeParent.width, nodeParent.height],
];
}
return coordinateExtent;
};

0 comments on commit c64c55e

Please sign in to comment.