|
|
|
@ -105,12 +105,12 @@ import { |
|
|
|
import { |
|
|
|
import { |
|
|
|
getObservedAppState, |
|
|
|
getObservedAppState, |
|
|
|
getCommonBounds, |
|
|
|
getCommonBounds, |
|
|
|
|
|
|
|
maybeSuggestBindingsForLinearElementAtCoords, |
|
|
|
getElementAbsoluteCoords, |
|
|
|
getElementAbsoluteCoords, |
|
|
|
bindOrUnbindLinearElements, |
|
|
|
bindOrUnbindLinearElements, |
|
|
|
fixBindingsAfterDeletion, |
|
|
|
fixBindingsAfterDeletion, |
|
|
|
getHoveredElementForBinding, |
|
|
|
getHoveredElementForBinding, |
|
|
|
isBindingEnabled, |
|
|
|
isBindingEnabled, |
|
|
|
isLinearElementSimpleAndAlreadyBound, |
|
|
|
|
|
|
|
shouldEnableBindingForPointerEvent, |
|
|
|
shouldEnableBindingForPointerEvent, |
|
|
|
updateBoundElements, |
|
|
|
updateBoundElements, |
|
|
|
getSuggestedBindingsForArrows, |
|
|
|
getSuggestedBindingsForArrows, |
|
|
|
@ -237,7 +237,6 @@ import { |
|
|
|
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, |
|
|
|
@ -5883,11 +5882,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); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -8217,31 +8220,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; |
|
|
|
} |
|
|
|
} |
|
|
|
@ -8720,11 +8711,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; |
|
|
|
@ -8919,16 +8914,17 @@ class App extends React.Component<AppProps, AppState> { |
|
|
|
|
|
|
|
|
|
|
|
const hitElements = pointerDownState.hit.allHitElements; |
|
|
|
const hitElements = pointerDownState.hit.allHitElements; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const sceneCoords = viewportCoordsToSceneCoords( |
|
|
|
|
|
|
|
{ clientX: childEvent.clientX, clientY: childEvent.clientY }, |
|
|
|
|
|
|
|
this.state, |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
if ( |
|
|
|
if ( |
|
|
|
this.state.activeTool.type === "selection" && |
|
|
|
this.state.activeTool.type === "selection" && |
|
|
|
!pointerDownState.boxSelection.hasOccurred && |
|
|
|
!pointerDownState.boxSelection.hasOccurred && |
|
|
|
!pointerDownState.resize.isResizing && |
|
|
|
!pointerDownState.resize.isResizing && |
|
|
|
!hitElements.some((el) => this.state.selectedElementIds[el.id]) |
|
|
|
!hitElements.some((el) => this.state.selectedElementIds[el.id]) |
|
|
|
) { |
|
|
|
) { |
|
|
|
const sceneCoords = viewportCoordsToSceneCoords( |
|
|
|
|
|
|
|
{ clientX: childEvent.clientX, clientY: childEvent.clientY }, |
|
|
|
|
|
|
|
this.state, |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
const hitLockedElement = this.getElementAtPosition( |
|
|
|
const hitLockedElement = this.getElementAtPosition( |
|
|
|
sceneCoords.x, |
|
|
|
sceneCoords.x, |
|
|
|
sceneCoords.y, |
|
|
|
sceneCoords.y, |
|
|
|
@ -9029,6 +9025,7 @@ class App extends React.Component<AppProps, AppState> { |
|
|
|
} else if (this.state.selectedLinearElement.isDragging) { |
|
|
|
} else if (this.state.selectedLinearElement.isDragging) { |
|
|
|
this.actionManager.executeAction(actionFinalize, "ui", { |
|
|
|
this.actionManager.executeAction(actionFinalize, "ui", { |
|
|
|
event: childEvent, |
|
|
|
event: childEvent, |
|
|
|
|
|
|
|
sceneCoords, |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -9123,7 +9120,10 @@ class App extends React.Component<AppProps, AppState> { |
|
|
|
isBindingEnabled(this.state) && |
|
|
|
isBindingEnabled(this.state) && |
|
|
|
isBindingElement(newElement, false) |
|
|
|
isBindingElement(newElement, false) |
|
|
|
) { |
|
|
|
) { |
|
|
|
this.actionManager.executeAction(actionFinalize); |
|
|
|
this.actionManager.executeAction(actionFinalize, "ui", { |
|
|
|
|
|
|
|
event: childEvent, |
|
|
|
|
|
|
|
sceneCoords, |
|
|
|
|
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
this.setState({ suggestedBindings: [], startBoundElement: null }); |
|
|
|
this.setState({ suggestedBindings: [], startBoundElement: null }); |
|
|
|
if (!activeTool.locked) { |
|
|
|
if (!activeTool.locked) { |
|
|
|
@ -9706,7 +9706,8 @@ class App extends React.Component<AppProps, AppState> { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if ( |
|
|
|
if ( |
|
|
|
pointerDownState.drag.hasOccurred || |
|
|
|
(pointerDownState.drag.hasOccurred && |
|
|
|
|
|
|
|
!this.state.selectedLinearElement) || |
|
|
|
isResizing || |
|
|
|
isResizing || |
|
|
|
isRotating || |
|
|
|
isRotating || |
|
|
|
isCropping |
|
|
|
isCropping |
|
|
|
@ -10172,49 +10173,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), |
|
|
|
|