New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[2572] Use dynamic handles #2573
Conversation
ad23956
to
6b6a71d
Compare
c0ed941
to
5298b41
Compare
0bfbf47
to
509d3c2
Compare
.../diagrams/frontend/sirius-components-diagrams-reactflow/src/converter/ConvertEngine.types.ts
Outdated
Show resolved
Hide resolved
...ages/diagrams/frontend/sirius-components-diagrams-reactflow/src/renderer/DiagramRenderer.tsx
Outdated
Show resolved
Hide resolved
...nd/sirius-components-diagrams-reactflow/src/renderer/handles/useRefreshConnectionHandles.tsx
Outdated
Show resolved
Hide resolved
...rius-components-diagrams-reactflow/src/renderer/handles/useRefreshConnectionHandles.types.ts
Outdated
Show resolved
Hide resolved
if ( | ||
nodeSourceConnectionHandle?.position !== sourcePosition && | ||
nodeTargetConnectionHandle?.position !== targetPosition | ||
) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be more like ||
instead of &&
? Written this way, it seems like we will update the connection handles only if both the source and target positions change.
Maybe something like this.
if (
nodeSourceConnectionHandle?.position !== sourcePosition ||
nodeTargetConnectionHandle?.position !== targetPosition
) {
let nodeSourceConnectionHandles: ConnectionHandle[] = sourceNode.data.connectionHandles;
if (nodeSourceConnectionHandle?.position !== sourcePosition) {
nodeSourceConnectionHandles = sourceNode.data.connectionHandles.map(
(nodeConnectionHandle: ConnectionHandle) => {
if (nodeConnectionHandle.id === sourceHandle && nodeConnectionHandle.type === 'source') {
nodeConnectionHandle.position = sourcePosition;
}
return nodeConnectionHandle;
}
);
}
let nodeTargetConnectionHandles: ConnectionHandle[] = targetNode.data.connectionHandles;
if (nodeTargetConnectionHandle?.position !== targetPosition) {
nodeTargetConnectionHandles = targetNode.data.connectionHandles.map(
(nodeConnectionHandle: ConnectionHandle) => {
if (nodeConnectionHandle.id === targetHandle && nodeConnectionHandle.type === 'target') {
nodeConnectionHandle.position = targetPosition;
}
return nodeConnectionHandle;
}
);
}
...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes currently, how we calculate a change in handle position is making both handles to change position.
packages/diagrams/frontend/sirius-components-diagrams-reactflow/src/converter/convertDiagram.ts
Outdated
Show resolved
Hide resolved
packages/diagrams/frontend/sirius-components-diagrams-reactflow/src/converter/convertDiagram.ts
Outdated
Show resolved
Hide resolved
const nodeSourceConnectionHandle: ConnectionHandle | undefined = sourceNode.data.connectionHandles.find( | ||
(connectionHandle: ConnectionHandle) => connectionHandle.id === sourceHandle | ||
); | ||
const nodeTargetConnectionHandle: ConnectionHandle | undefined = targetNode.data.connectionHandles.find( | ||
(connectionHandle: ConnectionHandle) => connectionHandle.id === targetHandle | ||
); | ||
|
||
if ( | ||
nodeSourceConnectionHandle?.position !== sourcePosition && | ||
nodeTargetConnectionHandle?.position !== targetPosition | ||
) { | ||
const nodeSourceConnectionHandles: ConnectionHandle[] = sourceNode.data.connectionHandles.map( | ||
(nodeConnectionHandle: ConnectionHandle) => { | ||
if (nodeConnectionHandle.id === sourceHandle && nodeConnectionHandle.type === 'source') { | ||
nodeConnectionHandle.position = sourcePosition; | ||
} | ||
return nodeConnectionHandle; | ||
} | ||
); | ||
|
||
const nodeTargetConnectionHandles: ConnectionHandle[] = targetNode.data.connectionHandles.map( | ||
(nodeConnectionHandle: ConnectionHandle) => { | ||
if (nodeConnectionHandle.id === targetHandle && nodeConnectionHandle.type === 'target') { | ||
nodeConnectionHandle.position = targetPosition; | ||
} | ||
return nodeConnectionHandle; | ||
} | ||
); | ||
|
||
setNodes((nodes: Node<NodeData>[]) => | ||
nodes.map((node) => { | ||
if (sourceNode.id === node.id) { | ||
node.data = { ...node.data, connectionHandles: nodeSourceConnectionHandles }; | ||
} | ||
if (targetNode.id === node.id) { | ||
node.data = { ...node.data, connectionHandles: nodeTargetConnectionHandles }; | ||
} | ||
return node; | ||
}) | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks very similar to what's in layoutHandles
(except it uses setNodes
instead of diagram.nodes =
), so:
- it's probably possible to share most/all of the code;
- the same remark I did regarding the logic of the
if
applies here too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I pushed a version that reuse more code but since we are in 2 différents situations I don't see how I could share more code.
packages/diagrams/frontend/sirius-components-diagrams-reactflow/src/converter/convertHandles.ts
Outdated
Show resolved
Hide resolved
packages/diagrams/frontend/sirius-components-diagrams-reactflow/src/converter/convertHandles.ts
Outdated
Show resolved
Hide resolved
43d844b
to
d011115
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks fine to me. There are a few minor known issues left, but they can probably be handled afterwards. @sbegaudeau can have a look and see if you find anything worth blocking this? Otherwise I'll merge it and start working the last remaining task (the feedback).
Known issues:
- the edges go 1/2 pixels too far inside the nodes instead of stopping right at their border.
- the presence of the "virtual handles" (one on the left side, one one the right side), even if they are invisible, means a single edge on the left or right side of a node does not point to the middle of the node's side.
- the way "sibling handles" are ordered on a given side does not take the position of the target nodes into account, which creates edge crossings in some cases. There's probably a way to improve this in common cases without going all the way and try to fix all potential edge crossings.
- Feedback is missing (incompatible nodes faded, compatible nodes unfaded, selected/target node highlighed).
- It's possible to trigger a reconnect even on an edge which is not currently selected (maybe we actually want this?).
There a probably also possible ergonomics improvements that we'll discover once this is merged and we actually start using all this.
Bug: #2572 Signed-off-by: Michaël Charfadi <michael.charfadi@obeosoft.com>
d011115
to
b449204
Compare
Waiting for the build to merge. We'll handle the known issues and missing parts in later PRs. |
Bug: #2572
Pull request template
General purpose
What is the main goal of this pull request?
Project management
priority:
andpr:
labels been added to the pull request? (In case of doubt, start with the labelspriority: low
andpr: to review later
)area:
,difficulty:
,type:
)CHANGELOG.adoc
been updated to reference the relevant issues?CHANGELOG.adoc
? (Including changes in the GraphQL API)CHANGELOG.adoc
? For example indoc/screenshots/2022.5.0-my-new-feature.png
Architectural decision records (ADR)
[doc]
?CHANGELOG.adoc
?Dependencies
CHANGELOG.adoc
?CHANGELOG.adoc
?Frontend
This section is not relevant if your contribution does not come with changes to the frontend.
General purpose
Typing
We need to improve the typing of our code, as such, we require every contribution to come with proper TypeScript typing for both changes contributing new files and those modifying existing files.
Please ensure that the following statements are true for each file created or modified (this may require you to improve code outside of your contribution).
useMutation<DATA_TYPE, VARIABLE_TYPE>(…)
useQuery<DATA_TYPE, VARIABLE_TYPE>(…)
useSubscription<DATA_TYPE, VARIABLE_TYPE>(…)
useMachine<CONTEXT_TYPE, EVENTS_TYPE>(…)
useState<STATE_TYPE>(…)
?.
(if the GraphQL API specifies that a field cannot benull
, do not treat it has potentiallynull
for example)let diagram: Diagram | null = null;
)Backend
This section is not relevant if your contribution does not come with changes to the backend.
General purpose
Architecture
Review
How to test this PR?
Please describe here the various use cases to test this pull request