mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
chore: Refactor and remove scene from elbow arrow generation (#8342)
* Refactor and remove scene from elbow arrow generation
This commit is contained in:
parent
72d6ee48fc
commit
dd1370381d
18 changed files with 115 additions and 156 deletions
|
@ -25,6 +25,7 @@ const deleteSelectedElements = (
|
||||||
appState: AppState,
|
appState: AppState,
|
||||||
app: AppClassProperties,
|
app: AppClassProperties,
|
||||||
) => {
|
) => {
|
||||||
|
const elementsMap = app.scene.getNonDeletedElementsMap();
|
||||||
const framesToBeDeleted = new Set(
|
const framesToBeDeleted = new Set(
|
||||||
getSelectedElements(
|
getSelectedElements(
|
||||||
elements.filter((el) => isFrameLikeElement(el)),
|
elements.filter((el) => isFrameLikeElement(el)),
|
||||||
|
@ -51,7 +52,7 @@ const deleteSelectedElements = (
|
||||||
? null
|
? null
|
||||||
: bound.endBinding,
|
: bound.endBinding,
|
||||||
});
|
});
|
||||||
mutateElbowArrow(bound, app.scene, bound.points);
|
mutateElbowArrow(bound, elementsMap, bound.points);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -159,7 +160,7 @@ export const actionDeleteSelected = register({
|
||||||
LinearElementEditor.deletePoints(
|
LinearElementEditor.deletePoints(
|
||||||
element,
|
element,
|
||||||
selectedPointsIndices,
|
selectedPointsIndices,
|
||||||
app.scene,
|
elementsMap,
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -44,7 +44,7 @@ export const actionDuplicateSelection = register({
|
||||||
if (appState.editingLinearElement) {
|
if (appState.editingLinearElement) {
|
||||||
const ret = LinearElementEditor.duplicateSelectedPoints(
|
const ret = LinearElementEditor.duplicateSelectedPoints(
|
||||||
appState,
|
appState,
|
||||||
app.scene,
|
app.scene.getNonDeletedElementsMap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
|
|
|
@ -120,7 +120,6 @@ const flipElements = (
|
||||||
true,
|
true,
|
||||||
flipDirection === "horizontal" ? maxX : minX,
|
flipDirection === "horizontal" ? maxX : minX,
|
||||||
flipDirection === "horizontal" ? minY : maxY,
|
flipDirection === "horizontal" ? minY : maxY,
|
||||||
app.scene,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
bindOrUnbindLinearElements(
|
bindOrUnbindLinearElements(
|
||||||
|
|
|
@ -58,7 +58,6 @@ export const createUndoAction: ActionCreator = (history, store) => ({
|
||||||
arrayToMap(elements) as SceneElementsMap, // TODO: #7348 refactor action manager to already include `SceneElementsMap`
|
arrayToMap(elements) as SceneElementsMap, // TODO: #7348 refactor action manager to already include `SceneElementsMap`
|
||||||
appState,
|
appState,
|
||||||
store.snapshot,
|
store.snapshot,
|
||||||
app.scene,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
keyTest: (event) =>
|
keyTest: (event) =>
|
||||||
|
@ -100,7 +99,6 @@ export const createRedoAction: ActionCreator = (history, store) => ({
|
||||||
arrayToMap(elements) as SceneElementsMap, // TODO: #7348 refactor action manager to already include `SceneElementsMap`
|
arrayToMap(elements) as SceneElementsMap, // TODO: #7348 refactor action manager to already include `SceneElementsMap`
|
||||||
appState,
|
appState,
|
||||||
store.snapshot,
|
store.snapshot,
|
||||||
app.scene,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
keyTest: (event) =>
|
keyTest: (event) =>
|
||||||
|
|
|
@ -1648,7 +1648,7 @@ export const actionChangeArrowType = register({
|
||||||
|
|
||||||
mutateElbowArrow(
|
mutateElbowArrow(
|
||||||
newElement,
|
newElement,
|
||||||
app.scene,
|
elementsMap,
|
||||||
[finalStartPoint, finalEndPoint].map(
|
[finalStartPoint, finalEndPoint].map(
|
||||||
(point) =>
|
(point) =>
|
||||||
[point[0] - newElement.x, point[1] - newElement.y] as Point,
|
[point[0] - newElement.x, point[1] - newElement.y] as Point,
|
||||||
|
|
|
@ -29,7 +29,6 @@ import type {
|
||||||
} from "./element/types";
|
} from "./element/types";
|
||||||
import { orderByFractionalIndex, syncMovedIndices } from "./fractionalIndex";
|
import { orderByFractionalIndex, syncMovedIndices } from "./fractionalIndex";
|
||||||
import { getNonDeletedGroupIds } from "./groups";
|
import { getNonDeletedGroupIds } from "./groups";
|
||||||
import type Scene from "./scene/Scene";
|
|
||||||
import { getObservedAppState } from "./store";
|
import { getObservedAppState } from "./store";
|
||||||
import type {
|
import type {
|
||||||
AppState,
|
AppState,
|
||||||
|
@ -1054,7 +1053,6 @@ export class ElementsChange implements Change<SceneElementsMap> {
|
||||||
public applyTo(
|
public applyTo(
|
||||||
elements: SceneElementsMap,
|
elements: SceneElementsMap,
|
||||||
snapshot: Map<string, OrderedExcalidrawElement>,
|
snapshot: Map<string, OrderedExcalidrawElement>,
|
||||||
scene: Scene,
|
|
||||||
): [SceneElementsMap, boolean] {
|
): [SceneElementsMap, boolean] {
|
||||||
let nextElements = toBrandedType<SceneElementsMap>(new Map(elements));
|
let nextElements = toBrandedType<SceneElementsMap>(new Map(elements));
|
||||||
let changedElements: Map<string, OrderedExcalidrawElement>;
|
let changedElements: Map<string, OrderedExcalidrawElement>;
|
||||||
|
@ -1102,7 +1100,6 @@ export class ElementsChange implements Change<SceneElementsMap> {
|
||||||
try {
|
try {
|
||||||
// TODO: #7348 refactor away mutations below, so that we couldn't end up in an incosistent state
|
// TODO: #7348 refactor away mutations below, so that we couldn't end up in an incosistent state
|
||||||
ElementsChange.redrawTextBoundingBoxes(nextElements, changedElements);
|
ElementsChange.redrawTextBoundingBoxes(nextElements, changedElements);
|
||||||
ElementsChange.redrawBoundArrows(nextElements, changedElements, scene);
|
|
||||||
|
|
||||||
// the following reorder performs also mutations, but only on new instances of changed elements
|
// the following reorder performs also mutations, but only on new instances of changed elements
|
||||||
// (unless something goes really bad and it fallbacks to fixing all invalid indices)
|
// (unless something goes really bad and it fallbacks to fixing all invalid indices)
|
||||||
|
@ -1111,6 +1108,9 @@ export class ElementsChange implements Change<SceneElementsMap> {
|
||||||
changedElements,
|
changedElements,
|
||||||
flags,
|
flags,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Need ordered nextElements to avoid z-index binding issues
|
||||||
|
ElementsChange.redrawBoundArrows(nextElements, changedElements);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(
|
console.error(
|
||||||
`Couldn't mutate elements after applying elements change`,
|
`Couldn't mutate elements after applying elements change`,
|
||||||
|
@ -1459,11 +1459,10 @@ export class ElementsChange implements Change<SceneElementsMap> {
|
||||||
private static redrawBoundArrows(
|
private static redrawBoundArrows(
|
||||||
elements: SceneElementsMap,
|
elements: SceneElementsMap,
|
||||||
changed: Map<string, OrderedExcalidrawElement>,
|
changed: Map<string, OrderedExcalidrawElement>,
|
||||||
scene: Scene,
|
|
||||||
) {
|
) {
|
||||||
for (const element of changed.values()) {
|
for (const element of changed.values()) {
|
||||||
if (!element.isDeleted && isBindableElement(element)) {
|
if (!element.isDeleted && isBindableElement(element)) {
|
||||||
updateBoundElements(element, elements, scene, {
|
updateBoundElements(element, elements, {
|
||||||
changedElements: changed,
|
changedElements: changed,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -4005,14 +4005,9 @@ class App extends React.Component<AppProps, AppState> {
|
||||||
y: element.y + offsetY,
|
y: element.y + offsetY,
|
||||||
});
|
});
|
||||||
|
|
||||||
updateBoundElements(
|
updateBoundElements(element, this.scene.getNonDeletedElementsMap(), {
|
||||||
element,
|
simultaneouslyUpdated: selectedElements,
|
||||||
this.scene.getNonDeletedElementsMap(),
|
});
|
||||||
this.scene,
|
|
||||||
{
|
|
||||||
simultaneouslyUpdated: selectedElements,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -4469,7 +4464,7 @@ class App extends React.Component<AppProps, AppState> {
|
||||||
onChange: withBatchedUpdates((nextOriginalText) => {
|
onChange: withBatchedUpdates((nextOriginalText) => {
|
||||||
updateElement(nextOriginalText, false);
|
updateElement(nextOriginalText, false);
|
||||||
if (isNonDeletedElement(element)) {
|
if (isNonDeletedElement(element)) {
|
||||||
updateBoundElements(element, elementsMap, this.scene);
|
updateBoundElements(element, this.scene.getNonDeletedElementsMap());
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
onSubmit: withBatchedUpdates(({ viaKeyboard, nextOriginalText }) => {
|
onSubmit: withBatchedUpdates(({ viaKeyboard, nextOriginalText }) => {
|
||||||
|
@ -5279,7 +5274,7 @@ class App extends React.Component<AppProps, AppState> {
|
||||||
scenePointerX,
|
scenePointerX,
|
||||||
scenePointerY,
|
scenePointerY,
|
||||||
this.state,
|
this.state,
|
||||||
this.scene,
|
this.scene.getNonDeletedElementsMap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
@ -5395,7 +5390,7 @@ class App extends React.Component<AppProps, AppState> {
|
||||||
if (isElbowArrow(multiElement)) {
|
if (isElbowArrow(multiElement)) {
|
||||||
mutateElbowArrow(
|
mutateElbowArrow(
|
||||||
multiElement,
|
multiElement,
|
||||||
this.scene,
|
this.scene.getNonDeletedElementsMap(),
|
||||||
[
|
[
|
||||||
...points.slice(0, -1),
|
...points.slice(0, -1),
|
||||||
[
|
[
|
||||||
|
@ -7771,7 +7766,7 @@ class App extends React.Component<AppProps, AppState> {
|
||||||
} else if (points.length > 1 && isElbowArrow(newElement)) {
|
} else if (points.length > 1 && isElbowArrow(newElement)) {
|
||||||
mutateElbowArrow(
|
mutateElbowArrow(
|
||||||
newElement,
|
newElement,
|
||||||
this.scene,
|
elementsMap,
|
||||||
[...points.slice(0, -1), [dx, dy]],
|
[...points.slice(0, -1), [dx, dy]],
|
||||||
[0, 0],
|
[0, 0],
|
||||||
undefined,
|
undefined,
|
||||||
|
@ -9756,7 +9751,6 @@ class App extends React.Component<AppProps, AppState> {
|
||||||
resizeY,
|
resizeY,
|
||||||
pointerDownState.resize.center.x,
|
pointerDownState.resize.center.x,
|
||||||
pointerDownState.resize.center.y,
|
pointerDownState.resize.center.y,
|
||||||
this.scene,
|
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
const suggestedBindings = getSuggestedBindingsForArrows(
|
const suggestedBindings = getSuggestedBindingsForArrows(
|
||||||
|
|
|
@ -66,7 +66,6 @@ const resizeElementInGroup = (
|
||||||
origElement: ExcalidrawElement,
|
origElement: ExcalidrawElement,
|
||||||
elementsMap: NonDeletedSceneElementsMap,
|
elementsMap: NonDeletedSceneElementsMap,
|
||||||
originalElementsMap: ElementsMap,
|
originalElementsMap: ElementsMap,
|
||||||
scene: Scene,
|
|
||||||
) => {
|
) => {
|
||||||
const updates = getResizedUpdates(anchorX, anchorY, scale, origElement);
|
const updates = getResizedUpdates(anchorX, anchorY, scale, origElement);
|
||||||
const { width: oldWidth, height: oldHeight } = latestElement;
|
const { width: oldWidth, height: oldHeight } = latestElement;
|
||||||
|
@ -78,7 +77,7 @@ const resizeElementInGroup = (
|
||||||
);
|
);
|
||||||
if (boundTextElement) {
|
if (boundTextElement) {
|
||||||
const newFontSize = boundTextElement.fontSize * scale;
|
const newFontSize = boundTextElement.fontSize * scale;
|
||||||
updateBoundElements(latestElement, elementsMap, scene, {
|
updateBoundElements(latestElement, elementsMap, {
|
||||||
oldSize: { width: oldWidth, height: oldHeight },
|
oldSize: { width: oldWidth, height: oldHeight },
|
||||||
});
|
});
|
||||||
const latestBoundTextElement = elementsMap.get(boundTextElement.id);
|
const latestBoundTextElement = elementsMap.get(boundTextElement.id);
|
||||||
|
@ -111,7 +110,6 @@ const resizeGroup = (
|
||||||
originalElements: ExcalidrawElement[],
|
originalElements: ExcalidrawElement[],
|
||||||
elementsMap: NonDeletedSceneElementsMap,
|
elementsMap: NonDeletedSceneElementsMap,
|
||||||
originalElementsMap: ElementsMap,
|
originalElementsMap: ElementsMap,
|
||||||
scene: Scene,
|
|
||||||
) => {
|
) => {
|
||||||
// keep aspect ratio for groups
|
// keep aspect ratio for groups
|
||||||
if (property === "width") {
|
if (property === "width") {
|
||||||
|
@ -135,7 +133,6 @@ const resizeGroup = (
|
||||||
origElement,
|
origElement,
|
||||||
elementsMap,
|
elementsMap,
|
||||||
originalElementsMap,
|
originalElementsMap,
|
||||||
scene,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -190,7 +187,6 @@ const handleDimensionChange: DragInputCallbackType<
|
||||||
originalElements,
|
originalElements,
|
||||||
elementsMap,
|
elementsMap,
|
||||||
originalElementsMap,
|
originalElementsMap,
|
||||||
scene,
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
const [el] = elementsInUnit;
|
const [el] = elementsInUnit;
|
||||||
|
@ -296,7 +292,6 @@ const handleDimensionChange: DragInputCallbackType<
|
||||||
originalElements,
|
originalElements,
|
||||||
elementsMap,
|
elementsMap,
|
||||||
originalElementsMap,
|
originalElementsMap,
|
||||||
scene,
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
const [el] = elementsInUnit;
|
const [el] = elementsInUnit;
|
||||||
|
|
|
@ -198,7 +198,7 @@ export const resizeElement = (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateBoundElements(latestElement, elementsMap, scene, {
|
updateBoundElements(latestElement, elementsMap, {
|
||||||
oldSize: { width: oldWidth, height: oldHeight },
|
oldSize: { width: oldWidth, height: oldHeight },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -316,6 +316,6 @@ export const updateBindings = (
|
||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
updateBoundElements(latestElement, elementsMap, scene, options);
|
updateBoundElements(latestElement, elementsMap, options);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,6 +25,7 @@ import type {
|
||||||
OrderedExcalidrawElement,
|
OrderedExcalidrawElement,
|
||||||
ExcalidrawElbowArrowElement,
|
ExcalidrawElbowArrowElement,
|
||||||
FixedPoint,
|
FixedPoint,
|
||||||
|
SceneElementsMap,
|
||||||
} from "./types";
|
} from "./types";
|
||||||
|
|
||||||
import type { Bounds } from "./bounds";
|
import type { Bounds } from "./bounds";
|
||||||
|
@ -124,7 +125,6 @@ export const bindOrUnbindLinearElement = (
|
||||||
boundToElementIds,
|
boundToElementIds,
|
||||||
unboundFromElementIds,
|
unboundFromElementIds,
|
||||||
elementsMap,
|
elementsMap,
|
||||||
scene,
|
|
||||||
);
|
);
|
||||||
bindOrUnbindLinearElementEdge(
|
bindOrUnbindLinearElementEdge(
|
||||||
linearElement,
|
linearElement,
|
||||||
|
@ -134,7 +134,6 @@ export const bindOrUnbindLinearElement = (
|
||||||
boundToElementIds,
|
boundToElementIds,
|
||||||
unboundFromElementIds,
|
unboundFromElementIds,
|
||||||
elementsMap,
|
elementsMap,
|
||||||
scene,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const onlyUnbound = Array.from(unboundFromElementIds).filter(
|
const onlyUnbound = Array.from(unboundFromElementIds).filter(
|
||||||
|
@ -161,7 +160,6 @@ const bindOrUnbindLinearElementEdge = (
|
||||||
// Is mutated
|
// Is mutated
|
||||||
unboundFromElementIds: Set<ExcalidrawBindableElement["id"]>,
|
unboundFromElementIds: Set<ExcalidrawBindableElement["id"]>,
|
||||||
elementsMap: NonDeletedSceneElementsMap,
|
elementsMap: NonDeletedSceneElementsMap,
|
||||||
scene: Scene,
|
|
||||||
): void => {
|
): void => {
|
||||||
// "keep" is for method chaining convenience, a "no-op", so just bail out
|
// "keep" is for method chaining convenience, a "no-op", so just bail out
|
||||||
if (bindableElement === "keep") {
|
if (bindableElement === "keep") {
|
||||||
|
@ -571,8 +569,7 @@ const calculateFocusAndGap = (
|
||||||
// in explicitly.
|
// in explicitly.
|
||||||
export const updateBoundElements = (
|
export const updateBoundElements = (
|
||||||
changedElement: NonDeletedExcalidrawElement,
|
changedElement: NonDeletedExcalidrawElement,
|
||||||
elementsMap: ElementsMap,
|
elementsMap: NonDeletedSceneElementsMap | SceneElementsMap,
|
||||||
scene: Scene,
|
|
||||||
options?: {
|
options?: {
|
||||||
simultaneouslyUpdated?: readonly ExcalidrawElement[];
|
simultaneouslyUpdated?: readonly ExcalidrawElement[];
|
||||||
oldSize?: { width: number; height: number };
|
oldSize?: { width: number; height: number };
|
||||||
|
@ -658,7 +655,7 @@ export const updateBoundElements = (
|
||||||
LinearElementEditor.movePoints(
|
LinearElementEditor.movePoints(
|
||||||
element,
|
element,
|
||||||
updates,
|
updates,
|
||||||
scene,
|
elementsMap,
|
||||||
{
|
{
|
||||||
...(changedElement.id === element.startBinding?.elementId
|
...(changedElement.id === element.startBinding?.elementId
|
||||||
? { startBinding: bindings.startBinding }
|
? { startBinding: bindings.startBinding }
|
||||||
|
|
|
@ -91,14 +91,9 @@ export const dragSelectedElements = (
|
||||||
updateElementCoords(pointerDownState, textElement, adjustedOffset);
|
updateElementCoords(pointerDownState, textElement, adjustedOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateBoundElements(
|
updateBoundElements(element, scene.getElementsMapIncludingDeleted(), {
|
||||||
element,
|
simultaneouslyUpdated: Array.from(elementsToUpdate),
|
||||||
scene.getElementsMapIncludingDeleted(),
|
});
|
||||||
scene,
|
|
||||||
{
|
|
||||||
simultaneouslyUpdated: Array.from(elementsToUpdate),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import type {
|
||||||
NonDeletedSceneElementsMap,
|
NonDeletedSceneElementsMap,
|
||||||
OrderedExcalidrawElement,
|
OrderedExcalidrawElement,
|
||||||
FixedPointBinding,
|
FixedPointBinding,
|
||||||
|
SceneElementsMap,
|
||||||
} from "./types";
|
} from "./types";
|
||||||
import {
|
import {
|
||||||
distance2d,
|
distance2d,
|
||||||
|
@ -290,7 +291,7 @@ export class LinearElementEditor {
|
||||||
isDragging: selectedIndex === lastClickedPoint,
|
isDragging: selectedIndex === lastClickedPoint,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
scene,
|
elementsMap,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
const newDraggingPointPosition = LinearElementEditor.createPointAt(
|
const newDraggingPointPosition = LinearElementEditor.createPointAt(
|
||||||
|
@ -326,7 +327,7 @@ export class LinearElementEditor {
|
||||||
isDragging: pointIndex === lastClickedPoint,
|
isDragging: pointIndex === lastClickedPoint,
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
scene,
|
elementsMap,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,7 +421,7 @@ export class LinearElementEditor {
|
||||||
: element.points[0],
|
: element.points[0],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
scene,
|
elementsMap,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -876,13 +877,12 @@ export class LinearElementEditor {
|
||||||
scenePointerX: number,
|
scenePointerX: number,
|
||||||
scenePointerY: number,
|
scenePointerY: number,
|
||||||
appState: AppState,
|
appState: AppState,
|
||||||
scene: Scene,
|
elementsMap: NonDeletedSceneElementsMap | SceneElementsMap,
|
||||||
): LinearElementEditor | null {
|
): LinearElementEditor | null {
|
||||||
if (!appState.editingLinearElement) {
|
if (!appState.editingLinearElement) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const { elementId, lastUncommittedPoint } = appState.editingLinearElement;
|
const { elementId, lastUncommittedPoint } = appState.editingLinearElement;
|
||||||
const elementsMap = scene.getNonDeletedElementsMap();
|
|
||||||
const element = LinearElementEditor.getElement(elementId, elementsMap);
|
const element = LinearElementEditor.getElement(elementId, elementsMap);
|
||||||
if (!element) {
|
if (!element) {
|
||||||
return appState.editingLinearElement;
|
return appState.editingLinearElement;
|
||||||
|
@ -893,7 +893,11 @@ export class LinearElementEditor {
|
||||||
|
|
||||||
if (!event.altKey) {
|
if (!event.altKey) {
|
||||||
if (lastPoint === lastUncommittedPoint) {
|
if (lastPoint === lastUncommittedPoint) {
|
||||||
LinearElementEditor.deletePoints(element, [points.length - 1], scene);
|
LinearElementEditor.deletePoints(
|
||||||
|
element,
|
||||||
|
[points.length - 1],
|
||||||
|
elementsMap,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
...appState.editingLinearElement,
|
...appState.editingLinearElement,
|
||||||
|
@ -939,14 +943,13 @@ export class LinearElementEditor {
|
||||||
point: newPoint,
|
point: newPoint,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
scene,
|
elementsMap,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
LinearElementEditor.addPoints(
|
LinearElementEditor.addPoints(
|
||||||
element,
|
element,
|
||||||
appState,
|
|
||||||
[{ point: newPoint }],
|
[{ point: newPoint }],
|
||||||
scene,
|
elementsMap,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
@ -1091,7 +1094,7 @@ export class LinearElementEditor {
|
||||||
const offsetY = points[0][1];
|
const offsetY = points[0][1];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
points: points.map((point, _idx) => {
|
points: points.map((point) => {
|
||||||
return [point[0] - offsetX, point[1] - offsetY] as const;
|
return [point[0] - offsetX, point[1] - offsetY] as const;
|
||||||
}),
|
}),
|
||||||
x: element.x + offsetX,
|
x: element.x + offsetX,
|
||||||
|
@ -1106,13 +1109,15 @@ export class LinearElementEditor {
|
||||||
mutateElement(element, LinearElementEditor.getNormalizedPoints(element));
|
mutateElement(element, LinearElementEditor.getNormalizedPoints(element));
|
||||||
}
|
}
|
||||||
|
|
||||||
static duplicateSelectedPoints(appState: AppState, scene: Scene) {
|
static duplicateSelectedPoints(
|
||||||
|
appState: AppState,
|
||||||
|
elementsMap: NonDeletedSceneElementsMap | SceneElementsMap,
|
||||||
|
) {
|
||||||
if (!appState.editingLinearElement) {
|
if (!appState.editingLinearElement) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { selectedPointsIndices, elementId } = appState.editingLinearElement;
|
const { selectedPointsIndices, elementId } = appState.editingLinearElement;
|
||||||
const elementsMap = scene.getNonDeletedElementsMap();
|
|
||||||
const element = LinearElementEditor.getElement(elementId, elementsMap);
|
const element = LinearElementEditor.getElement(elementId, elementsMap);
|
||||||
|
|
||||||
if (!element || selectedPointsIndices === null) {
|
if (!element || selectedPointsIndices === null) {
|
||||||
|
@ -1163,7 +1168,7 @@ export class LinearElementEditor {
|
||||||
point: [lastPoint[0] + 30, lastPoint[1] + 30],
|
point: [lastPoint[0] + 30, lastPoint[1] + 30],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
scene,
|
elementsMap,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1181,7 +1186,7 @@ export class LinearElementEditor {
|
||||||
static deletePoints(
|
static deletePoints(
|
||||||
element: NonDeleted<ExcalidrawLinearElement>,
|
element: NonDeleted<ExcalidrawLinearElement>,
|
||||||
pointIndices: readonly number[],
|
pointIndices: readonly number[],
|
||||||
scene: Scene,
|
elementsMap: NonDeletedSceneElementsMap | SceneElementsMap,
|
||||||
) {
|
) {
|
||||||
let offsetX = 0;
|
let offsetX = 0;
|
||||||
let offsetY = 0;
|
let offsetY = 0;
|
||||||
|
@ -1214,15 +1219,14 @@ export class LinearElementEditor {
|
||||||
nextPoints,
|
nextPoints,
|
||||||
offsetX,
|
offsetX,
|
||||||
offsetY,
|
offsetY,
|
||||||
scene,
|
elementsMap,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static addPoints(
|
static addPoints(
|
||||||
element: NonDeleted<ExcalidrawLinearElement>,
|
element: NonDeleted<ExcalidrawLinearElement>,
|
||||||
appState: AppState,
|
|
||||||
targetPoints: { point: Point }[],
|
targetPoints: { point: Point }[],
|
||||||
scene: Scene,
|
elementsMap: NonDeletedSceneElementsMap | SceneElementsMap,
|
||||||
) {
|
) {
|
||||||
const offsetX = 0;
|
const offsetX = 0;
|
||||||
const offsetY = 0;
|
const offsetY = 0;
|
||||||
|
@ -1233,14 +1237,14 @@ export class LinearElementEditor {
|
||||||
nextPoints,
|
nextPoints,
|
||||||
offsetX,
|
offsetX,
|
||||||
offsetY,
|
offsetY,
|
||||||
scene,
|
elementsMap,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static movePoints(
|
static movePoints(
|
||||||
element: NonDeleted<ExcalidrawLinearElement>,
|
element: NonDeleted<ExcalidrawLinearElement>,
|
||||||
targetPoints: { index: number; point: Point; isDragging?: boolean }[],
|
targetPoints: { index: number; point: Point; isDragging?: boolean }[],
|
||||||
scene: Scene,
|
elementsMap: NonDeletedSceneElementsMap | SceneElementsMap,
|
||||||
otherUpdates?: {
|
otherUpdates?: {
|
||||||
startBinding?: PointBinding | null;
|
startBinding?: PointBinding | null;
|
||||||
endBinding?: PointBinding | null;
|
endBinding?: PointBinding | null;
|
||||||
|
@ -1296,7 +1300,7 @@ export class LinearElementEditor {
|
||||||
nextPoints,
|
nextPoints,
|
||||||
offsetX,
|
offsetX,
|
||||||
offsetY,
|
offsetY,
|
||||||
scene,
|
elementsMap,
|
||||||
otherUpdates,
|
otherUpdates,
|
||||||
{
|
{
|
||||||
isDragging: targetPoints.reduce(
|
isDragging: targetPoints.reduce(
|
||||||
|
@ -1413,7 +1417,7 @@ export class LinearElementEditor {
|
||||||
nextPoints: readonly Point[],
|
nextPoints: readonly Point[],
|
||||||
offsetX: number,
|
offsetX: number,
|
||||||
offsetY: number,
|
offsetY: number,
|
||||||
scene: Scene,
|
elementsMap: NonDeletedSceneElementsMap | SceneElementsMap,
|
||||||
otherUpdates?: {
|
otherUpdates?: {
|
||||||
startBinding?: PointBinding | null;
|
startBinding?: PointBinding | null;
|
||||||
endBinding?: PointBinding | null;
|
endBinding?: PointBinding | null;
|
||||||
|
@ -1445,7 +1449,7 @@ export class LinearElementEditor {
|
||||||
|
|
||||||
mutateElbowArrow(
|
mutateElbowArrow(
|
||||||
element,
|
element,
|
||||||
scene,
|
elementsMap,
|
||||||
nextPoints,
|
nextPoints,
|
||||||
[offsetX, offsetY],
|
[offsetX, offsetY],
|
||||||
bindings,
|
bindings,
|
||||||
|
|
|
@ -11,6 +11,8 @@ import type {
|
||||||
ExcalidrawTextElementWithContainer,
|
ExcalidrawTextElementWithContainer,
|
||||||
ExcalidrawImageElement,
|
ExcalidrawImageElement,
|
||||||
ElementsMap,
|
ElementsMap,
|
||||||
|
NonDeletedSceneElementsMap,
|
||||||
|
SceneElementsMap,
|
||||||
} from "./types";
|
} from "./types";
|
||||||
import type { Mutable } from "../utility-types";
|
import type { Mutable } from "../utility-types";
|
||||||
import {
|
import {
|
||||||
|
@ -69,7 +71,7 @@ export const transformElements = (
|
||||||
originalElements: PointerDownState["originalElements"],
|
originalElements: PointerDownState["originalElements"],
|
||||||
transformHandleType: MaybeTransformHandleType,
|
transformHandleType: MaybeTransformHandleType,
|
||||||
selectedElements: readonly NonDeletedExcalidrawElement[],
|
selectedElements: readonly NonDeletedExcalidrawElement[],
|
||||||
elementsMap: ElementsMap,
|
elementsMap: SceneElementsMap,
|
||||||
shouldRotateWithDiscreteAngle: boolean,
|
shouldRotateWithDiscreteAngle: boolean,
|
||||||
shouldResizeFromCenter: boolean,
|
shouldResizeFromCenter: boolean,
|
||||||
shouldMaintainAspectRatio: boolean,
|
shouldMaintainAspectRatio: boolean,
|
||||||
|
@ -77,7 +79,6 @@ export const transformElements = (
|
||||||
pointerY: number,
|
pointerY: number,
|
||||||
centerX: number,
|
centerX: number,
|
||||||
centerY: number,
|
centerY: number,
|
||||||
scene: Scene,
|
|
||||||
) => {
|
) => {
|
||||||
if (selectedElements.length === 1) {
|
if (selectedElements.length === 1) {
|
||||||
const [element] = selectedElements;
|
const [element] = selectedElements;
|
||||||
|
@ -90,7 +91,7 @@ export const transformElements = (
|
||||||
pointerY,
|
pointerY,
|
||||||
shouldRotateWithDiscreteAngle,
|
shouldRotateWithDiscreteAngle,
|
||||||
);
|
);
|
||||||
updateBoundElements(element, elementsMap, scene);
|
updateBoundElements(element, elementsMap);
|
||||||
}
|
}
|
||||||
} else if (isTextElement(element) && transformHandleType) {
|
} else if (isTextElement(element) && transformHandleType) {
|
||||||
resizeSingleTextElement(
|
resizeSingleTextElement(
|
||||||
|
@ -102,7 +103,7 @@ export const transformElements = (
|
||||||
pointerX,
|
pointerX,
|
||||||
pointerY,
|
pointerY,
|
||||||
);
|
);
|
||||||
updateBoundElements(element, elementsMap, scene);
|
updateBoundElements(element, elementsMap);
|
||||||
} else if (transformHandleType) {
|
} else if (transformHandleType) {
|
||||||
resizeSingleElement(
|
resizeSingleElement(
|
||||||
originalElements,
|
originalElements,
|
||||||
|
@ -113,7 +114,6 @@ export const transformElements = (
|
||||||
shouldResizeFromCenter,
|
shouldResizeFromCenter,
|
||||||
pointerX,
|
pointerX,
|
||||||
pointerY,
|
pointerY,
|
||||||
scene,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +129,6 @@ export const transformElements = (
|
||||||
shouldRotateWithDiscreteAngle,
|
shouldRotateWithDiscreteAngle,
|
||||||
centerX,
|
centerX,
|
||||||
centerY,
|
centerY,
|
||||||
scene,
|
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
} else if (transformHandleType) {
|
} else if (transformHandleType) {
|
||||||
|
@ -142,7 +141,6 @@ export const transformElements = (
|
||||||
shouldMaintainAspectRatio,
|
shouldMaintainAspectRatio,
|
||||||
pointerX,
|
pointerX,
|
||||||
pointerY,
|
pointerY,
|
||||||
scene,
|
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -434,12 +432,11 @@ export const resizeSingleElement = (
|
||||||
originalElements: PointerDownState["originalElements"],
|
originalElements: PointerDownState["originalElements"],
|
||||||
shouldMaintainAspectRatio: boolean,
|
shouldMaintainAspectRatio: boolean,
|
||||||
element: NonDeletedExcalidrawElement,
|
element: NonDeletedExcalidrawElement,
|
||||||
elementsMap: ElementsMap,
|
elementsMap: SceneElementsMap,
|
||||||
transformHandleDirection: TransformHandleDirection,
|
transformHandleDirection: TransformHandleDirection,
|
||||||
shouldResizeFromCenter: boolean,
|
shouldResizeFromCenter: boolean,
|
||||||
pointerX: number,
|
pointerX: number,
|
||||||
pointerY: number,
|
pointerY: number,
|
||||||
scene: Scene,
|
|
||||||
) => {
|
) => {
|
||||||
const stateAtResizeStart = originalElements.get(element.id)!;
|
const stateAtResizeStart = originalElements.get(element.id)!;
|
||||||
// Gets bounds corners
|
// Gets bounds corners
|
||||||
|
@ -710,7 +707,7 @@ export const resizeSingleElement = (
|
||||||
) {
|
) {
|
||||||
mutateElement(element, resizedElement);
|
mutateElement(element, resizedElement);
|
||||||
|
|
||||||
updateBoundElements(element, elementsMap, scene, {
|
updateBoundElements(element, elementsMap, {
|
||||||
oldSize: {
|
oldSize: {
|
||||||
width: stateAtResizeStart.width,
|
width: stateAtResizeStart.width,
|
||||||
height: stateAtResizeStart.height,
|
height: stateAtResizeStart.height,
|
||||||
|
@ -734,13 +731,12 @@ export const resizeSingleElement = (
|
||||||
export const resizeMultipleElements = (
|
export const resizeMultipleElements = (
|
||||||
originalElements: PointerDownState["originalElements"],
|
originalElements: PointerDownState["originalElements"],
|
||||||
selectedElements: readonly NonDeletedExcalidrawElement[],
|
selectedElements: readonly NonDeletedExcalidrawElement[],
|
||||||
elementsMap: ElementsMap,
|
elementsMap: NonDeletedSceneElementsMap | SceneElementsMap,
|
||||||
transformHandleType: TransformHandleDirection,
|
transformHandleType: TransformHandleDirection,
|
||||||
shouldResizeFromCenter: boolean,
|
shouldResizeFromCenter: boolean,
|
||||||
shouldMaintainAspectRatio: boolean,
|
shouldMaintainAspectRatio: boolean,
|
||||||
pointerX: number,
|
pointerX: number,
|
||||||
pointerY: number,
|
pointerY: number,
|
||||||
scene: Scene,
|
|
||||||
) => {
|
) => {
|
||||||
// map selected elements to the original elements. While it never should
|
// map selected elements to the original elements. While it never should
|
||||||
// happen that pointerDownState.originalElements won't contain the selected
|
// happen that pointerDownState.originalElements won't contain the selected
|
||||||
|
@ -974,12 +970,19 @@ export const resizeMultipleElements = (
|
||||||
mutateElement(element, update, false);
|
mutateElement(element, update, false);
|
||||||
|
|
||||||
if (isArrowElement(element) && isElbowArrow(element)) {
|
if (isArrowElement(element) && isElbowArrow(element)) {
|
||||||
mutateElbowArrow(element, scene, element.points, undefined, undefined, {
|
mutateElbowArrow(
|
||||||
informMutation: false,
|
element,
|
||||||
});
|
elementsMap,
|
||||||
|
element.points,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
{
|
||||||
|
informMutation: false,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateBoundElements(element, elementsMap, scene, {
|
updateBoundElements(element, elementsMap, {
|
||||||
simultaneouslyUpdated: elementsToUpdate,
|
simultaneouslyUpdated: elementsToUpdate,
|
||||||
oldSize: { width: oldWidth, height: oldHeight },
|
oldSize: { width: oldWidth, height: oldHeight },
|
||||||
});
|
});
|
||||||
|
@ -1004,13 +1007,12 @@ export const resizeMultipleElements = (
|
||||||
const rotateMultipleElements = (
|
const rotateMultipleElements = (
|
||||||
originalElements: PointerDownState["originalElements"],
|
originalElements: PointerDownState["originalElements"],
|
||||||
elements: readonly NonDeletedExcalidrawElement[],
|
elements: readonly NonDeletedExcalidrawElement[],
|
||||||
elementsMap: ElementsMap,
|
elementsMap: SceneElementsMap,
|
||||||
pointerX: number,
|
pointerX: number,
|
||||||
pointerY: number,
|
pointerY: number,
|
||||||
shouldRotateWithDiscreteAngle: boolean,
|
shouldRotateWithDiscreteAngle: boolean,
|
||||||
centerX: number,
|
centerX: number,
|
||||||
centerY: number,
|
centerY: number,
|
||||||
scene: Scene,
|
|
||||||
) => {
|
) => {
|
||||||
let centerAngle =
|
let centerAngle =
|
||||||
(5 * Math.PI) / 2 + Math.atan2(pointerY - centerY, pointerX - centerX);
|
(5 * Math.PI) / 2 + Math.atan2(pointerY - centerY, pointerX - centerX);
|
||||||
|
@ -1037,7 +1039,7 @@ const rotateMultipleElements = (
|
||||||
|
|
||||||
if (isArrowElement(element) && isElbowArrow(element)) {
|
if (isArrowElement(element) && isElbowArrow(element)) {
|
||||||
const points = getArrowLocalFixedPoints(element, elementsMap);
|
const points = getArrowLocalFixedPoints(element, elementsMap);
|
||||||
mutateElbowArrow(element, scene, points);
|
mutateElbowArrow(element, elementsMap, points);
|
||||||
} else {
|
} else {
|
||||||
mutateElement(
|
mutateElement(
|
||||||
element,
|
element,
|
||||||
|
@ -1050,7 +1052,7 @@ const rotateMultipleElements = (
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateBoundElements(element, elementsMap, scene, {
|
updateBoundElements(element, elementsMap, {
|
||||||
simultaneouslyUpdated: elements,
|
simultaneouslyUpdated: elements,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ describe("elbow arrow routing", () => {
|
||||||
elbowed: true,
|
elbowed: true,
|
||||||
}) as ExcalidrawElbowArrowElement;
|
}) as ExcalidrawElbowArrowElement;
|
||||||
scene.insertElement(arrow);
|
scene.insertElement(arrow);
|
||||||
mutateElbowArrow(arrow, scene, [
|
mutateElbowArrow(arrow, scene.getNonDeletedElementsMap(), [
|
||||||
[-45 - arrow.x, -100.1 - arrow.y],
|
[-45 - arrow.x, -100.1 - arrow.y],
|
||||||
[45 - arrow.x, 99.9 - arrow.y],
|
[45 - arrow.x, 99.9 - arrow.y],
|
||||||
]);
|
]);
|
||||||
|
@ -98,7 +98,7 @@ describe("elbow arrow routing", () => {
|
||||||
expect(arrow.startBinding).not.toBe(null);
|
expect(arrow.startBinding).not.toBe(null);
|
||||||
expect(arrow.endBinding).not.toBe(null);
|
expect(arrow.endBinding).not.toBe(null);
|
||||||
|
|
||||||
mutateElbowArrow(arrow, scene, [
|
mutateElbowArrow(arrow, elementsMap, [
|
||||||
[0, 0],
|
[0, 0],
|
||||||
[90, 200],
|
[90, 200],
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -10,7 +10,6 @@ import {
|
||||||
translatePoint,
|
translatePoint,
|
||||||
} from "../math";
|
} from "../math";
|
||||||
import { getSizeFromPoints } from "../points";
|
import { getSizeFromPoints } from "../points";
|
||||||
import type Scene from "../scene/Scene";
|
|
||||||
import type { Point } from "../types";
|
import type { Point } from "../types";
|
||||||
import { isAnyTrue, toBrandedType, tupleToCoors } from "../utils";
|
import { isAnyTrue, toBrandedType, tupleToCoors } from "../utils";
|
||||||
import {
|
import {
|
||||||
|
@ -37,14 +36,10 @@ import { isBindableElement, isRectanguloidElement } from "./typeChecks";
|
||||||
import type {
|
import type {
|
||||||
ExcalidrawElbowArrowElement,
|
ExcalidrawElbowArrowElement,
|
||||||
FixedPointBinding,
|
FixedPointBinding,
|
||||||
NonDeletedExcalidrawElement,
|
|
||||||
NonDeletedSceneElementsMap,
|
NonDeletedSceneElementsMap,
|
||||||
|
SceneElementsMap,
|
||||||
} from "./types";
|
} from "./types";
|
||||||
import type {
|
import type { ElementsMap, ExcalidrawBindableElement } from "./types";
|
||||||
ElementsMap,
|
|
||||||
ExcalidrawBindableElement,
|
|
||||||
OrderedExcalidrawElement,
|
|
||||||
} from "./types";
|
|
||||||
|
|
||||||
type Node = {
|
type Node = {
|
||||||
f: number;
|
f: number;
|
||||||
|
@ -67,7 +62,7 @@ const BASE_PADDING = 40;
|
||||||
|
|
||||||
export const mutateElbowArrow = (
|
export const mutateElbowArrow = (
|
||||||
arrow: ExcalidrawElbowArrowElement,
|
arrow: ExcalidrawElbowArrowElement,
|
||||||
scene: Scene,
|
elementsMap: NonDeletedSceneElementsMap | SceneElementsMap,
|
||||||
nextPoints: readonly Point[],
|
nextPoints: readonly Point[],
|
||||||
offset?: Point,
|
offset?: Point,
|
||||||
otherUpdates?: {
|
otherUpdates?: {
|
||||||
|
@ -75,15 +70,11 @@ export const mutateElbowArrow = (
|
||||||
endBinding?: FixedPointBinding | null;
|
endBinding?: FixedPointBinding | null;
|
||||||
},
|
},
|
||||||
options?: {
|
options?: {
|
||||||
changedElements?: Map<string, OrderedExcalidrawElement>;
|
|
||||||
isDragging?: boolean;
|
isDragging?: boolean;
|
||||||
disableBinding?: boolean;
|
disableBinding?: boolean;
|
||||||
informMutation?: boolean;
|
informMutation?: boolean;
|
||||||
},
|
},
|
||||||
) => {
|
) => {
|
||||||
const elements = getAllElements(scene, options?.changedElements);
|
|
||||||
const elementsMap = getAllElementsMap(scene, options?.changedElements);
|
|
||||||
|
|
||||||
const origStartGlobalPoint = translatePoint(nextPoints[0], [
|
const origStartGlobalPoint = translatePoint(nextPoints[0], [
|
||||||
arrow.x + (offset ? offset[0] : 0),
|
arrow.x + (offset ? offset[0] : 0),
|
||||||
arrow.y + (offset ? offset[1] : 0),
|
arrow.y + (offset ? offset[1] : 0),
|
||||||
|
@ -99,22 +90,9 @@ export const mutateElbowArrow = (
|
||||||
const endElement =
|
const endElement =
|
||||||
arrow.endBinding &&
|
arrow.endBinding &&
|
||||||
getBindableElementForId(arrow.endBinding.elementId, elementsMap);
|
getBindableElementForId(arrow.endBinding.elementId, elementsMap);
|
||||||
const hoveredStartElement = options?.isDragging
|
const [hoveredStartElement, hoveredEndElement] = options?.isDragging
|
||||||
? getHoveredElementForBinding(
|
? getHoveredElements(origStartGlobalPoint, origEndGlobalPoint, elementsMap)
|
||||||
tupleToCoors(origStartGlobalPoint),
|
: [startElement, endElement];
|
||||||
elements,
|
|
||||||
elementsMap,
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
: startElement;
|
|
||||||
const hoveredEndElement = options?.isDragging
|
|
||||||
? getHoveredElementForBinding(
|
|
||||||
tupleToCoors(origEndGlobalPoint),
|
|
||||||
elements,
|
|
||||||
elementsMap,
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
: endElement;
|
|
||||||
const startGlobalPoint = getGlobalPoint(
|
const startGlobalPoint = getGlobalPoint(
|
||||||
arrow.startBinding?.fixedPoint,
|
arrow.startBinding?.fixedPoint,
|
||||||
origStartGlobalPoint,
|
origStartGlobalPoint,
|
||||||
|
@ -895,7 +873,7 @@ const normalizedArrowElementUpdate = (
|
||||||
const offsetY = global[0][1];
|
const offsetY = global[0][1];
|
||||||
|
|
||||||
const points = global.map(
|
const points = global.map(
|
||||||
(point, _idx) => [point[0] - offsetX, point[1] - offsetY] as const,
|
(point) => [point[0] - offsetX, point[1] - offsetY] as const,
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -935,32 +913,11 @@ const neighborIndexToHeading = (idx: number): Heading => {
|
||||||
return HEADING_LEFT;
|
return HEADING_LEFT;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getAllElementsMap = (
|
|
||||||
scene: Scene,
|
|
||||||
changedElements?: Map<string, OrderedExcalidrawElement>,
|
|
||||||
): NonDeletedSceneElementsMap =>
|
|
||||||
changedElements
|
|
||||||
? toBrandedType<NonDeletedSceneElementsMap>(
|
|
||||||
new Map([...scene.getNonDeletedElementsMap(), ...changedElements]),
|
|
||||||
)
|
|
||||||
: scene.getNonDeletedElementsMap();
|
|
||||||
|
|
||||||
const getAllElements = (
|
|
||||||
scene: Scene,
|
|
||||||
changedElements?: Map<string, OrderedExcalidrawElement>,
|
|
||||||
): readonly NonDeletedExcalidrawElement[] =>
|
|
||||||
changedElements
|
|
||||||
? ([
|
|
||||||
...scene.getNonDeletedElements(),
|
|
||||||
...[...changedElements].map(([_, value]) => value),
|
|
||||||
] as NonDeletedExcalidrawElement[])
|
|
||||||
: scene.getNonDeletedElements();
|
|
||||||
|
|
||||||
const getGlobalPoint = (
|
const getGlobalPoint = (
|
||||||
fixedPointRatio: [number, number] | undefined | null,
|
fixedPointRatio: [number, number] | undefined | null,
|
||||||
initialPoint: Point,
|
initialPoint: Point,
|
||||||
otherPoint: Point,
|
otherPoint: Point,
|
||||||
elementsMap: NonDeletedSceneElementsMap,
|
elementsMap: NonDeletedSceneElementsMap | SceneElementsMap,
|
||||||
boundElement?: ExcalidrawBindableElement | null,
|
boundElement?: ExcalidrawBindableElement | null,
|
||||||
hoveredElement?: ExcalidrawBindableElement | null,
|
hoveredElement?: ExcalidrawBindableElement | null,
|
||||||
isDragging?: boolean,
|
isDragging?: boolean,
|
||||||
|
@ -1016,7 +973,7 @@ const getSnapPoint = (
|
||||||
const getBindPointHeading = (
|
const getBindPointHeading = (
|
||||||
point: Point,
|
point: Point,
|
||||||
otherPoint: Point,
|
otherPoint: Point,
|
||||||
elementsMap: NonDeletedSceneElementsMap,
|
elementsMap: NonDeletedSceneElementsMap | SceneElementsMap,
|
||||||
hoveredElement: ExcalidrawBindableElement | null | undefined,
|
hoveredElement: ExcalidrawBindableElement | null | undefined,
|
||||||
origPoint: Point,
|
origPoint: Point,
|
||||||
) =>
|
) =>
|
||||||
|
@ -1034,3 +991,30 @@ const getBindPointHeading = (
|
||||||
elementsMap,
|
elementsMap,
|
||||||
origPoint,
|
origPoint,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const getHoveredElements = (
|
||||||
|
origStartGlobalPoint: Point,
|
||||||
|
origEndGlobalPoint: Point,
|
||||||
|
elementsMap: NonDeletedSceneElementsMap | SceneElementsMap,
|
||||||
|
) => {
|
||||||
|
// TODO: Might be a performance bottleneck and the Map type
|
||||||
|
// remembers the insertion order anyway...
|
||||||
|
const nonDeletedSceneElementsMap = toBrandedType<NonDeletedSceneElementsMap>(
|
||||||
|
new Map([...elementsMap].filter((el) => !el[1].isDeleted)),
|
||||||
|
);
|
||||||
|
const elements = Array.from(elementsMap.values());
|
||||||
|
return [
|
||||||
|
getHoveredElementForBinding(
|
||||||
|
tupleToCoors(origStartGlobalPoint),
|
||||||
|
elements,
|
||||||
|
nonDeletedSceneElementsMap,
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
getHoveredElementForBinding(
|
||||||
|
tupleToCoors(origEndGlobalPoint),
|
||||||
|
elements,
|
||||||
|
nonDeletedSceneElementsMap,
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import type { AppStateChange, ElementsChange } from "./change";
|
import type { AppStateChange, ElementsChange } from "./change";
|
||||||
import type { SceneElementsMap } from "./element/types";
|
import type { SceneElementsMap } from "./element/types";
|
||||||
import { Emitter } from "./emitter";
|
import { Emitter } from "./emitter";
|
||||||
import type Scene from "./scene/Scene";
|
|
||||||
import type { Snapshot } from "./store";
|
import type { Snapshot } from "./store";
|
||||||
import type { AppState } from "./types";
|
import type { AppState } from "./types";
|
||||||
|
|
||||||
|
@ -65,7 +64,6 @@ export class History {
|
||||||
elements: SceneElementsMap,
|
elements: SceneElementsMap,
|
||||||
appState: AppState,
|
appState: AppState,
|
||||||
snapshot: Readonly<Snapshot>,
|
snapshot: Readonly<Snapshot>,
|
||||||
scene: Scene,
|
|
||||||
) {
|
) {
|
||||||
return this.perform(
|
return this.perform(
|
||||||
elements,
|
elements,
|
||||||
|
@ -73,7 +71,6 @@ export class History {
|
||||||
snapshot,
|
snapshot,
|
||||||
() => History.pop(this.undoStack),
|
() => History.pop(this.undoStack),
|
||||||
(entry: HistoryEntry) => History.push(this.redoStack, entry, elements),
|
(entry: HistoryEntry) => History.push(this.redoStack, entry, elements),
|
||||||
scene,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +78,6 @@ export class History {
|
||||||
elements: SceneElementsMap,
|
elements: SceneElementsMap,
|
||||||
appState: AppState,
|
appState: AppState,
|
||||||
snapshot: Readonly<Snapshot>,
|
snapshot: Readonly<Snapshot>,
|
||||||
scene: Scene,
|
|
||||||
) {
|
) {
|
||||||
return this.perform(
|
return this.perform(
|
||||||
elements,
|
elements,
|
||||||
|
@ -89,7 +85,6 @@ export class History {
|
||||||
snapshot,
|
snapshot,
|
||||||
() => History.pop(this.redoStack),
|
() => History.pop(this.redoStack),
|
||||||
(entry: HistoryEntry) => History.push(this.undoStack, entry, elements),
|
(entry: HistoryEntry) => History.push(this.undoStack, entry, elements),
|
||||||
scene,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +94,6 @@ export class History {
|
||||||
snapshot: Readonly<Snapshot>,
|
snapshot: Readonly<Snapshot>,
|
||||||
pop: () => HistoryEntry | null,
|
pop: () => HistoryEntry | null,
|
||||||
push: (entry: HistoryEntry) => void,
|
push: (entry: HistoryEntry) => void,
|
||||||
scene: Scene,
|
|
||||||
): [SceneElementsMap, AppState] | void {
|
): [SceneElementsMap, AppState] | void {
|
||||||
try {
|
try {
|
||||||
let historyEntry = pop();
|
let historyEntry = pop();
|
||||||
|
@ -116,7 +110,7 @@ export class History {
|
||||||
while (historyEntry) {
|
while (historyEntry) {
|
||||||
try {
|
try {
|
||||||
[nextElements, nextAppState, containsVisibleChange] =
|
[nextElements, nextAppState, containsVisibleChange] =
|
||||||
historyEntry.applyTo(nextElements, nextAppState, snapshot, scene);
|
historyEntry.applyTo(nextElements, nextAppState, snapshot);
|
||||||
} finally {
|
} finally {
|
||||||
// make sure to always push / pop, even if the increment is corrupted
|
// make sure to always push / pop, even if the increment is corrupted
|
||||||
push(historyEntry);
|
push(historyEntry);
|
||||||
|
@ -187,10 +181,9 @@ export class HistoryEntry {
|
||||||
elements: SceneElementsMap,
|
elements: SceneElementsMap,
|
||||||
appState: AppState,
|
appState: AppState,
|
||||||
snapshot: Readonly<Snapshot>,
|
snapshot: Readonly<Snapshot>,
|
||||||
scene: Scene,
|
|
||||||
): [SceneElementsMap, AppState, boolean] {
|
): [SceneElementsMap, AppState, boolean] {
|
||||||
const [nextElements, elementsContainVisibleChange] =
|
const [nextElements, elementsContainVisibleChange] =
|
||||||
this.elementsChange.applyTo(elements, snapshot.elements, scene);
|
this.elementsChange.applyTo(elements, snapshot.elements);
|
||||||
|
|
||||||
const [nextAppState, appStateContainsVisibleChange] =
|
const [nextAppState, appStateContainsVisibleChange] =
|
||||||
this.appStateChange.applyTo(appState, nextElements);
|
this.appStateChange.applyTo(appState, nextElements);
|
||||||
|
|
|
@ -44,7 +44,6 @@ import { queryByText } from "@testing-library/react";
|
||||||
import { HistoryEntry } from "../history";
|
import { HistoryEntry } from "../history";
|
||||||
import { AppStateChange, ElementsChange } from "../change";
|
import { AppStateChange, ElementsChange } from "../change";
|
||||||
import { Snapshot, StoreAction } from "../store";
|
import { Snapshot, StoreAction } from "../store";
|
||||||
import type Scene from "../scene/Scene";
|
|
||||||
|
|
||||||
const { h } = window;
|
const { h } = window;
|
||||||
|
|
||||||
|
@ -118,7 +117,6 @@ describe("history", () => {
|
||||||
arrayToMap(h.elements) as SceneElementsMap,
|
arrayToMap(h.elements) as SceneElementsMap,
|
||||||
appState,
|
appState,
|
||||||
Snapshot.empty(),
|
Snapshot.empty(),
|
||||||
{} as Scene,
|
|
||||||
) as any,
|
) as any,
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -140,7 +138,6 @@ describe("history", () => {
|
||||||
arrayToMap(h.elements) as SceneElementsMap,
|
arrayToMap(h.elements) as SceneElementsMap,
|
||||||
appState,
|
appState,
|
||||||
Snapshot.empty(),
|
Snapshot.empty(),
|
||||||
{} as Scene,
|
|
||||||
) as any,
|
) as any,
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import type {
|
||||||
ExcalidrawLinearElement,
|
ExcalidrawLinearElement,
|
||||||
ExcalidrawTextElementWithContainer,
|
ExcalidrawTextElementWithContainer,
|
||||||
FontString,
|
FontString,
|
||||||
|
SceneElementsMap,
|
||||||
} from "../element/types";
|
} from "../element/types";
|
||||||
import { Excalidraw, mutateElement } from "../index";
|
import { Excalidraw, mutateElement } from "../index";
|
||||||
import { centerPoint } from "../math";
|
import { centerPoint } from "../math";
|
||||||
|
@ -1344,7 +1345,7 @@ describe("Test Linear Elements", () => {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
h.scene,
|
new Map() as SceneElementsMap,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
expect(line.x).toBe(origStartX + 10);
|
expect(line.x).toBe(origStartX + 10);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue