Skip to content

Commit 6f3ed67

Browse files
committed
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 <[email protected]> * chore(changeset): add Signed-off-by: braks <[email protected]> --------- Signed-off-by: braks <[email protected]>
1 parent 3d1b85f commit 6f3ed67

File tree

3 files changed

+54
-47
lines changed

3 files changed

+54
-47
lines changed

.changeset/flat-impalas-look.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@vue-flow/core": minor
3+
---
4+
5+
Use connection lookup to check what elements should be selected by a user selection box.

packages/core/src/container/Pane/Pane.vue

Lines changed: 32 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
import { ref, toRef, watch } from 'vue'
33
import UserSelection from '../../components/UserSelection/UserSelection.vue'
44
import NodesSelection from '../../components/NodesSelection/NodesSelection.vue'
5-
import type { NodeChange } from '../../types'
5+
import type { EdgeChange, NodeChange } from '../../types'
66
import { SelectionMode } from '../../types'
77
import { useKeyPress, useVueFlow } from '../../composables'
8-
import { getEventPosition, getNodesInside, getSelectionChanges } from '../../utils'
8+
import { areSetsEqual, getEventPosition, getNodesInside, getSelectionChanges } from '../../utils'
99
import { getMousePosition } from './utils'
1010
1111
const { isSelecting, selectionKeyPressed } = defineProps<{ isSelecting: boolean; selectionKeyPressed: boolean }>()
@@ -30,18 +30,18 @@ const {
3030
multiSelectionActive,
3131
edgeLookup,
3232
nodeLookup,
33+
connectionLookup,
34+
defaultEdgeOptions,
3335
} = useVueFlow()
3436
3537
const container = ref<HTMLDivElement | null>(null)
3638
37-
const prevSelectedNodesCount = ref(0)
39+
const selectedNodeIds = ref<Set<string>>(new Set())
3840
39-
const prevSelectedEdgesCount = ref(0)
41+
const selectedEdgeIds = ref<Set<string>>(new Set())
4042
4143
const containerBounds = ref<DOMRect>()
4244
43-
const edgeIdLookup = ref<Map<string, Set<string>>>(new Map())
44-
4545
const hasActiveSelection = toRef(() => elementsSelectable.value && (isSelecting || userSelectionActive.value))
4646
4747
// 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) {
7878
}
7979
}
8080
81-
function resetUserSelection() {
82-
userSelectionActive.value = false
83-
userSelectionRect.value = null
84-
85-
prevSelectedNodesCount.value = 0
86-
prevSelectedEdgesCount.value = 0
87-
}
88-
8981
function onClick(event: MouseEvent) {
9082
if (selectionInProgress) {
9183
selectionInProgress = false
@@ -129,12 +121,6 @@ function onPointerDown(event: PointerEvent) {
129121
130122
selectionStarted = true
131123
selectionInProgress = false
132-
edgeIdLookup.value = new Map()
133-
134-
for (const [id, edge] of edgeLookup.value) {
135-
edgeIdLookup.value.set(edge.source, edgeIdLookup.value.get(edge.source)?.add(id) || new Set([id]))
136-
edgeIdLookup.value.set(edge.target, edgeIdLookup.value.get(edge.target)?.add(id) || new Set([id]))
137-
}
138124
139125
removeSelectedElements()
140126
@@ -169,38 +155,39 @@ function onPointerMove(event: PointerEvent) {
169155
height: Math.abs(mouseY - startY),
170156
}
171157
172-
const selectedNodes = getNodesInside(
173-
nodes.value,
174-
nextUserSelectRect,
175-
viewport.value,
176-
selectionMode.value === SelectionMode.Partial,
177-
true,
178-
)
179-
180-
const selectedEdgeIds = new Set<string>()
181-
const selectedNodeIds = new Set<string>()
158+
const prevSelectedNodeIds = selectedNodeIds.value
159+
const prevSelectedEdgeIds = selectedEdgeIds.value
182160
183-
for (const selectedNode of selectedNodes) {
184-
selectedNodeIds.add(selectedNode.id)
161+
selectedNodeIds.value = new Set(
162+
getNodesInside(nodes.value, nextUserSelectRect, viewport.value, selectionMode.value === SelectionMode.Partial, true).map(
163+
(node) => node.id,
164+
),
165+
)
185166
186-
const edgeIds = edgeIdLookup.value.get(selectedNode.id)
167+
selectedEdgeIds.value = new Set()
168+
const edgesSelectable = defaultEdgeOptions.value?.selectable ?? true
187169
188-
if (edgeIds) {
189-
for (const edgeId of edgeIds) {
190-
selectedEdgeIds.add(edgeId)
170+
// We look for all edges connected to the selected nodes
171+
for (const nodeId of selectedNodeIds.value) {
172+
const connections = connectionLookup.value.get(nodeId)
173+
if (!connections) {
174+
continue
175+
}
176+
for (const { edgeId } of connections.values()) {
177+
const edge = edgeLookup.value.get(edgeId)
178+
if (edge && (edge.selectable ?? edgesSelectable)) {
179+
selectedEdgeIds.value.add(edgeId)
191180
}
192181
}
193182
}
194183
195-
if (prevSelectedNodesCount.value !== selectedNodeIds.size) {
196-
prevSelectedNodesCount.value = selectedNodeIds.size
197-
const changes = getSelectionChanges(nodeLookup.value, selectedNodeIds, true) as NodeChange[]
184+
if (!areSetsEqual(prevSelectedNodeIds, selectedNodeIds.value)) {
185+
const changes = getSelectionChanges(nodeLookup.value, selectedNodeIds.value, true) as NodeChange[]
198186
emits.nodesChange(changes)
199187
}
200188
201-
if (prevSelectedEdgesCount.value !== selectedEdgeIds.size) {
202-
prevSelectedEdgesCount.value = selectedEdgeIds.size
203-
const changes = getSelectionChanges(edgeLookup.value, selectedEdgeIds)
189+
if (!areSetsEqual(prevSelectedEdgeIds, selectedEdgeIds.value)) {
190+
const changes = getSelectionChanges(edgeLookup.value, selectedEdgeIds.value) as EdgeChange[]
204191
emits.edgesChange(changes)
205192
}
206193
@@ -222,11 +209,9 @@ function onPointerUp(event: PointerEvent) {
222209
onClick(event)
223210
}
224211
225-
if (prevSelectedNodesCount.value > 0) {
226-
nodesSelectionActive.value = true
227-
}
228-
229-
resetUserSelection()
212+
userSelectionActive.value = false
213+
userSelectionRect.value = null
214+
nodesSelectionActive.value = selectedNodeIds.value.size > 0
230215
231216
emits.selectionEnd(event)
232217

packages/core/src/utils/store.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,23 @@ export function areConnectionMapsEqual(a?: Map<string, Connection>, b?: Map<stri
233233
return true
234234
}
235235

236+
/**
237+
* @internal
238+
*/
239+
export function areSetsEqual(a: Set<string>, b: Set<string>) {
240+
if (a.size !== b.size) {
241+
return false
242+
}
243+
244+
for (const item of a) {
245+
if (!b.has(item)) {
246+
return false
247+
}
248+
}
249+
250+
return true
251+
}
252+
236253
/**
237254
* @internal
238255
*/

0 commit comments

Comments
 (0)