|
|
|
|
@ -15,7 +15,7 @@ import {
@@ -15,7 +15,7 @@ import {
|
|
|
|
|
import BinaryHeap from "../binaryheap"; |
|
|
|
|
import { getSizeFromPoints } from "../points"; |
|
|
|
|
import { aabbForElement, pointInsideBounds } from "../shapes"; |
|
|
|
|
import { invariant, isAnyTrue, toBrandedType, tupleToCoors } from "../utils"; |
|
|
|
|
import { invariant, isAnyTrue, tupleToCoors } from "../utils"; |
|
|
|
|
import type { AppState } from "../types"; |
|
|
|
|
import { |
|
|
|
|
bindPointToSnapToElementOutline, |
|
|
|
|
@ -52,6 +52,7 @@ import type {
@@ -52,6 +52,7 @@ import type {
|
|
|
|
|
ExcalidrawBindableElement, |
|
|
|
|
FixedPointBinding, |
|
|
|
|
FixedSegment, |
|
|
|
|
NonDeletedExcalidrawElement, |
|
|
|
|
} from "./types"; |
|
|
|
|
import { distanceToBindableElement } from "./distance"; |
|
|
|
|
|
|
|
|
|
@ -101,7 +102,7 @@ export const BASE_PADDING = 40;
@@ -101,7 +102,7 @@ export const BASE_PADDING = 40;
|
|
|
|
|
|
|
|
|
|
const handleSegmentRenormalization = ( |
|
|
|
|
arrow: ExcalidrawElbowArrowElement, |
|
|
|
|
elementsMap: NonDeletedSceneElementsMap | SceneElementsMap, |
|
|
|
|
elementsMap: NonDeletedSceneElementsMap, |
|
|
|
|
) => { |
|
|
|
|
const nextFixedSegments: FixedSegment[] | null = arrow.fixedSegments |
|
|
|
|
? arrow.fixedSegments.slice() |
|
|
|
|
@ -234,6 +235,16 @@ const handleSegmentRenormalization = (
@@ -234,6 +235,16 @@ const handleSegmentRenormalization = (
|
|
|
|
|
nextPoints.map((p) => |
|
|
|
|
pointFrom<LocalPoint>(p[0] - arrow.x, p[1] - arrow.y), |
|
|
|
|
), |
|
|
|
|
arrow.startBinding && |
|
|
|
|
getBindableElementForId( |
|
|
|
|
arrow.startBinding.elementId, |
|
|
|
|
elementsMap, |
|
|
|
|
), |
|
|
|
|
arrow.endBinding && |
|
|
|
|
getBindableElementForId( |
|
|
|
|
arrow.endBinding.elementId, |
|
|
|
|
elementsMap, |
|
|
|
|
), |
|
|
|
|
), |
|
|
|
|
) ?? [], |
|
|
|
|
), |
|
|
|
|
@ -271,7 +282,7 @@ const handleSegmentRenormalization = (
@@ -271,7 +282,7 @@ const handleSegmentRenormalization = (
|
|
|
|
|
const handleSegmentRelease = ( |
|
|
|
|
arrow: ExcalidrawElbowArrowElement, |
|
|
|
|
fixedSegments: readonly FixedSegment[], |
|
|
|
|
elementsMap: NonDeletedSceneElementsMap | SceneElementsMap, |
|
|
|
|
elementsMap: NonDeletedSceneElementsMap, |
|
|
|
|
) => { |
|
|
|
|
const newFixedSegmentIndices = fixedSegments.map((segment) => segment.index); |
|
|
|
|
const oldFixedSegmentIndices = |
|
|
|
|
@ -295,6 +306,8 @@ const handleSegmentRelease = (
@@ -295,6 +306,8 @@ const handleSegmentRelease = (
|
|
|
|
|
// We need to render a sub-arrow path to restore deleted segments
|
|
|
|
|
const x = arrow.x + (prevSegment ? prevSegment.end[0] : 0); |
|
|
|
|
const y = arrow.y + (prevSegment ? prevSegment.end[1] : 0); |
|
|
|
|
const startBinding = prevSegment ? null : arrow.startBinding; |
|
|
|
|
const endBinding = nextSegment ? null : arrow.endBinding; |
|
|
|
|
const { |
|
|
|
|
startHeading, |
|
|
|
|
endHeading, |
|
|
|
|
@ -307,10 +320,11 @@ const handleSegmentRelease = (
@@ -307,10 +320,11 @@ const handleSegmentRelease = (
|
|
|
|
|
{ |
|
|
|
|
x, |
|
|
|
|
y, |
|
|
|
|
startBinding: prevSegment ? null : arrow.startBinding, |
|
|
|
|
endBinding: nextSegment ? null : arrow.endBinding, |
|
|
|
|
startBinding, |
|
|
|
|
endBinding, |
|
|
|
|
startArrowhead: null, |
|
|
|
|
endArrowhead: null, |
|
|
|
|
points: arrow.points, |
|
|
|
|
}, |
|
|
|
|
elementsMap, |
|
|
|
|
[ |
|
|
|
|
@ -324,6 +338,9 @@ const handleSegmentRelease = (
@@ -324,6 +338,9 @@ const handleSegmentRelease = (
|
|
|
|
|
y, |
|
|
|
|
), |
|
|
|
|
], |
|
|
|
|
startBinding && |
|
|
|
|
getBindableElementForId(startBinding.elementId, elementsMap), |
|
|
|
|
endBinding && getBindableElementForId(endBinding.elementId, elementsMap), |
|
|
|
|
{ isDragging: false }, |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
@ -870,7 +887,7 @@ const MAX_POS = 1e6;
@@ -870,7 +887,7 @@ const MAX_POS = 1e6;
|
|
|
|
|
*/ |
|
|
|
|
export const updateElbowArrowPoints = ( |
|
|
|
|
arrow: Readonly<ExcalidrawElbowArrowElement>, |
|
|
|
|
elementsMap: NonDeletedSceneElementsMap | SceneElementsMap, |
|
|
|
|
elementsMap: NonDeletedSceneElementsMap, |
|
|
|
|
updates: { |
|
|
|
|
points?: readonly LocalPoint[]; |
|
|
|
|
fixedSegments?: FixedSegment[] | null; |
|
|
|
|
@ -986,8 +1003,11 @@ export const updateElbowArrowPoints = (
@@ -986,8 +1003,11 @@ export const updateElbowArrowPoints = (
|
|
|
|
|
typeof updates.endBinding !== "undefined" |
|
|
|
|
? updates.endBinding |
|
|
|
|
: arrow.endBinding; |
|
|
|
|
const startElement = startBinding && elementsMap.get(startBinding.elementId); |
|
|
|
|
const endElement = endBinding && elementsMap.get(endBinding.elementId); |
|
|
|
|
const startElement = |
|
|
|
|
startBinding && |
|
|
|
|
getBindableElementForId(startBinding.elementId, elementsMap); |
|
|
|
|
const endElement = |
|
|
|
|
endBinding && getBindableElementForId(endBinding.elementId, elementsMap); |
|
|
|
|
if ( |
|
|
|
|
(elementsMap.size === 0 && validateElbowPoints(updatedPoints)) || |
|
|
|
|
startElement?.id !== startBinding?.elementId || |
|
|
|
|
@ -1019,9 +1039,12 @@ export const updateElbowArrowPoints = (
@@ -1019,9 +1039,12 @@ export const updateElbowArrowPoints = (
|
|
|
|
|
endBinding, |
|
|
|
|
startArrowhead: arrow.startArrowhead, |
|
|
|
|
endArrowhead: arrow.endArrowhead, |
|
|
|
|
points: arrow.points, |
|
|
|
|
}, |
|
|
|
|
elementsMap, |
|
|
|
|
updatedPoints, |
|
|
|
|
startElement, |
|
|
|
|
endElement, |
|
|
|
|
options, |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
@ -1155,9 +1178,12 @@ const getElbowArrowData = (
@@ -1155,9 +1178,12 @@ const getElbowArrowData = (
|
|
|
|
|
endBinding: FixedPointBinding | null; |
|
|
|
|
startArrowhead: Arrowhead | null; |
|
|
|
|
endArrowhead: Arrowhead | null; |
|
|
|
|
points: readonly LocalPoint[]; |
|
|
|
|
}, |
|
|
|
|
elementsMap: NonDeletedSceneElementsMap | SceneElementsMap, |
|
|
|
|
elementsMap: NonDeletedSceneElementsMap, |
|
|
|
|
nextPoints: readonly LocalPoint[], |
|
|
|
|
startElement: ExcalidrawBindableElement | null, |
|
|
|
|
endElement: ExcalidrawBindableElement | null, |
|
|
|
|
options?: { |
|
|
|
|
isDragging?: boolean; |
|
|
|
|
zoom?: AppState["zoom"]; |
|
|
|
|
@ -1171,20 +1197,27 @@ const getElbowArrowData = (
@@ -1171,20 +1197,27 @@ const getElbowArrowData = (
|
|
|
|
|
LocalPoint, |
|
|
|
|
GlobalPoint |
|
|
|
|
>(nextPoints[nextPoints.length - 1], vector(arrow.x, arrow.y)); |
|
|
|
|
const startElement = |
|
|
|
|
arrow.startBinding && |
|
|
|
|
getBindableElementForId(arrow.startBinding.elementId, elementsMap); |
|
|
|
|
const endElement = |
|
|
|
|
arrow.endBinding && |
|
|
|
|
getBindableElementForId(arrow.endBinding.elementId, elementsMap); |
|
|
|
|
const [hoveredStartElement, hoveredEndElement] = options?.isDragging |
|
|
|
|
? getHoveredElements( |
|
|
|
|
|
|
|
|
|
let hoveredStartElement = startElement; |
|
|
|
|
let hoveredEndElement = endElement; |
|
|
|
|
if (options?.isDragging) { |
|
|
|
|
const elements = Array.from(elementsMap.values()); |
|
|
|
|
hoveredStartElement = |
|
|
|
|
getHoveredElement( |
|
|
|
|
origStartGlobalPoint, |
|
|
|
|
elementsMap, |
|
|
|
|
elements, |
|
|
|
|
options?.zoom, |
|
|
|
|
) || startElement; |
|
|
|
|
hoveredEndElement = |
|
|
|
|
getHoveredElement( |
|
|
|
|
origEndGlobalPoint, |
|
|
|
|
elementsMap, |
|
|
|
|
elements, |
|
|
|
|
options?.zoom, |
|
|
|
|
) |
|
|
|
|
: [startElement, endElement]; |
|
|
|
|
) || endElement; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const startGlobalPoint = getGlobalPoint( |
|
|
|
|
{ |
|
|
|
|
...arrow, |
|
|
|
|
@ -2214,36 +2247,20 @@ const getBindPointHeading = (
@@ -2214,36 +2247,20 @@ const getBindPointHeading = (
|
|
|
|
|
origPoint, |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
const getHoveredElements = ( |
|
|
|
|
origStartGlobalPoint: GlobalPoint, |
|
|
|
|
origEndGlobalPoint: GlobalPoint, |
|
|
|
|
elementsMap: NonDeletedSceneElementsMap | SceneElementsMap, |
|
|
|
|
const getHoveredElement = ( |
|
|
|
|
origPoint: GlobalPoint, |
|
|
|
|
elementsMap: NonDeletedSceneElementsMap, |
|
|
|
|
elements: readonly NonDeletedExcalidrawElement[], |
|
|
|
|
zoom?: AppState["zoom"], |
|
|
|
|
) => { |
|
|
|
|
// 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)), |
|
|
|
|
return getHoveredElementForBinding( |
|
|
|
|
tupleToCoors(origPoint), |
|
|
|
|
elements, |
|
|
|
|
elementsMap, |
|
|
|
|
zoom, |
|
|
|
|
true, |
|
|
|
|
true, |
|
|
|
|
); |
|
|
|
|
const elements = Array.from(elementsMap.values()); |
|
|
|
|
return [ |
|
|
|
|
getHoveredElementForBinding( |
|
|
|
|
tupleToCoors(origStartGlobalPoint), |
|
|
|
|
elements, |
|
|
|
|
nonDeletedSceneElementsMap, |
|
|
|
|
zoom, |
|
|
|
|
true, |
|
|
|
|
true, |
|
|
|
|
), |
|
|
|
|
getHoveredElementForBinding( |
|
|
|
|
tupleToCoors(origEndGlobalPoint), |
|
|
|
|
elements, |
|
|
|
|
nonDeletedSceneElementsMap, |
|
|
|
|
zoom, |
|
|
|
|
true, |
|
|
|
|
true, |
|
|
|
|
), |
|
|
|
|
]; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const gridAddressesEqual = (a: GridAddress, b: GridAddress): boolean => |
|
|
|
|
|