mirror of
https://github.com/drawdb-io/drawdb.git
synced 2025-09-01 10:25:13 +00:00
Add ctrl select support (#527)
* Add ctrl select support * fix the issue with clicking on overlapping objects * simplify the code, add meta to ctrl for macos * fix lock unlock with command on macos
This commit is contained in:
@@ -48,11 +48,47 @@ export default function Area({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const lockUnlockArea = () => {
|
const lockUnlockArea = (e) => {
|
||||||
setBulkSelectedElements((prev) =>
|
const locking = !data.locked;
|
||||||
prev.filter((el) => el.id !== data.id || el.type !== ObjectType.AREA),
|
updateArea(data.id, { locked: locking });
|
||||||
);
|
|
||||||
updateArea(data.id, { locked: !data.locked });
|
const lockArea = () => {
|
||||||
|
setSelectedElement({
|
||||||
|
...selectedElement,
|
||||||
|
element: ObjectType.NONE,
|
||||||
|
id: -1,
|
||||||
|
open: false,
|
||||||
|
});
|
||||||
|
setBulkSelectedElements((prev) =>
|
||||||
|
prev.filter((el) => el.id !== data.id || el.type !== ObjectType.AREA),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const unlockArea = () => {
|
||||||
|
const elementInBulk = {
|
||||||
|
id: data.id,
|
||||||
|
type: ObjectType.AREA,
|
||||||
|
initialCoords: { x: data.x, y: data.y },
|
||||||
|
currentCoords: { x: data.x, y: data.y },
|
||||||
|
};
|
||||||
|
if (e.ctrlKey || e.metaKey) {
|
||||||
|
setBulkSelectedElements((prev) => [...prev, elementInBulk]);
|
||||||
|
} else {
|
||||||
|
setBulkSelectedElements([elementInBulk]);
|
||||||
|
}
|
||||||
|
setSelectedElement((prev) => ({
|
||||||
|
...prev,
|
||||||
|
element: ObjectType.AREA,
|
||||||
|
id: data.id,
|
||||||
|
open: false,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
if (locking) {
|
||||||
|
lockArea();
|
||||||
|
} else {
|
||||||
|
unlockArea();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const edit = () => {
|
const edit = () => {
|
||||||
|
@@ -29,7 +29,7 @@ import { useTranslation } from "react-i18next";
|
|||||||
import { useEventListener } from "usehooks-ts";
|
import { useEventListener } from "usehooks-ts";
|
||||||
import { areFieldsCompatible, getTableHeight } from "../../utils/utils";
|
import { areFieldsCompatible, getTableHeight } from "../../utils/utils";
|
||||||
import { getRectFromEndpoints, isInsideRect } from "../../utils/rect";
|
import { getRectFromEndpoints, isInsideRect } from "../../utils/rect";
|
||||||
import { noteWidth, State } from "../../data/constants";
|
import { State, noteWidth } from "../../data/constants";
|
||||||
|
|
||||||
export default function Canvas() {
|
export default function Canvas() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -89,145 +89,170 @@ export default function Canvas() {
|
|||||||
width: 0,
|
width: 0,
|
||||||
height: 0,
|
height: 0,
|
||||||
});
|
});
|
||||||
const [bulkSelectRectPts, setBulkSelectRectPts] = useState({
|
const [bulkSelectRect, setBulkSelectRect] = useState({
|
||||||
x1: 0,
|
x1: 0,
|
||||||
y1: 0,
|
y1: 0,
|
||||||
x2: 0,
|
x2: 0,
|
||||||
y2: 0,
|
y2: 0,
|
||||||
show: false,
|
show: false,
|
||||||
|
ctrlKey: false,
|
||||||
|
metaKey: false,
|
||||||
});
|
});
|
||||||
|
// this is used to store the element that is clicked on
|
||||||
|
// at the moment, and shouldn't be a part of the state
|
||||||
|
let elementPointerDown = null;
|
||||||
|
|
||||||
|
const isSameElement = (el1, el2) => {
|
||||||
|
return el1.id === el2.id && el1.type === el2.type;
|
||||||
|
};
|
||||||
|
|
||||||
const collectSelectedElements = () => {
|
const collectSelectedElements = () => {
|
||||||
const rect = getRectFromEndpoints(bulkSelectRectPts);
|
const rect = getRectFromEndpoints(bulkSelectRect);
|
||||||
|
|
||||||
const elements = [];
|
const elements = [];
|
||||||
|
const shouldAddElement = (elementRect, element) => {
|
||||||
|
// if ctrl key is pressed, only add the elements that are not already selected
|
||||||
|
// can theoretically be optimized later if the selected elements is
|
||||||
|
// a map from id to element (after the ids are made unique)
|
||||||
|
return (
|
||||||
|
isInsideRect(elementRect, rect) &&
|
||||||
|
((!bulkSelectRect.ctrlKey && !bulkSelectRect.metaKey) ||
|
||||||
|
!bulkSelectedElements.some((el) => isSameElement(el, element)))
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
tables.forEach((table) => {
|
tables.forEach((table) => {
|
||||||
if (table.locked) return;
|
if (table.locked) return;
|
||||||
|
|
||||||
if (
|
const element = {
|
||||||
isInsideRect(
|
id: table.id,
|
||||||
{
|
type: ObjectType.TABLE,
|
||||||
x: table.x,
|
currentCoords: { x: table.x, y: table.y },
|
||||||
y: table.y,
|
initialCoords: { x: table.x, y: table.y },
|
||||||
width: settings.tableWidth,
|
};
|
||||||
height: getTableHeight(table),
|
const tableRect = {
|
||||||
},
|
x: table.x,
|
||||||
rect,
|
y: table.y,
|
||||||
)
|
width: settings.tableWidth,
|
||||||
) {
|
height: getTableHeight(table),
|
||||||
elements.push({
|
};
|
||||||
id: table.id,
|
if (shouldAddElement(tableRect, element)) {
|
||||||
type: ObjectType.TABLE,
|
elements.push(element);
|
||||||
currentCoords: { x: table.x, y: table.y },
|
|
||||||
initialCoords: { x: table.x, y: table.y },
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
areas.forEach((area) => {
|
areas.forEach((area) => {
|
||||||
if (area.locked) return;
|
if (area.locked) return;
|
||||||
|
|
||||||
if (
|
const element = {
|
||||||
isInsideRect(
|
id: area.id,
|
||||||
{
|
type: ObjectType.AREA,
|
||||||
x: area.x,
|
currentCoords: { x: area.x, y: area.y },
|
||||||
y: area.y,
|
initialCoords: { x: area.x, y: area.y },
|
||||||
width: area.width,
|
};
|
||||||
height: area.height,
|
const areaRect = {
|
||||||
},
|
x: area.x,
|
||||||
rect,
|
y: area.y,
|
||||||
)
|
width: area.width,
|
||||||
) {
|
height: area.height,
|
||||||
elements.push({
|
};
|
||||||
id: area.id,
|
if (shouldAddElement(areaRect, element)) {
|
||||||
type: ObjectType.AREA,
|
elements.push(element);
|
||||||
currentCoords: { x: area.x, y: area.y },
|
|
||||||
initialCoords: { x: area.x, y: area.y },
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
notes.forEach((note) => {
|
notes.forEach((note) => {
|
||||||
if (note.locked) return;
|
if (note.locked) return;
|
||||||
|
|
||||||
if (
|
const element = {
|
||||||
isInsideRect(
|
id: note.id,
|
||||||
{
|
type: ObjectType.NOTE,
|
||||||
x: note.x,
|
currentCoords: { x: note.x, y: note.y },
|
||||||
y: note.y,
|
initialCoords: { x: note.x, y: note.y },
|
||||||
width: noteWidth,
|
};
|
||||||
height: note.height,
|
const noteRect = {
|
||||||
},
|
x: note.x,
|
||||||
rect,
|
y: note.y,
|
||||||
)
|
width: noteWidth,
|
||||||
) {
|
height: note.height,
|
||||||
elements.push({
|
};
|
||||||
id: note.id,
|
if (shouldAddElement(noteRect, element)) {
|
||||||
type: ObjectType.NOTE,
|
elements.push(element);
|
||||||
currentCoords: { x: note.x, y: note.y },
|
|
||||||
initialCoords: { x: note.x, y: note.y },
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
setBulkSelectedElements(elements);
|
if (bulkSelectRect.ctrlKey || bulkSelectRect.metaKey) {
|
||||||
};
|
setBulkSelectedElements([...bulkSelectedElements, ...elements]);
|
||||||
|
} else {
|
||||||
const getElement = (element) => {
|
setBulkSelectedElements(elements);
|
||||||
switch (element.type) {
|
|
||||||
case ObjectType.TABLE:
|
|
||||||
return tables.find((t) => t.id === element.id);
|
|
||||||
case ObjectType.AREA:
|
|
||||||
return areas[element.id];
|
|
||||||
case ObjectType.NOTE:
|
|
||||||
return notes[element.id];
|
|
||||||
default:
|
|
||||||
return { x: 0, y: 0, locked: false };
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
const handlePointerDownOnElement = (e, { element, type }) => {
|
||||||
* @param {PointerEvent} e
|
|
||||||
* @param {number} id
|
|
||||||
* @param {ObjectType[keyof ObjectType]} type
|
|
||||||
*/
|
|
||||||
const handlePointerDownOnElement = (e, id, type) => {
|
|
||||||
if (selectedElement.open && !layout.sidebar) return;
|
if (selectedElement.open && !layout.sidebar) return;
|
||||||
|
|
||||||
if (!e.isPrimary) return;
|
if (!e.isPrimary) return;
|
||||||
|
|
||||||
const element = getElement({ id, type });
|
if (!element.locked || !(e.ctrlKey || e.metaKey)) {
|
||||||
|
setSelectedElement((prev) => ({
|
||||||
setSelectedElement((prev) => ({
|
...prev,
|
||||||
...prev,
|
element: type,
|
||||||
element: type,
|
id: element.id,
|
||||||
id: id,
|
open: false,
|
||||||
open: false,
|
}));
|
||||||
}));
|
}
|
||||||
|
|
||||||
if (element.locked) {
|
if (element.locked) {
|
||||||
setBulkSelectedElements([]);
|
if (!(e.ctrlKey || e.metaKey)) {
|
||||||
|
setBulkSelectedElements([]);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let newBulkSelectedElements;
|
setBulkSelectRect((prev) => ({
|
||||||
if (bulkSelectedElements.some((el) => el.id === id && el.type === type)) {
|
...prev,
|
||||||
newBulkSelectedElements = bulkSelectedElements;
|
show: false,
|
||||||
} else {
|
}));
|
||||||
newBulkSelectedElements = [
|
|
||||||
{
|
// this is the object that will be added to the bulk selected elements
|
||||||
id,
|
// if necessary
|
||||||
type,
|
const elementInBulk = {
|
||||||
currentCoords: { x: element.x, y: element.y },
|
id: element.id,
|
||||||
initialCoords: { x: element.x, y: element.y },
|
type,
|
||||||
},
|
currentCoords: { x: element.x, y: element.y },
|
||||||
];
|
initialCoords: { x: element.x, y: element.y },
|
||||||
setBulkSelectedElements(newBulkSelectedElements);
|
};
|
||||||
|
|
||||||
|
const isSelected = bulkSelectedElements.some((el) =>
|
||||||
|
isSameElement(el, elementInBulk),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (e.ctrlKey || e.metaKey) {
|
||||||
|
if (isSelected) {
|
||||||
|
if (bulkSelectedElements.length > 1) {
|
||||||
|
setBulkSelectedElements(
|
||||||
|
bulkSelectedElements.filter(
|
||||||
|
(el) => !isSameElement(el, elementInBulk),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
setSelectedElement({
|
||||||
|
...selectedElement,
|
||||||
|
element: ObjectType.NONE,
|
||||||
|
id: -1,
|
||||||
|
open: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setBulkSelectedElements([...bulkSelectedElements, elementInBulk]);
|
||||||
|
}
|
||||||
|
setDragging(notDragging);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isSelected) {
|
||||||
|
setBulkSelectedElements([elementInBulk]);
|
||||||
|
}
|
||||||
setDragging({
|
setDragging({
|
||||||
id,
|
id: element.id,
|
||||||
type,
|
type,
|
||||||
grabOffset: {
|
grabOffset: {
|
||||||
x: pointer.spaces.diagram.x - element.x,
|
x: pointer.spaces.diagram.x - element.x,
|
||||||
@@ -285,8 +310,8 @@ export default function Canvas() {
|
|||||||
y: pointer.spaces.diagram.y - dragging.grabOffset.y,
|
y: pointer.spaces.diagram.y - dragging.grabOffset.y,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { currentCoords } = bulkSelectedElements.find(
|
const { currentCoords } = bulkSelectedElements.find((el) =>
|
||||||
(el) => el.id === dragging.id && el.type === dragging.type,
|
isSameElement(el, dragging),
|
||||||
);
|
);
|
||||||
|
|
||||||
const deltaX = mainElementFinalX - currentCoords.x;
|
const deltaX = mainElementFinalX - currentCoords.x;
|
||||||
@@ -352,8 +377,8 @@ export default function Canvas() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bulkSelectRectPts.show) {
|
if (bulkSelectRect.show) {
|
||||||
setBulkSelectRectPts((prev) => ({
|
setBulkSelectRect((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
x2: pointer.spaces.diagram.x,
|
x2: pointer.spaces.diagram.x,
|
||||||
y2: pointer.spaces.diagram.y,
|
y2: pointer.spaces.diagram.y,
|
||||||
@@ -379,13 +404,18 @@ export default function Canvas() {
|
|||||||
const isMouseMiddleButton = e.button === 1;
|
const isMouseMiddleButton = e.button === 1;
|
||||||
|
|
||||||
if (isMouseLeftButton) {
|
if (isMouseLeftButton) {
|
||||||
setBulkSelectRectPts({
|
setBulkSelectRect({
|
||||||
x1: pointer.spaces.diagram.x,
|
x1: pointer.spaces.diagram.x,
|
||||||
y1: pointer.spaces.diagram.y,
|
y1: pointer.spaces.diagram.y,
|
||||||
x2: pointer.spaces.diagram.x,
|
x2: pointer.spaces.diagram.x,
|
||||||
y2: pointer.spaces.diagram.y,
|
y2: pointer.spaces.diagram.y,
|
||||||
show: true,
|
show: elementPointerDown === null || !elementPointerDown.element.locked,
|
||||||
|
ctrlKey: e.ctrlKey,
|
||||||
|
metaKey: e.metaKey,
|
||||||
});
|
});
|
||||||
|
if (elementPointerDown !== null) {
|
||||||
|
handlePointerDownOnElement(e, elementPointerDown);
|
||||||
|
}
|
||||||
pointer.setStyle("crosshair");
|
pointer.setStyle("crosshair");
|
||||||
} else if (isMouseMiddleButton) {
|
} else if (isMouseMiddleButton) {
|
||||||
setPanning({
|
setPanning({
|
||||||
@@ -459,8 +489,8 @@ export default function Canvas() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bulkSelectRectPts.show) {
|
if (bulkSelectRect.show) {
|
||||||
setBulkSelectRectPts((prev) => ({
|
setBulkSelectRect((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
x2: pointer.spaces.diagram.x,
|
x2: pointer.spaces.diagram.x,
|
||||||
y2: pointer.spaces.diagram.y,
|
y2: pointer.spaces.diagram.y,
|
||||||
@@ -661,11 +691,14 @@ export default function Canvas() {
|
|||||||
<Area
|
<Area
|
||||||
key={a.id}
|
key={a.id}
|
||||||
data={a}
|
data={a}
|
||||||
onPointerDown={(e) =>
|
|
||||||
handlePointerDownOnElement(e, a.id, ObjectType.AREA)
|
|
||||||
}
|
|
||||||
setResize={setAreaResize}
|
setResize={setAreaResize}
|
||||||
setInitDimensions={setAreaInitDimensions}
|
setInitDimensions={setAreaInitDimensions}
|
||||||
|
onPointerDown={() => {
|
||||||
|
elementPointerDown = {
|
||||||
|
element: a,
|
||||||
|
type: ObjectType.AREA,
|
||||||
|
};
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
{relationships.map((e, i) => (
|
{relationships.map((e, i) => (
|
||||||
@@ -678,9 +711,12 @@ export default function Canvas() {
|
|||||||
setHoveredTable={setHoveredTable}
|
setHoveredTable={setHoveredTable}
|
||||||
handleGripField={handleGripField}
|
handleGripField={handleGripField}
|
||||||
setLinkingLine={setLinkingLine}
|
setLinkingLine={setLinkingLine}
|
||||||
onPointerDown={(e) =>
|
onPointerDown={() => {
|
||||||
handlePointerDownOnElement(e, table.id, ObjectType.TABLE)
|
elementPointerDown = {
|
||||||
}
|
element: table,
|
||||||
|
type: ObjectType.TABLE,
|
||||||
|
};
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
{linking && (
|
{linking && (
|
||||||
@@ -695,14 +731,17 @@ export default function Canvas() {
|
|||||||
<Note
|
<Note
|
||||||
key={n.id}
|
key={n.id}
|
||||||
data={n}
|
data={n}
|
||||||
onPointerDown={(e) =>
|
onPointerDown={() => {
|
||||||
handlePointerDownOnElement(e, n.id, ObjectType.NOTE)
|
elementPointerDown = {
|
||||||
}
|
element: n,
|
||||||
|
type: ObjectType.NOTE,
|
||||||
|
};
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
{bulkSelectRectPts.show && (
|
{bulkSelectRect.show && (
|
||||||
<rect
|
<rect
|
||||||
{...getRectFromEndpoints(bulkSelectRectPts)}
|
{...getRectFromEndpoints(bulkSelectRect)}
|
||||||
stroke="grey"
|
stroke="grey"
|
||||||
fill="grey"
|
fill="grey"
|
||||||
fillOpacity={0.15}
|
fillOpacity={0.15}
|
||||||
|
@@ -100,11 +100,47 @@ export default function Note({ data, onPointerDown }) {
|
|||||||
setRedoStack([]);
|
setRedoStack([]);
|
||||||
};
|
};
|
||||||
|
|
||||||
const lockUnlockNote = () => {
|
const lockUnlockNote = (e) => {
|
||||||
setBulkSelectedElements((prev) =>
|
const locking = !data.locked;
|
||||||
prev.filter((el) => el.id !== data.id || el.type !== ObjectType.NOTE),
|
updateNote(data.id, { locked: locking });
|
||||||
);
|
|
||||||
updateNote(data.id, { locked: !data.locked });
|
const lockNote = () => {
|
||||||
|
setSelectedElement({
|
||||||
|
...selectedElement,
|
||||||
|
element: ObjectType.NONE,
|
||||||
|
id: -1,
|
||||||
|
open: false,
|
||||||
|
});
|
||||||
|
setBulkSelectedElements((prev) =>
|
||||||
|
prev.filter((el) => el.id !== data.id || el.type !== ObjectType.NOTE),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const unlockNote = () => {
|
||||||
|
const elementInBulk = {
|
||||||
|
id: data.id,
|
||||||
|
type: ObjectType.NOTE,
|
||||||
|
initialCoords: { x: data.x, y: data.y },
|
||||||
|
currentCoords: { x: data.x, y: data.y },
|
||||||
|
};
|
||||||
|
if (e.ctrlKey || e.metaKey) {
|
||||||
|
setBulkSelectedElements((prev) => [...prev, elementInBulk]);
|
||||||
|
} else {
|
||||||
|
setBulkSelectedElements([elementInBulk]);
|
||||||
|
}
|
||||||
|
setSelectedElement((prev) => ({
|
||||||
|
...prev,
|
||||||
|
element: ObjectType.NOTE,
|
||||||
|
id: data.id,
|
||||||
|
open: false,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
if (locking) {
|
||||||
|
lockNote();
|
||||||
|
} else {
|
||||||
|
unlockNote();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const edit = () => {
|
const edit = () => {
|
||||||
|
@@ -24,16 +24,15 @@ import { isRtl } from "../../i18n/utils/rtl";
|
|||||||
import i18n from "../../i18n/i18n";
|
import i18n from "../../i18n/i18n";
|
||||||
import { getTableHeight } from "../../utils/utils";
|
import { getTableHeight } from "../../utils/utils";
|
||||||
|
|
||||||
export default function Table(props) {
|
export default function Table({
|
||||||
|
tableData,
|
||||||
|
onPointerDown,
|
||||||
|
setHoveredTable,
|
||||||
|
handleGripField,
|
||||||
|
setLinkingLine,
|
||||||
|
}) {
|
||||||
const [hoveredField, setHoveredField] = useState(null);
|
const [hoveredField, setHoveredField] = useState(null);
|
||||||
const { database } = useDiagram();
|
const { database } = useDiagram();
|
||||||
const {
|
|
||||||
tableData,
|
|
||||||
onPointerDown,
|
|
||||||
setHoveredTable,
|
|
||||||
handleGripField,
|
|
||||||
setLinkingLine,
|
|
||||||
} = props;
|
|
||||||
const { layout } = useLayout();
|
const { layout } = useLayout();
|
||||||
const { deleteTable, deleteField, updateTable } = useDiagram();
|
const { deleteTable, deleteField, updateTable } = useDiagram();
|
||||||
const { settings } = useSettings();
|
const { settings } = useSettings();
|
||||||
@@ -62,11 +61,49 @@ export default function Table(props) {
|
|||||||
);
|
);
|
||||||
}, [selectedElement, tableData, bulkSelectedElements]);
|
}, [selectedElement, tableData, bulkSelectedElements]);
|
||||||
|
|
||||||
const lockUnlockTable = () => {
|
const lockUnlockTable = (e) => {
|
||||||
setBulkSelectedElements((prev) =>
|
const locking = !tableData.locked;
|
||||||
prev.filter((el) => el.id !== tableData.id || el.type !== ObjectType.TABLE),
|
updateTable(tableData.id, { locked: locking });
|
||||||
);
|
|
||||||
updateTable(tableData.id, { locked: !tableData.locked });
|
const lockTable = () => {
|
||||||
|
setSelectedElement({
|
||||||
|
...selectedElement,
|
||||||
|
element: ObjectType.NONE,
|
||||||
|
id: -1,
|
||||||
|
open: false,
|
||||||
|
});
|
||||||
|
setBulkSelectedElements((prev) =>
|
||||||
|
prev.filter(
|
||||||
|
(el) => el.id !== tableData.id || el.type !== ObjectType.TABLE,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const unlockTable = () => {
|
||||||
|
const elementInBulk = {
|
||||||
|
id: tableData.id,
|
||||||
|
type: ObjectType.TABLE,
|
||||||
|
initialCoords: { x: tableData.x, y: tableData.y },
|
||||||
|
currentCoords: { x: tableData.x, y: tableData.y },
|
||||||
|
};
|
||||||
|
if (e.ctrlKey || e.metaKey) {
|
||||||
|
setBulkSelectedElements((prev) => [...prev, elementInBulk]);
|
||||||
|
} else {
|
||||||
|
setBulkSelectedElements([elementInBulk]);
|
||||||
|
}
|
||||||
|
setSelectedElement((prev) => ({
|
||||||
|
...prev,
|
||||||
|
element: ObjectType.TABLE,
|
||||||
|
id: tableData.id,
|
||||||
|
open: false,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
if (locking) {
|
||||||
|
lockTable();
|
||||||
|
} else {
|
||||||
|
unlockTable();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const openEditor = () => {
|
const openEditor = () => {
|
||||||
|
Reference in New Issue
Block a user