diagram: select more nodes by drag rectangke

This commit is contained in:
Jan Prochazka
2022-01-20 12:52:20 +01:00
parent a530a353b6
commit c0891af5c3
4 changed files with 96 additions and 5 deletions

View File

@@ -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)}
<svelte:component
@@ -700,6 +740,20 @@
/>
{/each}
</div>
{#if dragStartPoint && dragCurrentPoint}
<svg class="drag-rect">
<polyline
points={`
${dragStartPoint.x},${dragStartPoint.y}
${dragStartPoint.x},${dragCurrentPoint.y}
${dragCurrentPoint.x},${dragCurrentPoint.y}
${dragCurrentPoint.x},${dragStartPoint.y}
${dragStartPoint.x},${dragStartPoint.y}
`}
/>
</svg>
{/if}
</div>
<style>
@@ -715,4 +769,24 @@
.canvas {
position: relative;
}
svg.drag-rect {
visibility: hidden;
pointer-events: none;
}
:global(.dbgate-screen) svg.drag-rect {
visibility: visible;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
}
:global(.dbgate-screen) svg.drag-rect polyline {
fill: none;
stroke: var(--theme-bg-4);
stroke-width: 2;
}
</style>

View File

@@ -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;

View File

@@ -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) {}

View File

@@ -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);