diff --git a/packages/web/src/designer/Designer.svelte b/packages/web/src/designer/Designer.svelte index 3b82b5b03..7e826740c 100644 --- a/packages/web/src/designer/Designer.svelte +++ b/packages/web/src/designer/Designer.svelte @@ -41,6 +41,8 @@ import { GraphDefinition, GraphLayout } from './GraphLayout'; import { saveFileToDisk } from '../utility/exportElectronFile'; import { apiCall } from '../utility/api'; + import moveDrag from '../utility/moveDrag'; + import { rectanglesHaveIntersection } from './designerMath'; export let value; export let onChange; @@ -55,6 +57,8 @@ let domCanvas; let canvasWidth = 3000; let canvasHeight = 3000; + let dragStartPoint = null; + let dragCurrentPoint = null; const sourceDragColumn$ = writable(null); const targetDragColumn$ = writable(null); @@ -542,6 +546,41 @@ tick().then(recomputeReferencePositions); }; + const handleMoveStart = (x, y) => { + dragStartPoint = { x, y }; + }; + const handleMove = (dx, dy, x, y) => { + dragCurrentPoint = { x, y }; + }; + const handleMoveEnd = (x, y) => { + if (dragStartPoint && dragCurrentPoint) { + const bounds = { + left: Math.min(dragStartPoint.x, dragCurrentPoint.x), + right: Math.max(dragStartPoint.x, dragCurrentPoint.x), + top: Math.min(dragStartPoint.y, dragCurrentPoint.y), + bottom: Math.max(dragStartPoint.y, dragCurrentPoint.y), + }; + + callChange( + current => ({ + ...current, + tables: (current.tables || []).map(x => { + const domTable = domTables[x.designerId] as any; + const rect = domTable.getRect(); + return { + ...x, + isSelectedTable: rectanglesHaveIntersection(rect, bounds), + }; + }), + }), + true + ); + } + + dragStartPoint = null; + dragCurrentPoint = null; + }; + function recomputeReferencePositions() { for (const ref of Object.values(referenceRefs) as any[]) { if (ref) ref.recomputePosition(); @@ -651,6 +690,7 @@ ); } }} + use:moveDrag={settings?.canSelectTables ? [handleMoveStart, handleMove, handleMoveEnd] : null} > {#each references || [] as ref (ref.designerId)} {/each} + + {#if dragStartPoint && dragCurrentPoint} + + + + {/if} diff --git a/packages/web/src/designer/DesignerTable.svelte b/packages/web/src/designer/DesignerTable.svelte index 5da1c193c..7fc5a1f6a 100644 --- a/packages/web/src/designer/DesignerTable.svelte +++ b/packages/web/src/designer/DesignerTable.svelte @@ -7,6 +7,7 @@ import contextMenu from '../utility/contextMenu'; import moveDrag from '../utility/moveDrag'; import ColumnLine from './ColumnLine.svelte'; +import { rectanglesHaveIntersection } from './designerMath'; import DomTableRef from './DomTableRef'; export let table; diff --git a/packages/web/src/designer/designerMath.ts b/packages/web/src/designer/designerMath.ts index 348604105..caf11e8e8 100644 --- a/packages/web/src/designer/designerMath.ts +++ b/packages/web/src/designer/designerMath.ts @@ -1,5 +1,6 @@ -import { arrayDifference } from 'interval-operations'; +import { intersection, arrayDifference } from 'interval-operations'; import _ from 'lodash'; + export interface IPoint { x: number; y: number; @@ -101,6 +102,13 @@ export function rectangleIntersectArea(rect1: IBoxBounds, rect2: IBoxBounds) { return x_overlap * y_overlap; } +export function rectanglesHaveIntersection(rect1: IBoxBounds, rect2: IBoxBounds) { + const xIntersection = intersection([rect1.left, rect1.right], [rect2.left, rect2.right]); + const yIntersection = intersection([rect1.top, rect1.bottom], [rect2.top, rect2.bottom]); + + return !!xIntersection && !!yIntersection; +} + export class Vector2D { constructor(public x: number, public y: number) {} diff --git a/packages/web/src/utility/moveDrag.ts b/packages/web/src/utility/moveDrag.ts index c94257bfb..eef0c1e6c 100644 --- a/packages/web/src/utility/moveDrag.ts +++ b/packages/web/src/utility/moveDrag.ts @@ -1,17 +1,25 @@ export default function moveDrag(node, dragEvents) { if (!dragEvents) return; - + const [onStart, onMove, onEnd] = dragEvents; let startX = null; let startY = null; + let clientX = null; + let clientY = null; + const handleMoveDown = e => { if (e.button != 0) return; + + const clientRect = node.getBoundingClientRect(); + clientX = clientRect.left; + clientY = clientRect.top; + startX = e.clientX; startY = e.clientY; document.addEventListener('mousemove', handleMoveMove, true); document.addEventListener('mouseup', handleMoveEnd, true); - onStart(); + onStart(e.clientX - clientX, e.clientY - clientY); }; const handleMoveMove = e => { @@ -21,7 +29,7 @@ export default function moveDrag(node, dragEvents) { const diffY = e.clientY - startY; startY = e.clientY; - onMove(diffX, diffY); + onMove(diffX, diffY, e.clientX - clientX, e.clientY - clientY); }; const handleMoveEnd = e => { e.preventDefault(); @@ -29,7 +37,7 @@ export default function moveDrag(node, dragEvents) { startY = null; document.removeEventListener('mousemove', handleMoveMove, true); document.removeEventListener('mouseup', handleMoveEnd, true); - onEnd(); + onEnd(e.clientX - clientX, e.clientY - clientY); }; node.addEventListener('mousedown', handleMoveDown);