mirror of
https://github.com/drawdb-io/drawdb.git
synced 2025-07-18 10:11:24 +00:00
Panning with middle click, persistent bulk selection (#498)
* panning with middle click, persistant bulk selection * remove unused variables
This commit is contained in:
@@ -5,8 +5,6 @@ import {
|
||||
Constraint,
|
||||
darkBgTheme,
|
||||
ObjectType,
|
||||
tableFieldHeight,
|
||||
tableHeaderHeight,
|
||||
gridSize,
|
||||
gridCircleRadius,
|
||||
} from "../../data/constants";
|
||||
@@ -29,7 +27,7 @@ import {
|
||||
} from "../../hooks";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useEventListener } from "usehooks-ts";
|
||||
import { areFieldsCompatible } from "../../utils/utils";
|
||||
import { areFieldsCompatible, getTableHeight } from "../../utils/utils";
|
||||
import { getRectFromEndpoints, isInsideRect } from "../../utils/rect";
|
||||
import { noteWidth, State } from "../../data/constants";
|
||||
|
||||
@@ -117,8 +115,7 @@ export default function Canvas() {
|
||||
x: table.x,
|
||||
y: table.y,
|
||||
width: settings.tableWidth,
|
||||
height:
|
||||
table.fields.length * tableFieldHeight + tableHeaderHeight + 7,
|
||||
height: getTableHeight(table),
|
||||
},
|
||||
rect,
|
||||
)
|
||||
@@ -230,14 +227,7 @@ export default function Canvas() {
|
||||
prevCoords = { prevX: note.x, prevY: note.y };
|
||||
}
|
||||
|
||||
if (locked) {
|
||||
setPanning({
|
||||
isPanning: true,
|
||||
panStart: transform.pan,
|
||||
cursorStart: pointer.spaces.screen,
|
||||
});
|
||||
pointer.setStyle("grabbing");
|
||||
} else {
|
||||
if (!locked) {
|
||||
setDragging((prev) => ({
|
||||
...prev,
|
||||
id,
|
||||
@@ -274,6 +264,21 @@ export default function Canvas() {
|
||||
|
||||
if (!e.isPrimary) return;
|
||||
|
||||
if (panning.isPanning) {
|
||||
setTransform((prev) => ({
|
||||
...prev,
|
||||
pan: {
|
||||
x:
|
||||
panning.panStart.x +
|
||||
(panning.cursorStart.x - pointer.spaces.screen.x) / transform.zoom,
|
||||
y:
|
||||
panning.panStart.y +
|
||||
(panning.cursorStart.y - pointer.spaces.screen.y) / transform.zoom,
|
||||
},
|
||||
}));
|
||||
return;
|
||||
}
|
||||
|
||||
const isDragging =
|
||||
dragging.element !== ObjectType.NONE && dragging.id !== null;
|
||||
|
||||
@@ -300,26 +305,38 @@ export default function Canvas() {
|
||||
} else if (
|
||||
dragging.element !== ObjectType.NONE &&
|
||||
dragging.id !== null &&
|
||||
bulkSelectedElements.length
|
||||
bulkSelectedElements.length &&
|
||||
bulkSelectedElements.some(
|
||||
(element) =>
|
||||
element.id === dragging.id && element.type === dragging.element,
|
||||
)
|
||||
) {
|
||||
for (const element of bulkSelectedElements) {
|
||||
if (element.type === ObjectType.TABLE) {
|
||||
const { x, y } = tables.find((e) => e.id === element.id);
|
||||
const table = tables.find((e) => e.id === element.id);
|
||||
if (table.locked) continue;
|
||||
const { x, y } = table;
|
||||
updateTable(element.id, {
|
||||
x: x + deltaX,
|
||||
y: y + deltaY,
|
||||
});
|
||||
}
|
||||
if (element.type === ObjectType.AREA) {
|
||||
const area = areas[element.id];
|
||||
if (area.locked) continue;
|
||||
const { x, y } = area;
|
||||
updateArea(element.id, {
|
||||
x: areas[element.id].x + deltaX,
|
||||
y: areas[element.id].y + deltaY,
|
||||
x: x + deltaX,
|
||||
y: y + deltaY,
|
||||
});
|
||||
}
|
||||
if (element.type === ObjectType.NOTE) {
|
||||
const note = notes[element.id];
|
||||
if (note.locked) continue;
|
||||
const { x, y } = note;
|
||||
updateNote(element.id, {
|
||||
x: notes[element.id].x + deltaX,
|
||||
y: notes[element.id].y + deltaY,
|
||||
x: x + deltaX,
|
||||
y: y + deltaY,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -329,25 +346,6 @@ export default function Canvas() {
|
||||
prevX: finalX,
|
||||
prevY: finalY,
|
||||
}));
|
||||
} else if (
|
||||
panning.isPanning &&
|
||||
dragging.element === ObjectType.NONE &&
|
||||
areaResize.id === -1
|
||||
) {
|
||||
if (!settings.panning) {
|
||||
return;
|
||||
}
|
||||
setTransform((prev) => ({
|
||||
...prev,
|
||||
pan: {
|
||||
x:
|
||||
panning.panStart.x +
|
||||
(panning.cursorStart.x - pointer.spaces.screen.x) / transform.zoom,
|
||||
y:
|
||||
panning.panStart.y +
|
||||
(panning.cursorStart.y - pointer.spaces.screen.y) / transform.zoom,
|
||||
},
|
||||
}));
|
||||
} else if (dragging.element === ObjectType.TABLE && dragging.id !== null) {
|
||||
const table = tables.find((t) => t.id === dragging.id);
|
||||
if (table.locked) return;
|
||||
@@ -430,7 +428,10 @@ export default function Canvas() {
|
||||
)
|
||||
return;
|
||||
|
||||
if (!settings.panning) {
|
||||
const isMouseLeftButton = e.button === 0;
|
||||
const isMouseMiddleButton = e.button === 1;
|
||||
|
||||
if (isMouseLeftButton) {
|
||||
setBulkSelectRectPts({
|
||||
x1: pointer.spaces.diagram.x,
|
||||
y1: pointer.spaces.diagram.y,
|
||||
@@ -439,7 +440,7 @@ export default function Canvas() {
|
||||
show: true,
|
||||
});
|
||||
pointer.setStyle("crosshair");
|
||||
} else {
|
||||
} else if (isMouseMiddleButton) {
|
||||
setPanning({
|
||||
isPanning: true,
|
||||
panStart: transform.pan,
|
||||
@@ -488,6 +489,8 @@ export default function Canvas() {
|
||||
|
||||
if (!e.isPrimary) return;
|
||||
|
||||
let bulkMoved = false;
|
||||
|
||||
if (coordsDidUpdate({ id: dragging.id, type: dragging.element })) {
|
||||
if (bulkSelectedElements.length) {
|
||||
setUndoStack((prev) => [
|
||||
@@ -505,12 +508,7 @@ export default function Canvas() {
|
||||
})),
|
||||
},
|
||||
]);
|
||||
setSelectedElement((prev) => ({
|
||||
...prev,
|
||||
element: ObjectType.NONE,
|
||||
id: -1,
|
||||
open: false,
|
||||
}));
|
||||
bulkMoved = true;
|
||||
} else {
|
||||
const element = getElement({
|
||||
id: dragging.id,
|
||||
@@ -553,18 +551,13 @@ export default function Canvas() {
|
||||
y2: pointer.spaces.diagram.y,
|
||||
show: false,
|
||||
}));
|
||||
collectSelectedElements();
|
||||
if (!bulkMoved) {
|
||||
collectSelectedElements();
|
||||
}
|
||||
}
|
||||
|
||||
if (panning.isPanning && didPan()) {
|
||||
setSaveState(State.SAVING);
|
||||
setSelectedElement((prev) => ({
|
||||
...prev,
|
||||
element: ObjectType.NONE,
|
||||
id: -1,
|
||||
open: false,
|
||||
}));
|
||||
setBulkSelectedElements([]);
|
||||
}
|
||||
setPanning((old) => ({ ...old, isPanning: false }));
|
||||
pointer.setStyle("default");
|
||||
|
@@ -1396,15 +1396,6 @@ export default function ControlPanel({
|
||||
function: () =>
|
||||
setSettings((prev) => ({ ...prev, autosave: !prev.autosave })),
|
||||
},
|
||||
panning: {
|
||||
state: settings.panning ? (
|
||||
<i className="bi bi-toggle-on" />
|
||||
) : (
|
||||
<i className="bi bi-toggle-off" />
|
||||
),
|
||||
function: () =>
|
||||
setSettings((prev) => ({ ...prev, panning: !prev.panning })),
|
||||
},
|
||||
table_width: {
|
||||
function: () => setModal(MODAL.TABLE_WIDTH),
|
||||
},
|
||||
@@ -1603,23 +1594,6 @@ export default function ControlPanel({
|
||||
<i className="fa-solid fa-magnifying-glass-minus" />
|
||||
</button>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
content={settings.panning ? t("multiselect") : t("panning")}
|
||||
position="bottom"
|
||||
>
|
||||
<button
|
||||
className="py-1 px-2 hover-2 rounded-sm text-lg w-10"
|
||||
onClick={() =>
|
||||
setSettings((prev) => ({ ...prev, panning: !prev.panning }))
|
||||
}
|
||||
>
|
||||
{settings.panning ? (
|
||||
<i className="fa-solid fa-expand" />
|
||||
) : (
|
||||
<i className="fa-regular fa-hand"></i>
|
||||
)}
|
||||
</button>
|
||||
</Tooltip>
|
||||
<Divider layout="vertical" margin="8px" />
|
||||
<Tooltip content={t("undo")} position="bottom">
|
||||
<button
|
||||
|
@@ -9,7 +9,6 @@ const defaultSettings = {
|
||||
showDataTypes: true,
|
||||
mode: "light",
|
||||
autosave: true,
|
||||
panning: true,
|
||||
showCardinality: true,
|
||||
showRelationshipLabels: true,
|
||||
tableWidth: tableWidth,
|
||||
|
Reference in New Issue
Block a user