loopLock -> polygon

This commit is contained in:
dwelle 2025-05-08 23:04:39 +02:00
parent 35fa4fc041
commit 74dcaeebda
12 changed files with 38 additions and 37 deletions

View File

@ -1313,14 +1313,14 @@ export class LinearElementEditor {
element.points[element.points.length - 1];
// break polygon if deleting start/end point
if (isLineElement(element) && element.loopLock) {
if (isLineElement(element) && element.polygon) {
if (
pointIndices.includes(0) ||
(pointIndices.includes(element.points.length - 1) &&
// don't disable polygon if cleaning up uncommitted point
!isUncommittedPoint)
) {
app.scene.mutateElement(element, { loopLock: false });
app.scene.mutateElement(element, { polygon: false });
}
}
@ -1328,7 +1328,7 @@ export class LinearElementEditor {
return !pointIndices.includes(idx);
});
if (isUncommittedPoint && isLineElement(element) && element.loopLock) {
if (isUncommittedPoint && isLineElement(element) && element.polygon) {
nextPoints[0] = pointFrom(
nextPoints[nextPoints.length - 1][0],
nextPoints[nextPoints.length - 1][1],
@ -1357,7 +1357,7 @@ export class LinearElementEditor {
) {
const nextPoints = [...element.points, ...addedPoints];
if (isLineElement(element) && element.loopLock) {
if (isLineElement(element) && element.polygon) {
nextPoints[0] = pointFrom(
nextPoints[nextPoints.length - 1][0],
nextPoints[nextPoints.length - 1][1],
@ -1391,7 +1391,7 @@ export class LinearElementEditor {
const { points } = element;
// Handle loop lock behavior
if (isLineElement(element) && element.loopLock) {
if (isLineElement(element) && element.polygon) {
const firstPointUpdate = pointUpdates.get(0);
const lastPointUpdate = pointUpdates.get(points.length - 1);

View File

@ -475,7 +475,7 @@ export const newLinearElement = (
if (isLineElement(element)) {
const lineElement: NonDeleted<ExcalidrawLineElement> = {
...element,
loopLock: false,
polygon: false,
};
return lineElement;

View File

@ -426,7 +426,7 @@ export const toggleLinePolygonState = (
// TODO: satisfies ElementUpdate<ExcalidrawLineElement>
const ret = {
loopLock: nextPolygonState,
polygon: nextPolygonState,
points: updatedPoints,
};

View File

@ -331,7 +331,7 @@ export type ExcalidrawLinearElement = _ExcalidrawElementBase &
export type ExcalidrawLineElement = ExcalidrawLinearElement &
Readonly<{
type: "line";
loopLock: boolean;
polygon: boolean;
}>;
export type FixedSegment = {

View File

@ -136,7 +136,7 @@ export const actionFinalize = register({
if (isLineElement(multiPointElement)) {
scene.mutateElement(multiPointElement, {
points,
loopLock: true,
polygon: true,
});
} else {
scene.mutateElement(multiPointElement, {

View File

@ -94,8 +94,8 @@ export const actionToggleLinearEditor = register({
},
});
export const actionToggleLoopLock = register({
name: "toggleLoopLock",
export const actionTogglePolygon = register({
name: "togglePolygon",
category: DEFAULT_CATEGORIES.elements,
icon: polygonIcon,
keywords: ["loop"],
@ -108,10 +108,12 @@ export const actionToggleLoopLock = register({
const allLocked =
selectedElements.length > 0 &&
selectedElements.every(
(element) => isLineElement(element) && element.loopLock,
(element) => isLineElement(element) && element.polygon,
);
return allLocked ? "labels.loopLock.unlock" : "labels.loopLock.lock";
return allLocked
? "labels.polygon.breakPolygon"
: "labels.polygon.convertToPolygon";
},
trackEvent: {
category: "element",
@ -137,10 +139,8 @@ export const actionToggleLoopLock = register({
const targetElements = selectedElements as ExcalidrawLineElement[];
// Check if we should lock or unlock based on current state
// If all elements are locked, unlock all. Otherwise, lock all.
const allLocked = targetElements.every((element) => element.loopLock);
const newLoopLockState = !allLocked;
// if one element not a polygon, convert all to polygon
const nextPolygonState = targetElements.some((element) => !element.polygon);
const targetElementsMap = arrayToMap(targetElements);
@ -151,10 +151,10 @@ export const actionToggleLoopLock = register({
}
return newElementWith(element, {
backgroundColor: newLoopLockState
backgroundColor: nextPolygonState
? element.backgroundColor
: "transparent",
...toggleLinePolygonState(element, newLoopLockState),
...toggleLinePolygonState(element, nextPolygonState),
});
}),
appState,
@ -174,20 +174,21 @@ export const actionToggleLoopLock = register({
// only show polygon button if every selected element is already
// a polygon, effectively showing this button only to allow for
// disabling the polygon state
!element.loopLock ||
!element.polygon ||
element.points.length < 3,
)
) {
return null;
}
// If all are locked, show locked icon. Otherwise show unlocked
const allLocked = selectedElements.every(
(element) => isLineElement(element) && element.loopLock,
const allPolygon = selectedElements.every(
(element) => isLineElement(element) && element.polygon,
);
const label = t(
allLocked ? "labels.loopLock.unlock" : "labels.loopLock.lock",
allPolygon
? "labels.polygon.breakPolygon"
: "labels.polygon.convertToPolygon",
);
return (
@ -195,7 +196,7 @@ export const actionToggleLoopLock = register({
icon={polygonIcon}
title={label}
aria-label={label}
active={allLocked}
active={allPolygon}
onClick={() => updateData(null)}
style={{ marginLeft: "auto" }}
/>

View File

@ -1439,7 +1439,7 @@ export const actionChangeRoundness = register({
)}
onChange={(value) => updateData(value)}
>
{renderAction("toggleLoopLock")}
{renderAction("togglePolygon")}
</ButtonIconSelect>
</fieldset>
);

View File

@ -143,7 +143,7 @@ export type ActionName =
| "wrapSelectionInFrame"
| "toggleLassoTool"
| "toggleShapeSwitch"
| "toggleLoopLock";
| "togglePolygon";
export type PanelComponentProps = {
elements: readonly ExcalidrawElement[];

View File

@ -293,7 +293,7 @@ function CommandPaletteInner({
actionManager.actions.decreaseFontSize,
actionManager.actions.toggleLinearEditor,
actionManager.actions.cropEditor,
actionManager.actions.toggleLoopLock,
actionManager.actions.togglePolygon,
actionLink,
actionCopyElementLink,
actionLinkToElement,
@ -586,10 +586,10 @@ function CommandPaletteInner({
});
setAllCommands(allCommands);
setLastUsed(
allCommands.find((command) => command.label === lastUsed?.label) ??
null,
);
// setLastUsed(
// allCommands.find((command) => command.label === lastUsed?.label) ??
// null,
// );
}
}, [
stableDeps,

View File

@ -342,7 +342,7 @@ const restoreElement = (
x,
y,
...(isLineElement(element)
? { loopLock: element.loopLock ?? false }
? { polygon: element.polygon ?? false }
: {}),
...getSizeFromPoints(points),
});

View File

@ -141,9 +141,9 @@
"edit": "Edit line",
"editArrow": "Edit arrow"
},
"loopLock": {
"unlock": "Break polygon",
"lock": "Convert to polygon"
"polygon": {
"breakPolygon": "Break polygon",
"convertToPolygon": "Convert to polygon"
},
"elementLock": {
"lock": "Lock",

View File

@ -466,7 +466,7 @@ const renderLinearPointHandles = (
(idx !== points.length - 1 ||
appState.editingLinearElement ||
!_isLineElement ||
!element.loopLock) &&
!element.polygon) &&
pointsEqual(
point,
idx === points.length - 1 ? points[0] : points[idx - 1],