From 8a832f1bc2eb045f95d9cc0e66bba7be559caad5 Mon Sep 17 00:00:00 2001 From: Braks <78412429+bcakmakoglu@users.noreply.github.com> Date: Wed, 8 Jan 2025 19:49:04 +0100 Subject: [PATCH] refactor(core): use connection lookup to check for selected elements (#1737) * refactor(core): use connection lookup to check for selected elements Signed-off-by: braks <78412429+bcakmakoglu@users.noreply.github.com> * chore(changeset): add Signed-off-by: braks <78412429+bcakmakoglu@users.noreply.github.com> --------- Signed-off-by: braks <78412429+bcakmakoglu@users.noreply.github.com> --- .changeset/flat-impalas-look.md | 5 ++ packages/core/src/container/Pane/Pane.vue | 79 +++++++++-------------- packages/core/src/utils/store.ts | 17 +++++ 3 files changed, 54 insertions(+), 47 deletions(-) create mode 100644 .changeset/flat-impalas-look.md diff --git a/.changeset/flat-impalas-look.md b/.changeset/flat-impalas-look.md new file mode 100644 index 000000000..bd67d0e4b --- /dev/null +++ b/.changeset/flat-impalas-look.md @@ -0,0 +1,5 @@ +--- +"@vue-flow/core": minor +--- + +Use connection lookup to check what elements should be selected by a user selection box. diff --git a/packages/core/src/container/Pane/Pane.vue b/packages/core/src/container/Pane/Pane.vue index e13a54844..35936554d 100644 --- a/packages/core/src/container/Pane/Pane.vue +++ b/packages/core/src/container/Pane/Pane.vue @@ -2,10 +2,10 @@ import { ref, toRef, watch } from 'vue' import UserSelection from '../../components/UserSelection/UserSelection.vue' import NodesSelection from '../../components/NodesSelection/NodesSelection.vue' -import type { NodeChange } from '../../types' +import type { EdgeChange, NodeChange } from '../../types' import { SelectionMode } from '../../types' import { useKeyPress, useVueFlow } from '../../composables' -import { getEventPosition, getNodesInside, getSelectionChanges } from '../../utils' +import { areSetsEqual, getEventPosition, getNodesInside, getSelectionChanges } from '../../utils' import { getMousePosition } from './utils' const { isSelecting, selectionKeyPressed } = defineProps<{ isSelecting: boolean; selectionKeyPressed: boolean }>() @@ -30,18 +30,18 @@ const { multiSelectionActive, edgeLookup, nodeLookup, + connectionLookup, + defaultEdgeOptions, } = useVueFlow() const container = ref(null) -const prevSelectedNodesCount = ref(0) +const selectedNodeIds = ref>(new Set()) -const prevSelectedEdgesCount = ref(0) +const selectedEdgeIds = ref>(new Set()) const containerBounds = ref() -const edgeIdLookup = ref>>(new Map()) - const hasActiveSelection = toRef(() => elementsSelectable.value && (isSelecting || userSelectionActive.value)) // Used to prevent click events when the user lets go of the selectionKey during a selection @@ -78,14 +78,6 @@ function wrapHandler(handler: Function, containerRef: HTMLDivElement | null) { } } -function resetUserSelection() { - userSelectionActive.value = false - userSelectionRect.value = null - - prevSelectedNodesCount.value = 0 - prevSelectedEdgesCount.value = 0 -} - function onClick(event: MouseEvent) { if (selectionInProgress) { selectionInProgress = false @@ -129,12 +121,6 @@ function onPointerDown(event: PointerEvent) { selectionStarted = true selectionInProgress = false - edgeIdLookup.value = new Map() - - for (const [id, edge] of edgeLookup.value) { - edgeIdLookup.value.set(edge.source, edgeIdLookup.value.get(edge.source)?.add(id) || new Set([id])) - edgeIdLookup.value.set(edge.target, edgeIdLookup.value.get(edge.target)?.add(id) || new Set([id])) - } removeSelectedElements() @@ -169,38 +155,39 @@ function onPointerMove(event: PointerEvent) { height: Math.abs(mouseY - startY), } - const selectedNodes = getNodesInside( - nodes.value, - nextUserSelectRect, - viewport.value, - selectionMode.value === SelectionMode.Partial, - true, - ) - - const selectedEdgeIds = new Set() - const selectedNodeIds = new Set() + const prevSelectedNodeIds = selectedNodeIds.value + const prevSelectedEdgeIds = selectedEdgeIds.value - for (const selectedNode of selectedNodes) { - selectedNodeIds.add(selectedNode.id) + selectedNodeIds.value = new Set( + getNodesInside(nodes.value, nextUserSelectRect, viewport.value, selectionMode.value === SelectionMode.Partial, true).map( + (node) => node.id, + ), + ) - const edgeIds = edgeIdLookup.value.get(selectedNode.id) + selectedEdgeIds.value = new Set() + const edgesSelectable = defaultEdgeOptions.value?.selectable ?? true - if (edgeIds) { - for (const edgeId of edgeIds) { - selectedEdgeIds.add(edgeId) + // We look for all edges connected to the selected nodes + for (const nodeId of selectedNodeIds.value) { + const connections = connectionLookup.value.get(nodeId) + if (!connections) { + continue + } + for (const { edgeId } of connections.values()) { + const edge = edgeLookup.value.get(edgeId) + if (edge && (edge.selectable ?? edgesSelectable)) { + selectedEdgeIds.value.add(edgeId) } } } - if (prevSelectedNodesCount.value !== selectedNodeIds.size) { - prevSelectedNodesCount.value = selectedNodeIds.size - const changes = getSelectionChanges(nodeLookup.value, selectedNodeIds, true) as NodeChange[] + if (!areSetsEqual(prevSelectedNodeIds, selectedNodeIds.value)) { + const changes = getSelectionChanges(nodeLookup.value, selectedNodeIds.value, true) as NodeChange[] emits.nodesChange(changes) } - if (prevSelectedEdgesCount.value !== selectedEdgeIds.size) { - prevSelectedEdgesCount.value = selectedEdgeIds.size - const changes = getSelectionChanges(edgeLookup.value, selectedEdgeIds) + if (!areSetsEqual(prevSelectedEdgeIds, selectedEdgeIds.value)) { + const changes = getSelectionChanges(edgeLookup.value, selectedEdgeIds.value) as EdgeChange[] emits.edgesChange(changes) } @@ -222,11 +209,9 @@ function onPointerUp(event: PointerEvent) { onClick(event) } - if (prevSelectedNodesCount.value > 0) { - nodesSelectionActive.value = true - } - - resetUserSelection() + userSelectionActive.value = false + userSelectionRect.value = null + nodesSelectionActive.value = selectedNodeIds.value.size > 0 emits.selectionEnd(event) diff --git a/packages/core/src/utils/store.ts b/packages/core/src/utils/store.ts index 0cbad7f07..f6e86e317 100644 --- a/packages/core/src/utils/store.ts +++ b/packages/core/src/utils/store.ts @@ -233,6 +233,23 @@ export function areConnectionMapsEqual(a?: Map, b?: Map, b: Set) { + if (a.size !== b.size) { + return false + } + + for (const item of a) { + if (!b.has(item)) { + return false + } + } + + return true +} + /** * @internal */