Skip to content

Commit

Permalink
[4664] Make ConnectionLine snap to the border of a node
Browse files Browse the repository at this point in the history
Bug: #4664
Signed-off-by: Michaël Charfadi <[email protected]>
  • Loading branch information
mcharfadi committed Mar 5, 2025
1 parent 5b57f24 commit 268af68
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ Given that it is an application service, it comes with some constraints with reg
- https://github.com/eclipse-sirius/sirius-web/issues/4588[#4588] [core] Added support for custom ordering in representation creation modal.
See the new interface `org.eclipse.sirius.components.emf.services.api.IRepresentationDescriptionMetadataSorter`.
- https://github.com/eclipse-sirius/sirius-web/issues/4616[#4616] [sirius-web] Allow end users to see the content of a library in a workbench, the path of the new page is `/libraries/:namespace/:name/:version`
- https://github.com/eclipse-sirius/sirius-web/issues/4664[#4664] [diagram] Make ConnectionLine snap to the border of a node


=== Improvements
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,7 @@ export const DiagramRenderer = memo(({ diagramRefreshedEventPayload }: DiagramRe
onConnectStart: onConnectStart,
onConnectEnd: onConnectEnd,
connectionLineComponent: ConnectionLine,
connectionRadius: 0,
onEdgesChange: handleEdgesChange,
onReconnect: reconnectEdge,
onPaneContextMenu: handlePaneContextMenu,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2024 Obeo.
* Copyright (c) 2024, 2025 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
Expand All @@ -10,10 +10,10 @@
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/

import { Theme, useTheme } from '@mui/material/styles';
import { ConnectionLineComponentProps, getSmoothStepPath } from '@xyflow/react';
import React, { memo } from 'react';
import { getNearestPointInPerimeter } from './EdgeLayout';

const connectionLineStyle = (theme: Theme): React.CSSProperties => {
return {
Expand All @@ -23,9 +23,40 @@ const connectionLineStyle = (theme: Theme): React.CSSProperties => {
};

export const ConnectionLine = memo(
({ fromX, fromY, toX, toY, fromPosition, toPosition }: ConnectionLineComponentProps) => {
({ fromX, fromY, toX, toY, fromPosition, toPosition, fromNode, toNode }: ConnectionLineComponentProps) => {
const theme = useTheme();

// Snap the ConnectionLine to the border of the targetted node
if (toNode && toNode.width && toNode.height) {
const pointToSnap = getNearestPointInPerimeter(
toNode.internals.positionAbsolute.x,
toNode.internals.positionAbsolute.y,
toNode.width,
toNode.height,
toX,
toY
);

toX = pointToSnap.XYpostion.x;
toY = pointToSnap.XYpostion.y;
toPosition = pointToSnap.position;
}

if (fromNode && fromNode.width && fromNode.height) {
const pointToSnap = getNearestPointInPerimeter(
fromNode.internals.positionAbsolute.x,
fromNode.internals.positionAbsolute.y,
fromNode.width,
fromNode.height,
fromX,
fromY
);

fromX = pointToSnap.XYpostion.x;
fromY = pointToSnap.XYpostion.y;
fromPosition = pointToSnap.position;
}

const [edgePath] = getSmoothStepPath({
sourceX: fromX,
sourceY: fromY,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2023, 2024 Obeo.
* Copyright (c) 2023, 2025 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
Expand Down Expand Up @@ -27,6 +27,39 @@ import {
NodeCenter,
} from './EdgeLayout.types';

const clamp = (n: number, lower: number, upper: number) => Math.max(lower, Math.min(upper, n));

export const getNearestPointInPerimeter = (
rectX: number,
rectY: number,
width: number,
height: number,
x: number,
y: number
): { XYpostion: XYPosition; position: Position } => {
const rectX2 = rectX + width;
const rectY2 = rectY + height;

x = clamp(x, rectX, rectX2);
y = clamp(y, rectY, rectY2);

const left = Math.abs(x - rectX);
const right = Math.abs(x - rectX2);
const top = Math.abs(y - rectY);
const bottom = Math.abs(y - rectY2);
const m = Math.min(left, right, top, bottom);

if (m === top) {
return { XYpostion: { x, y: rectY }, position: Position.Top };
} else if (m === bottom) {
return { XYpostion: { x, y: rectY2 }, position: Position.Bottom };
} else if (m === left) {
return { XYpostion: { x: rectX, y }, position: Position.Left };
} else {
return { XYpostion: { x: rectX2, y }, position: Position.Right };
}
};

export const getUpdatedConnectionHandles: GetUpdatedConnectionHandlesParameters = (
sourceNode,
targetNode,
Expand Down

0 comments on commit 268af68

Please sign in to comment.