Panning with middle click, persistent bulk selection (#498)

* panning with middle click, persistant bulk selection

* remove unused variables
This commit is contained in:
Karen Mkrtumyan
2025-06-21 19:48:15 +04:00
committed by GitHub
parent e56f6409ff
commit 3cdf908ffd
3 changed files with 47 additions and 81 deletions

View File

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

View File

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

View File

@@ -9,7 +9,6 @@ const defaultSettings = {
showDataTypes: true,
mode: "light",
autosave: true,
panning: true,
showCardinality: true,
showRelationshipLabels: true,
tableWidth: tableWidth,