From 2999c971cf3108b975022108e1ce3fc7bfc6eefa Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Sun, 23 Apr 2023 00:02:53 -0500 Subject: [PATCH] Expose current dragging and receiving nodes --- src/features/boards/Board.vue | 103 +++++++++++++++--------------- src/features/boards/BoardNode.vue | 12 ++-- src/features/boards/board.ts | 25 +++++++- 3 files changed, 82 insertions(+), 58 deletions(-) diff --git a/src/features/boards/Board.vue b/src/features/boards/Board.vue index 4212988..ef613b2 100644 --- a/src/features/boards/Board.vue +++ b/src/features/boards/Board.vue @@ -17,9 +17,9 @@ @touchmove="drag" @mousedown="(e: MouseEvent) => mouseDown(e)" @touchstart="(e: TouchEvent) => mouseDown(e)" - @mouseup="() => endDragging(dragging)" - @touchend.passive="() => endDragging(dragging)" - @mouseleave="() => endDragging(dragging)" + @mouseup="() => endDragging(unref(draggingNode))" + @touchend.passive="() => endDragging(unref(draggingNode))" + @mouseleave="() => endDragging(unref(draggingNode))" > @@ -36,10 +36,10 @@ ; selectedAction: Ref; selectedNode: Ref; + draggingNode: Ref; + receivingNode: Ref; mousePosition: Ref<{ x: number; y: number } | null>; + setReceivingNode: (node: BoardNode | null) => void; + setDraggingNode: (node: BoardNode | null) => void; }>(); const props = toRefs(_props); const lastMousePosition = ref({ x: 0, y: 0 }); const dragged = ref({ x: 0, y: 0 }); -const dragging = ref(null); const hasDragged = ref(false); // eslint-disable-next-line @typescript-eslint/no-explicit-any const stage = ref(null); -const draggingNode = computed(() => - dragging.value == null ? undefined : props.nodes.value.find(node => node.id === dragging.value) -); - const sortedNodes = computed(() => { const nodes = props.nodes.value.slice(); - if (draggingNode.value) { - const node = nodes.splice(nodes.indexOf(draggingNode.value), 1)[0]; + if (props.draggingNode.value) { + const node = nodes.splice(nodes.indexOf(props.draggingNode.value), 1)[0]; nodes.push(node); } return nodes; }); -const receivingNode = computed(() => { - const node = draggingNode.value; +watchEffect(() => { + const node = props.draggingNode.value; if (node == null) { return null; } @@ -116,26 +115,30 @@ const receivingNode = computed(() => { y: node.position.y + dragged.value.y }; let smallestDistance = Number.MAX_VALUE; - return props.nodes.value.reduce((smallest: BoardNode | null, curr: BoardNode) => { - if (curr.id === node.id) { - return smallest; - } - const nodeType = props.types.value[curr.type]; - const canAccept = getNodeProperty(nodeType.canAccept, curr); - if (!canAccept) { - return smallest; - } - const distanceSquared = - Math.pow(position.x - curr.position.x, 2) + Math.pow(position.y - curr.position.y, 2); - let size = getNodeProperty(nodeType.size, curr); - if (distanceSquared > smallestDistance || distanceSquared > size * size) { - return smallest; - } + props.setReceivingNode.value( + props.nodes.value.reduce((smallest: BoardNode | null, curr: BoardNode) => { + if (curr.id === node.id) { + return smallest; + } + const nodeType = props.types.value[curr.type]; + const canAccept = getNodeProperty(nodeType.canAccept, curr); + if (!canAccept) { + return smallest; + } - smallestDistance = distanceSquared; - return curr; - }, null); + const distanceSquared = + Math.pow(position.x - curr.position.x, 2) + + Math.pow(position.y - curr.position.y, 2); + let size = getNodeProperty(nodeType.size, curr); + if (distanceSquared > smallestDistance || distanceSquared > size * size) { + return smallest; + } + + smallestDistance = distanceSquared; + return curr; + }, null) + ); }); // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -144,8 +147,8 @@ function onInit(panzoomInstance: any) { panzoomInstance.moveTo(stage.value.$el.clientWidth / 2, stage.value.$el.clientHeight / 2); } -function mouseDown(e: MouseEvent | TouchEvent, nodeID: number | null = null, draggable = false) { - if (dragging.value == null) { +function mouseDown(e: MouseEvent | TouchEvent, node: BoardNode | null = null, draggable = false) { + if (props.draggingNode.value == null) { e.preventDefault(); e.stopPropagation(); @@ -169,10 +172,10 @@ function mouseDown(e: MouseEvent | TouchEvent, nodeID: number | null = null, dra hasDragged.value = false; if (draggable) { - dragging.value = nodeID; + props.setDraggingNode.value(node); } } - if (nodeID != null) { + if (node != null) { props.state.value.selectedNode = null; props.state.value.selectedAction = null; } @@ -187,7 +190,7 @@ function drag(e: MouseEvent | TouchEvent) { clientX = e.touches[0].clientX; clientY = e.touches[0].clientY; } else { - endDragging(dragging.value); + endDragging(props.draggingNode.value); props.mousePosition.value = null; return; } @@ -214,28 +217,28 @@ function drag(e: MouseEvent | TouchEvent) { hasDragged.value = true; } - if (dragging.value != null) { + if (props.draggingNode.value != null) { e.preventDefault(); e.stopPropagation(); } } -function endDragging(nodeID: number | null) { - if (dragging.value != null && dragging.value === nodeID && draggingNode.value != null) { - draggingNode.value.position.x += Math.round(dragged.value.x / 25) * 25; - draggingNode.value.position.y += Math.round(dragged.value.y / 25) * 25; +function endDragging(node: BoardNode | null) { + if (props.draggingNode.value != null && props.draggingNode.value === node) { + props.draggingNode.value.position.x += Math.round(dragged.value.x / 25) * 25; + props.draggingNode.value.position.y += Math.round(dragged.value.y / 25) * 25; const nodes = props.nodes.value; - nodes.push(nodes.splice(nodes.indexOf(draggingNode.value), 1)[0]); + nodes.push(nodes.splice(nodes.indexOf(props.draggingNode.value), 1)[0]); - if (receivingNode.value) { - props.types.value[receivingNode.value.type].onDrop?.( - receivingNode.value, - draggingNode.value + if (props.receivingNode.value) { + props.types.value[props.receivingNode.value.type].onDrop?.( + props.receivingNode.value, + props.draggingNode.value ); } - dragging.value = null; + props.setDraggingNode.value(null); } else if (!hasDragged.value) { props.state.value.selectedNode = null; props.state.value.selectedAction = null; diff --git a/src/features/boards/BoardNode.vue b/src/features/boards/BoardNode.vue index ffc2cb6..e5e292d 100644 --- a/src/features/boards/BoardNode.vue +++ b/src/features/boards/BoardNode.vue @@ -153,7 +153,7 @@ const sqrtTwo = Math.sqrt(2); const _props = defineProps<{ node: BoardNode; nodeType: GenericNodeType; - dragging?: BoardNode; + dragging: BoardNode | null; dragged?: { x: number; y: number; @@ -165,8 +165,8 @@ const _props = defineProps<{ }>(); const props = toRefs(_props); const emit = defineEmits<{ - (e: "mouseDown", event: MouseEvent | TouchEvent, node: number, isDraggable: boolean): void; - (e: "endDragging", node: number): void; + (e: "mouseDown", event: MouseEvent | TouchEvent, node: BoardNode, isDraggable: boolean): void; + (e: "endDragging", node: BoardNode): void; (e: "clickAction", actionId: string): void; }>(); @@ -178,7 +178,7 @@ const isDraggable = computed(() => watch(isDraggable, value => { const node = unref(props.node); if (unref(props.dragging) === node && !value) { - emit("endDragging", node.id); + emit("endDragging", node); } }); @@ -261,12 +261,12 @@ const style = computed(() => getNodeProperty(props.nodeType.value.style, unref(p const classes = computed(() => getNodeProperty(props.nodeType.value.classes, unref(props.node))); function mouseDown(e: MouseEvent | TouchEvent) { - emit("mouseDown", e, props.node.value.id, isDraggable.value); + emit("mouseDown", e, props.node.value, isDraggable.value); } function mouseUp(e: MouseEvent | TouchEvent) { if (!props.hasDragged?.value) { - emit("endDragging", props.node.value.id); + emit("endDragging", props.node.value); props.nodeType.value.onClick?.(props.node.value); e.stopPropagation(); } diff --git a/src/features/boards/board.ts b/src/features/boards/board.ts index a972f9f..d6ac58a 100644 --- a/src/features/boards/board.ts +++ b/src/features/boards/board.ts @@ -258,6 +258,10 @@ export interface BaseBoard { selectedNode: Ref; /** The currently selected action, if any. */ selectedAction: Ref; + /** The currently being dragged node, if any. */ + draggingNode: Ref; + /** If dragging a node, the node it's currently being hovered over, if any. */ + receivingNode: Ref; /** The current mouse position, if over the board. */ mousePosition: Ref<{ x: number; y: number } | null>; /** A symbol that helps identify features of the same type. */ @@ -372,6 +376,8 @@ export function createBoard( return null; }); } + board.draggingNode = ref(null); + board.receivingNode = ref(null); processComputable(board as T, "visibility"); setDefault(board, "visibility", Visibility.Visible); processComputable(board as T, "width"); @@ -427,6 +433,15 @@ export function createBoard( } } + function setDraggingNode(node: BoardNode | null) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + board.draggingNode!.value = node; + } + function setReceivingNode(node: BoardNode | null) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + board.receivingNode!.value = node; + } + board[GatherProps] = function (this: GenericBoard) { const { nodes, @@ -440,7 +455,9 @@ export function createBoard( links, selectedAction, selectedNode, - mousePosition + mousePosition, + draggingNode, + receivingNode } = this; return { nodes, @@ -454,7 +471,11 @@ export function createBoard( links, selectedAction, selectedNode, - mousePosition + mousePosition, + draggingNode, + receivingNode, + setDraggingNode, + setReceivingNode }; };