confirm arrow on doubleclick (#949)
* confirm arrow on double click * change hint * fix cursor not updating on click
This commit is contained in:
parent
254a0753ff
commit
b7da524538
@ -18,12 +18,15 @@ export const actionFinalize = register({
|
||||
if (appState.multiElement) {
|
||||
// pen and mouse have hover
|
||||
if (appState.lastPointerDownWith !== "touch") {
|
||||
mutateElement(appState.multiElement, {
|
||||
points: appState.multiElement.points.slice(
|
||||
0,
|
||||
appState.multiElement.points.length - 1,
|
||||
),
|
||||
});
|
||||
const { points, lastCommittedPoint } = appState.multiElement;
|
||||
if (
|
||||
!lastCommittedPoint ||
|
||||
points[points.length - 1] !== lastCommittedPoint
|
||||
) {
|
||||
mutateElement(appState.multiElement, {
|
||||
points: appState.multiElement.points.slice(0, -1),
|
||||
});
|
||||
}
|
||||
}
|
||||
if (isInvisiblySmallElement(appState.multiElement)) {
|
||||
newElements = newElements.slice(0, -1);
|
||||
|
@ -60,6 +60,16 @@ export class ActionManager implements ActionsManagerInterface {
|
||||
return true;
|
||||
}
|
||||
|
||||
executeAction(action: Action) {
|
||||
const commitToHistory =
|
||||
action.commitToHistory &&
|
||||
action.commitToHistory(this.getAppState(), this.getElements());
|
||||
this.updater(
|
||||
action.perform(this.getElements(), this.getAppState(), null),
|
||||
commitToHistory,
|
||||
);
|
||||
}
|
||||
|
||||
getContextMenuItems(actionFilter: ActionFilterFn = action => action) {
|
||||
return Object.values(this.actions)
|
||||
.filter(actionFilter)
|
||||
|
@ -92,6 +92,7 @@ import {
|
||||
POINTER_BUTTON,
|
||||
DRAGGING_THRESHOLD,
|
||||
TEXT_TO_CENTER_SNAP_THRESHOLD,
|
||||
ARROW_CONFIRM_THRESHOLD,
|
||||
} from "../constants";
|
||||
import { LayerUI } from "./LayerUI";
|
||||
import { ScrollBars } from "../scene/types";
|
||||
@ -102,6 +103,7 @@ import { unstable_batchedUpdates } from "react-dom";
|
||||
import { SceneStateCallbackRemover } from "../scene/globalScene";
|
||||
import { isLinearElement } from "../element/typeChecks";
|
||||
import { rescalePoints } from "../points";
|
||||
import { actionFinalize } from "../actions";
|
||||
|
||||
function withBatchedUpdates<
|
||||
TFunction extends ((event: any) => void) | (() => void)
|
||||
@ -1122,13 +1124,52 @@ export class App extends React.Component<any, AppState> {
|
||||
);
|
||||
if (this.state.multiElement) {
|
||||
const { multiElement } = this.state;
|
||||
const originX = multiElement.x;
|
||||
const originY = multiElement.y;
|
||||
const points = multiElement.points;
|
||||
const { x: rx, y: ry } = multiElement;
|
||||
|
||||
mutateElement(multiElement, {
|
||||
points: [...points.slice(0, -1), [x - originX, y - originY]],
|
||||
});
|
||||
const { points, lastCommittedPoint } = multiElement;
|
||||
const lastPoint = points[points.length - 1];
|
||||
|
||||
setCursorForShape(this.state.elementType);
|
||||
|
||||
if (lastPoint === lastCommittedPoint) {
|
||||
// if we haven't yet created a temp point and we're beyond commit-zone
|
||||
// threshold, add a point
|
||||
if (
|
||||
distance2d(x - rx, y - ry, lastPoint[0], lastPoint[1]) >=
|
||||
ARROW_CONFIRM_THRESHOLD
|
||||
) {
|
||||
mutateElement(multiElement, {
|
||||
points: [...points, [x - rx, y - ry]],
|
||||
});
|
||||
} else {
|
||||
document.documentElement.style.cursor = CURSOR_TYPE.POINTER;
|
||||
// in this branch, we're inside the commit zone, and no uncommitted
|
||||
// point exists. Thus do nothing (don't add/remove points).
|
||||
}
|
||||
} else {
|
||||
// cursor moved inside commit zone, and there's uncommitted point,
|
||||
// thus remove it
|
||||
if (
|
||||
points.length > 2 &&
|
||||
lastCommittedPoint &&
|
||||
distance2d(
|
||||
x - rx,
|
||||
y - ry,
|
||||
lastCommittedPoint[0],
|
||||
lastCommittedPoint[1],
|
||||
) < ARROW_CONFIRM_THRESHOLD
|
||||
) {
|
||||
document.documentElement.style.cursor = CURSOR_TYPE.POINTER;
|
||||
mutateElement(multiElement, {
|
||||
points: points.slice(0, -1),
|
||||
});
|
||||
} else {
|
||||
// update last uncommitted point
|
||||
mutateElement(multiElement, {
|
||||
points: [...points.slice(0, -1), [x - rx, y - ry]],
|
||||
});
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1505,16 +1546,36 @@ export class App extends React.Component<any, AppState> {
|
||||
) {
|
||||
if (this.state.multiElement) {
|
||||
const { multiElement } = this.state;
|
||||
const { x: rx, y: ry } = multiElement;
|
||||
|
||||
const { x: rx, y: ry, lastCommittedPoint } = multiElement;
|
||||
|
||||
// clicking inside commit zone → finalize arrow
|
||||
if (
|
||||
multiElement.points.length > 1 &&
|
||||
lastCommittedPoint &&
|
||||
distance2d(
|
||||
x - rx,
|
||||
y - ry,
|
||||
lastCommittedPoint[0],
|
||||
lastCommittedPoint[1],
|
||||
) < ARROW_CONFIRM_THRESHOLD
|
||||
) {
|
||||
this.actionManager.executeAction(actionFinalize);
|
||||
return;
|
||||
}
|
||||
this.setState(prevState => ({
|
||||
selectedElementIds: {
|
||||
...prevState.selectedElementIds,
|
||||
[multiElement.id]: true,
|
||||
},
|
||||
}));
|
||||
// clicking outside commit zone → update reference for last committed
|
||||
// point
|
||||
mutateElement(multiElement, {
|
||||
points: [...multiElement.points, [x - rx, y - ry]],
|
||||
lastCommittedPoint:
|
||||
multiElement.points[multiElement.points.length - 1],
|
||||
});
|
||||
document.documentElement.style.cursor = CURSOR_TYPE.POINTER;
|
||||
} else {
|
||||
const element = newLinearElement({
|
||||
type: this.state.elementType,
|
||||
|
@ -1,4 +1,5 @@
|
||||
export const DRAGGING_THRESHOLD = 10; // 10px
|
||||
export const ARROW_CONFIRM_THRESHOLD = 10; // 10px
|
||||
export const ELEMENT_SHIFT_TRANSLATE_AMOUNT = 5;
|
||||
export const ELEMENT_TRANSLATE_AMOUNT = 1;
|
||||
export const TEXT_TO_CENTER_SNAP_THRESHOLD = 30;
|
||||
@ -6,6 +7,7 @@ export const CURSOR_TYPE = {
|
||||
TEXT: "text",
|
||||
CROSSHAIR: "crosshair",
|
||||
GRABBING: "grabbing",
|
||||
POINTER: "pointer",
|
||||
};
|
||||
export const POINTER_BUTTON = {
|
||||
MAIN: 0,
|
||||
|
@ -91,12 +91,14 @@ export function newTextElement(
|
||||
|
||||
export function newLinearElement(
|
||||
opts: {
|
||||
type: "arrow" | "line";
|
||||
type: ExcalidrawLinearElement["type"];
|
||||
lastCommittedPoint?: ExcalidrawLinearElement["lastCommittedPoint"];
|
||||
} & ElementConstructorOpts,
|
||||
): ExcalidrawLinearElement {
|
||||
return {
|
||||
..._newElementBase<ExcalidrawLinearElement>(opts.type, opts),
|
||||
points: [],
|
||||
lastCommittedPoint: opts.lastCommittedPoint || null,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,7 @@ export type ExcalidrawLinearElement = _ExcalidrawElementBase &
|
||||
Readonly<{
|
||||
type: "arrow" | "line";
|
||||
points: Point[];
|
||||
lastCommittedPoint?: Point | null;
|
||||
}>;
|
||||
|
||||
export type PointerType = "mouse" | "pen" | "touch";
|
||||
|
@ -95,7 +95,7 @@
|
||||
},
|
||||
"hints": {
|
||||
"linearElement": "Click to start multiple points, drag for single line",
|
||||
"linearElementMulti": "Press Escape or Enter to finish",
|
||||
"linearElementMulti": "Click on last point or press Escape or Enter to finish",
|
||||
"resize": "You can constraint proportions by holding SHIFT while resizing"
|
||||
},
|
||||
"errorSplash": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user