Refactor binding suggestions
This commit is contained in:
parent
95d89a751a
commit
9af3177dbd
@ -398,6 +398,51 @@ export const getSuggestedBindingsForArrows = (
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const maybeSuggestBindingsForLinearElementAtCoords = (
|
||||||
|
linearElement: NonDeleted<ExcalidrawLinearElement>,
|
||||||
|
/** scene coords */
|
||||||
|
pointerCoords: {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
}[],
|
||||||
|
scene: Scene,
|
||||||
|
zoom: AppState["zoom"],
|
||||||
|
// During line creation the start binding hasn't been written yet
|
||||||
|
// into `linearElement`
|
||||||
|
oppositeBindingBoundElement?: ExcalidrawBindableElement | null,
|
||||||
|
): ExcalidrawBindableElement[] => {
|
||||||
|
if (!pointerCoords.length) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const suggestedBindings = pointerCoords.reduce(
|
||||||
|
(acc: NonDeleted<ExcalidrawBindableElement>[], coords) => {
|
||||||
|
const hoveredBindableElement = getHoveredElementForBinding(
|
||||||
|
coords,
|
||||||
|
scene.getNonDeletedElements(),
|
||||||
|
scene.getNonDeletedElementsMap(),
|
||||||
|
zoom,
|
||||||
|
isElbowArrow(linearElement),
|
||||||
|
isElbowArrow(linearElement),
|
||||||
|
);
|
||||||
|
if (
|
||||||
|
hoveredBindableElement != null &&
|
||||||
|
!isLinearElementSimpleAndAlreadyBound(
|
||||||
|
linearElement,
|
||||||
|
oppositeBindingBoundElement?.id,
|
||||||
|
hoveredBindableElement,
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
acc.push(hoveredBindableElement);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
return suggestedBindings;
|
||||||
|
};
|
||||||
|
|
||||||
export const maybeBindLinearElement = (
|
export const maybeBindLinearElement = (
|
||||||
linearElement: NonDeleted<ExcalidrawLinearElement>,
|
linearElement: NonDeleted<ExcalidrawLinearElement>,
|
||||||
appState: AppState,
|
appState: AppState,
|
||||||
|
@ -39,6 +39,7 @@ import {
|
|||||||
bindOrUnbindLinearElement,
|
bindOrUnbindLinearElement,
|
||||||
getHoveredElementForBinding,
|
getHoveredElementForBinding,
|
||||||
isBindingEnabled,
|
isBindingEnabled,
|
||||||
|
maybeSuggestBindingsForLinearElementAtCoords,
|
||||||
} from "./binding";
|
} from "./binding";
|
||||||
import {
|
import {
|
||||||
getElementAbsoluteCoords,
|
getElementAbsoluteCoords,
|
||||||
@ -245,18 +246,13 @@ export class LinearElementEditor {
|
|||||||
app: AppClassProperties,
|
app: AppClassProperties,
|
||||||
scenePointerX: number,
|
scenePointerX: number,
|
||||||
scenePointerY: number,
|
scenePointerY: number,
|
||||||
maybeSuggestBinding: (
|
|
||||||
element: NonDeleted<ExcalidrawLinearElement>,
|
|
||||||
pointSceneCoords: { x: number; y: number }[],
|
|
||||||
) => void,
|
|
||||||
linearElementEditor: LinearElementEditor,
|
linearElementEditor: LinearElementEditor,
|
||||||
scene: Scene,
|
): Pick<AppState, keyof AppState> | null {
|
||||||
): LinearElementEditor | null {
|
|
||||||
if (!linearElementEditor) {
|
if (!linearElementEditor) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const { elementId } = linearElementEditor;
|
const { elementId } = linearElementEditor;
|
||||||
const elementsMap = scene.getNonDeletedElementsMap();
|
const elementsMap = app.scene.getNonDeletedElementsMap();
|
||||||
const element = LinearElementEditor.getElement(elementId, elementsMap);
|
const element = LinearElementEditor.getElement(elementId, elementsMap);
|
||||||
if (!element) {
|
if (!element) {
|
||||||
return null;
|
return null;
|
||||||
@ -309,7 +305,7 @@ export class LinearElementEditor {
|
|||||||
|
|
||||||
LinearElementEditor.movePoints(
|
LinearElementEditor.movePoints(
|
||||||
element,
|
element,
|
||||||
scene,
|
app.scene,
|
||||||
new Map([
|
new Map([
|
||||||
[
|
[
|
||||||
selectedIndex,
|
selectedIndex,
|
||||||
@ -337,7 +333,7 @@ export class LinearElementEditor {
|
|||||||
|
|
||||||
LinearElementEditor.movePoints(
|
LinearElementEditor.movePoints(
|
||||||
element,
|
element,
|
||||||
scene,
|
app.scene,
|
||||||
new Map(
|
new Map(
|
||||||
selectedPointsIndices.map((pointIndex) => {
|
selectedPointsIndices.map((pointIndex) => {
|
||||||
const newPointPosition: LocalPoint =
|
const newPointPosition: LocalPoint =
|
||||||
@ -369,10 +365,11 @@ export class LinearElementEditor {
|
|||||||
|
|
||||||
const boundTextElement = getBoundTextElement(element, elementsMap);
|
const boundTextElement = getBoundTextElement(element, elementsMap);
|
||||||
if (boundTextElement) {
|
if (boundTextElement) {
|
||||||
handleBindTextResize(element, scene, false);
|
handleBindTextResize(element, app.scene, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// suggest bindings for first and last point if selected
|
// suggest bindings for first and last point if selected
|
||||||
|
let suggestedBindings: ExcalidrawBindableElement[] = [];
|
||||||
if (isBindingElement(element, false)) {
|
if (isBindingElement(element, false)) {
|
||||||
const coords: { x: number; y: number }[] = [];
|
const coords: { x: number; y: number }[] = [];
|
||||||
|
|
||||||
@ -404,11 +401,16 @@ export class LinearElementEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (coords.length) {
|
if (coords.length) {
|
||||||
maybeSuggestBinding(element, coords);
|
suggestedBindings = maybeSuggestBindingsForLinearElementAtCoords(
|
||||||
|
element,
|
||||||
|
coords,
|
||||||
|
app.scene,
|
||||||
|
app.state.zoom,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
const newLinearElementEditor = {
|
||||||
...linearElementEditor,
|
...linearElementEditor,
|
||||||
selectedPointsIndices,
|
selectedPointsIndices,
|
||||||
segmentMidPointHoveredCoords:
|
segmentMidPointHoveredCoords:
|
||||||
@ -427,6 +429,15 @@ export class LinearElementEditor {
|
|||||||
: -1,
|
: -1,
|
||||||
isDragging: true,
|
isDragging: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
...app.state,
|
||||||
|
editingLinearElement: app.state.editingLinearElement
|
||||||
|
? newLinearElementEditor
|
||||||
|
: null,
|
||||||
|
selectedLinearElement: newLinearElementEditor,
|
||||||
|
suggestedBindings,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -104,7 +104,11 @@ import {
|
|||||||
Emitter,
|
Emitter,
|
||||||
} from "@excalidraw/common";
|
} from "@excalidraw/common";
|
||||||
|
|
||||||
import { getCommonBounds, getElementAbsoluteCoords } from "@excalidraw/element";
|
import {
|
||||||
|
getCommonBounds,
|
||||||
|
getElementAbsoluteCoords,
|
||||||
|
maybeSuggestBindingsForLinearElementAtCoords,
|
||||||
|
} from "@excalidraw/element";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
bindOrUnbindLinearElement,
|
bindOrUnbindLinearElement,
|
||||||
@ -112,7 +116,6 @@ import {
|
|||||||
fixBindingsAfterDeletion,
|
fixBindingsAfterDeletion,
|
||||||
getHoveredElementForBinding,
|
getHoveredElementForBinding,
|
||||||
isBindingEnabled,
|
isBindingEnabled,
|
||||||
isLinearElementSimpleAndAlreadyBound,
|
|
||||||
maybeBindLinearElement,
|
maybeBindLinearElement,
|
||||||
shouldEnableBindingForPointerEvent,
|
shouldEnableBindingForPointerEvent,
|
||||||
updateBoundElements,
|
updateBoundElements,
|
||||||
@ -299,7 +302,6 @@ import type { ElementUpdate } from "@excalidraw/element";
|
|||||||
import type { LocalPoint, Radians } from "@excalidraw/math";
|
import type { LocalPoint, Radians } from "@excalidraw/math";
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
ExcalidrawBindableElement,
|
|
||||||
ExcalidrawElement,
|
ExcalidrawElement,
|
||||||
ExcalidrawFreeDrawElement,
|
ExcalidrawFreeDrawElement,
|
||||||
ExcalidrawGenericElement,
|
ExcalidrawGenericElement,
|
||||||
@ -5961,11 +5963,15 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
// and point
|
// and point
|
||||||
const { newElement } = this.state;
|
const { newElement } = this.state;
|
||||||
if (isBindingElement(newElement, false)) {
|
if (isBindingElement(newElement, false)) {
|
||||||
this.maybeSuggestBindingsForLinearElementAtCoords(
|
this.setState({
|
||||||
newElement,
|
suggestedBindings: maybeSuggestBindingsForLinearElementAtCoords(
|
||||||
[scenePointer],
|
newElement,
|
||||||
this.state.startBoundElement,
|
[scenePointer],
|
||||||
);
|
this.scene,
|
||||||
|
this.state.zoom,
|
||||||
|
this.state.startBoundElement,
|
||||||
|
),
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
this.maybeSuggestBindingAtCursor(scenePointer, false);
|
this.maybeSuggestBindingAtCursor(scenePointer, false);
|
||||||
}
|
}
|
||||||
@ -8251,31 +8257,19 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const newLinearElementEditor = LinearElementEditor.handlePointDragging(
|
const newState = LinearElementEditor.handlePointDragging(
|
||||||
event,
|
event,
|
||||||
this,
|
this,
|
||||||
pointerCoords.x,
|
pointerCoords.x,
|
||||||
pointerCoords.y,
|
pointerCoords.y,
|
||||||
(element, pointsSceneCoords) => {
|
|
||||||
this.maybeSuggestBindingsForLinearElementAtCoords(
|
|
||||||
element,
|
|
||||||
pointsSceneCoords,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
linearElementEditor,
|
linearElementEditor,
|
||||||
this.scene,
|
|
||||||
);
|
);
|
||||||
if (newLinearElementEditor) {
|
if (newState) {
|
||||||
pointerDownState.lastCoords.x = pointerCoords.x;
|
pointerDownState.lastCoords.x = pointerCoords.x;
|
||||||
pointerDownState.lastCoords.y = pointerCoords.y;
|
pointerDownState.lastCoords.y = pointerCoords.y;
|
||||||
pointerDownState.drag.hasOccurred = true;
|
pointerDownState.drag.hasOccurred = true;
|
||||||
|
|
||||||
this.setState({
|
this.setState(newState);
|
||||||
editingLinearElement: this.state.editingLinearElement
|
|
||||||
? newLinearElementEditor
|
|
||||||
: null,
|
|
||||||
selectedLinearElement: newLinearElementEditor,
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -8754,11 +8748,15 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
|
|
||||||
if (isBindingElement(newElement, false)) {
|
if (isBindingElement(newElement, false)) {
|
||||||
// When creating a linear element by dragging
|
// When creating a linear element by dragging
|
||||||
this.maybeSuggestBindingsForLinearElementAtCoords(
|
this.setState({
|
||||||
newElement,
|
suggestedBindings: maybeSuggestBindingsForLinearElementAtCoords(
|
||||||
[pointerCoords],
|
newElement,
|
||||||
this.state.startBoundElement,
|
[pointerCoords],
|
||||||
);
|
this.scene,
|
||||||
|
this.state.zoom,
|
||||||
|
this.state.startBoundElement,
|
||||||
|
),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pointerDownState.lastCoords.x = pointerCoords.x;
|
pointerDownState.lastCoords.x = pointerCoords.x;
|
||||||
@ -10285,49 +10283,6 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
private maybeSuggestBindingsForLinearElementAtCoords = (
|
|
||||||
linearElement: NonDeleted<ExcalidrawLinearElement>,
|
|
||||||
/** scene coords */
|
|
||||||
pointerCoords: {
|
|
||||||
x: number;
|
|
||||||
y: number;
|
|
||||||
}[],
|
|
||||||
// During line creation the start binding hasn't been written yet
|
|
||||||
// into `linearElement`
|
|
||||||
oppositeBindingBoundElement?: ExcalidrawBindableElement | null,
|
|
||||||
): void => {
|
|
||||||
if (!pointerCoords.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const suggestedBindings = pointerCoords.reduce(
|
|
||||||
(acc: NonDeleted<ExcalidrawBindableElement>[], coords) => {
|
|
||||||
const hoveredBindableElement = getHoveredElementForBinding(
|
|
||||||
coords,
|
|
||||||
this.scene.getNonDeletedElements(),
|
|
||||||
this.scene.getNonDeletedElementsMap(),
|
|
||||||
this.state.zoom,
|
|
||||||
isElbowArrow(linearElement),
|
|
||||||
isElbowArrow(linearElement),
|
|
||||||
);
|
|
||||||
if (
|
|
||||||
hoveredBindableElement != null &&
|
|
||||||
!isLinearElementSimpleAndAlreadyBound(
|
|
||||||
linearElement,
|
|
||||||
oppositeBindingBoundElement?.id,
|
|
||||||
hoveredBindableElement,
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
acc.push(hoveredBindableElement);
|
|
||||||
}
|
|
||||||
return acc;
|
|
||||||
},
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
this.setState({ suggestedBindings });
|
|
||||||
};
|
|
||||||
|
|
||||||
private clearSelection(hitElement: ExcalidrawElement | null): void {
|
private clearSelection(hitElement: ExcalidrawElement | null): void {
|
||||||
this.setState((prevState) => ({
|
this.setState((prevState) => ({
|
||||||
selectedElementIds: makeNextSelectedElementIds({}, prevState),
|
selectedElementIds: makeNextSelectedElementIds({}, prevState),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user