rebind arrow on rotation (#2096)
This commit is contained in:
parent
0e28177ccc
commit
26ef235019
@ -143,7 +143,6 @@ import {
|
|||||||
isLinearElementType,
|
isLinearElementType,
|
||||||
isBindingElement,
|
isBindingElement,
|
||||||
isBindingElementType,
|
isBindingElementType,
|
||||||
isBindableElement,
|
|
||||||
} from "../element/typeChecks";
|
} from "../element/typeChecks";
|
||||||
import { actionFinalize, actionDeleteSelected } from "../actions";
|
import { actionFinalize, actionDeleteSelected } from "../actions";
|
||||||
import { loadLibrary } from "../data/localStorage";
|
import { loadLibrary } from "../data/localStorage";
|
||||||
@ -168,7 +167,6 @@ import {
|
|||||||
bindOrUnbindSelectedElements,
|
bindOrUnbindSelectedElements,
|
||||||
unbindLinearElements,
|
unbindLinearElements,
|
||||||
fixBindingsAfterDuplication,
|
fixBindingsAfterDuplication,
|
||||||
maybeBindBindableElement,
|
|
||||||
getElligibleElementForBindingElementAtCoors,
|
getElligibleElementForBindingElementAtCoors,
|
||||||
fixBindingsAfterDeletion,
|
fixBindingsAfterDeletion,
|
||||||
isLinearElementSimpleAndAlreadyBound,
|
isLinearElementSimpleAndAlreadyBound,
|
||||||
@ -2946,6 +2944,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
this.maybeSuggestBindingForAll(selectedElements);
|
this.maybeSuggestBindingForAll(selectedElements);
|
||||||
|
bindOrUnbindSelectedElements(selectedElements);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3339,11 +3338,10 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|||||||
getNormalizedDimensions(draggingElement),
|
getNormalizedDimensions(draggingElement),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (
|
if (isBindingEnabled(this.state)) {
|
||||||
isBindingEnabled(this.state) &&
|
bindOrUnbindSelectedElements(
|
||||||
isBindableElement(draggingElement)
|
getSelectedElements(this.scene.getElements(), this.state),
|
||||||
) {
|
);
|
||||||
maybeBindBindableElement(draggingElement);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -997,7 +997,7 @@ Object {
|
|||||||
"versionNonce": 915032327,
|
"versionNonce": 915032327,
|
||||||
"width": 10,
|
"width": 10,
|
||||||
"x": 30,
|
"x": 30,
|
||||||
"y": 30,
|
"y": 0,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -1025,7 +1025,7 @@ Object {
|
|||||||
"versionNonce": 81784553,
|
"versionNonce": 81784553,
|
||||||
"width": 10,
|
"width": 10,
|
||||||
"x": 60,
|
"x": 60,
|
||||||
"y": 60,
|
"y": 0,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -1125,7 +1125,7 @@ Object {
|
|||||||
"versionNonce": 453191,
|
"versionNonce": 453191,
|
||||||
"width": 10,
|
"width": 10,
|
||||||
"x": 30,
|
"x": 30,
|
||||||
"y": 30,
|
"y": 0,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -1191,7 +1191,7 @@ Object {
|
|||||||
"versionNonce": 1116226695,
|
"versionNonce": 1116226695,
|
||||||
"width": 10,
|
"width": 10,
|
||||||
"x": 30,
|
"x": 30,
|
||||||
"y": 30,
|
"y": 0,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -1255,7 +1255,7 @@ Object {
|
|||||||
"versionNonce": 1116226695,
|
"versionNonce": 1116226695,
|
||||||
"width": 10,
|
"width": 10,
|
||||||
"x": 30,
|
"x": 30,
|
||||||
"y": 30,
|
"y": 0,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -1318,7 +1318,7 @@ Object {
|
|||||||
"versionNonce": 1116226695,
|
"versionNonce": 1116226695,
|
||||||
"width": 10,
|
"width": 10,
|
||||||
"x": 30,
|
"x": 30,
|
||||||
"y": 30,
|
"y": 0,
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
@ -1341,7 +1341,7 @@ Object {
|
|||||||
"versionNonce": 1604849351,
|
"versionNonce": 1604849351,
|
||||||
"width": 10,
|
"width": 10,
|
||||||
"x": 60,
|
"x": 60,
|
||||||
"y": 60,
|
"y": 0,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -1410,7 +1410,7 @@ Object {
|
|||||||
"versionNonce": 915032327,
|
"versionNonce": 915032327,
|
||||||
"width": 10,
|
"width": 10,
|
||||||
"x": 30,
|
"x": 30,
|
||||||
"y": 30,
|
"y": 0,
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
@ -1435,7 +1435,7 @@ Object {
|
|||||||
"versionNonce": 81784553,
|
"versionNonce": 81784553,
|
||||||
"width": 10,
|
"width": 10,
|
||||||
"x": 60,
|
"x": 60,
|
||||||
"y": 60,
|
"y": 0,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -1501,7 +1501,7 @@ Object {
|
|||||||
"versionNonce": 915032327,
|
"versionNonce": 915032327,
|
||||||
"width": 10,
|
"width": 10,
|
||||||
"x": 30,
|
"x": 30,
|
||||||
"y": 30,
|
"y": 0,
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
@ -1526,7 +1526,7 @@ Object {
|
|||||||
"versionNonce": 81784553,
|
"versionNonce": 81784553,
|
||||||
"width": 10,
|
"width": 10,
|
||||||
"x": 60,
|
"x": 60,
|
||||||
"y": 60,
|
"y": 0,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -1592,7 +1592,7 @@ Object {
|
|||||||
"versionNonce": 915032327,
|
"versionNonce": 915032327,
|
||||||
"width": 10,
|
"width": 10,
|
||||||
"x": 30,
|
"x": 30,
|
||||||
"y": 30,
|
"y": 0,
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
@ -1617,7 +1617,7 @@ Object {
|
|||||||
"versionNonce": 81784553,
|
"versionNonce": 81784553,
|
||||||
"width": 10,
|
"width": 10,
|
||||||
"x": 60,
|
"x": 60,
|
||||||
"y": 60,
|
"y": 0,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -25348,7 +25348,7 @@ Object {
|
|||||||
"versionNonce": 81784553,
|
"versionNonce": 81784553,
|
||||||
"width": 10,
|
"width": 10,
|
||||||
"x": 10,
|
"x": 10,
|
||||||
"y": 10,
|
"y": 0,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -25377,7 +25377,7 @@ Object {
|
|||||||
"versionNonce": 747212839,
|
"versionNonce": 747212839,
|
||||||
"width": 10,
|
"width": 10,
|
||||||
"x": 50,
|
"x": 50,
|
||||||
"y": 50,
|
"y": 0,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -25476,7 +25476,7 @@ Object {
|
|||||||
"versionNonce": 1278240551,
|
"versionNonce": 1278240551,
|
||||||
"width": 10,
|
"width": 10,
|
||||||
"x": 10,
|
"x": 10,
|
||||||
"y": 10,
|
"y": 0,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -25512,7 +25512,7 @@ Object {
|
|||||||
"versionNonce": 1278240551,
|
"versionNonce": 1278240551,
|
||||||
"width": 10,
|
"width": 10,
|
||||||
"x": 10,
|
"x": 10,
|
||||||
"y": 10,
|
"y": 0,
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
@ -25535,7 +25535,7 @@ Object {
|
|||||||
"versionNonce": 453191,
|
"versionNonce": 453191,
|
||||||
"width": 10,
|
"width": 10,
|
||||||
"x": 50,
|
"x": 50,
|
||||||
"y": 50,
|
"y": 0,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -25576,7 +25576,7 @@ Object {
|
|||||||
"versionNonce": 1150084233,
|
"versionNonce": 1150084233,
|
||||||
"width": 10,
|
"width": 10,
|
||||||
"x": 10,
|
"x": 10,
|
||||||
"y": 10,
|
"y": 0,
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
@ -25601,7 +25601,7 @@ Object {
|
|||||||
"versionNonce": 1116226695,
|
"versionNonce": 1116226695,
|
||||||
"width": 10,
|
"width": 10,
|
||||||
"x": 50,
|
"x": 50,
|
||||||
"y": 50,
|
"y": 0,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -25639,7 +25639,7 @@ Object {
|
|||||||
"versionNonce": 1150084233,
|
"versionNonce": 1150084233,
|
||||||
"width": 10,
|
"width": 10,
|
||||||
"x": 10,
|
"x": 10,
|
||||||
"y": 10,
|
"y": 0,
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
@ -25664,7 +25664,7 @@ Object {
|
|||||||
"versionNonce": 1116226695,
|
"versionNonce": 1116226695,
|
||||||
"width": 10,
|
"width": 10,
|
||||||
"x": 50,
|
"x": 50,
|
||||||
"y": 50,
|
"y": 0,
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
@ -25725,7 +25725,7 @@ Object {
|
|||||||
"versionNonce": 1150084233,
|
"versionNonce": 1150084233,
|
||||||
"width": 10,
|
"width": 10,
|
||||||
"x": 10,
|
"x": 10,
|
||||||
"y": 10,
|
"y": 0,
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
@ -25750,7 +25750,7 @@ Object {
|
|||||||
"versionNonce": 1116226695,
|
"versionNonce": 1116226695,
|
||||||
"width": 10,
|
"width": 10,
|
||||||
"x": 50,
|
"x": 50,
|
||||||
"y": 50,
|
"y": 0,
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
@ -25837,7 +25837,7 @@ Object {
|
|||||||
"versionNonce": 1150084233,
|
"versionNonce": 1150084233,
|
||||||
"width": 10,
|
"width": 10,
|
||||||
"x": 10,
|
"x": 10,
|
||||||
"y": 10,
|
"y": 0,
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
@ -25862,7 +25862,7 @@ Object {
|
|||||||
"versionNonce": 1116226695,
|
"versionNonce": 1116226695,
|
||||||
"width": 10,
|
"width": 10,
|
||||||
"x": 50,
|
"x": 50,
|
||||||
"y": 50,
|
"y": 0,
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
@ -25954,7 +25954,7 @@ Object {
|
|||||||
"versionNonce": 81784553,
|
"versionNonce": 81784553,
|
||||||
"width": 10,
|
"width": 10,
|
||||||
"x": 10,
|
"x": 10,
|
||||||
"y": 10,
|
"y": 0,
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
@ -25980,7 +25980,7 @@ Object {
|
|||||||
"versionNonce": 747212839,
|
"versionNonce": 747212839,
|
||||||
"width": 10,
|
"width": 10,
|
||||||
"x": 50,
|
"x": 50,
|
||||||
"y": 50,
|
"y": 0,
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
|
49
src/tests/binding.test.tsx
Normal file
49
src/tests/binding.test.tsx
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { render } from "./test-utils";
|
||||||
|
import App from "../components/App";
|
||||||
|
import { UI, Pointer } from "./helpers/ui";
|
||||||
|
import { getTransformHandles } from "../element/transformHandles";
|
||||||
|
|
||||||
|
const { h } = window;
|
||||||
|
|
||||||
|
const mouse = new Pointer("mouse");
|
||||||
|
|
||||||
|
describe("element binding", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
render(<App />);
|
||||||
|
});
|
||||||
|
|
||||||
|
// NOTE if this tests fails, skip it -- it was really flaky at one point
|
||||||
|
it("rotation of arrow should rebind both ends", () => {
|
||||||
|
const rect1 = UI.createElement("rectangle", {
|
||||||
|
x: 0,
|
||||||
|
width: 100,
|
||||||
|
height: 1000,
|
||||||
|
});
|
||||||
|
const rect2 = UI.createElement("rectangle", {
|
||||||
|
x: 200,
|
||||||
|
width: 100,
|
||||||
|
height: 1000,
|
||||||
|
});
|
||||||
|
const arrow = UI.createElement("arrow", {
|
||||||
|
x: 110,
|
||||||
|
y: 50,
|
||||||
|
width: 80,
|
||||||
|
height: 1,
|
||||||
|
});
|
||||||
|
expect(arrow.startBinding?.elementId).toBe(rect1.id);
|
||||||
|
expect(arrow.endBinding?.elementId).toBe(rect2.id);
|
||||||
|
|
||||||
|
const { rotation } = getTransformHandles(arrow, h.state.zoom, "mouse");
|
||||||
|
if (rotation) {
|
||||||
|
const rotationHandleX = rotation[0] + rotation[2] / 2;
|
||||||
|
const rotationHandleY = rotation[1] + rotation[3] / 2;
|
||||||
|
mouse.down(rotationHandleX, rotationHandleY);
|
||||||
|
mouse.move(0, 1000);
|
||||||
|
mouse.up();
|
||||||
|
}
|
||||||
|
expect(arrow.angle).toBeGreaterThan(3);
|
||||||
|
expect(arrow.startBinding?.elementId).toBe(rect2.id);
|
||||||
|
expect(arrow.endBinding?.elementId).toBe(rect1.id);
|
||||||
|
});
|
||||||
|
});
|
@ -1,7 +1,11 @@
|
|||||||
import { ToolName } from "../queries/toolQueries";
|
import { ToolName } from "../queries/toolQueries";
|
||||||
import { fireEvent, GlobalTestState } from "../test-utils";
|
import { fireEvent, GlobalTestState } from "../test-utils";
|
||||||
import { KEYS, Key } from "../../keys";
|
import { KEYS, Key } from "../../keys";
|
||||||
import { ExcalidrawElement } from "../../element/types";
|
import {
|
||||||
|
ExcalidrawElement,
|
||||||
|
ExcalidrawLinearElement,
|
||||||
|
ExcalidrawTextElement,
|
||||||
|
} from "../../element/types";
|
||||||
import { API } from "./api";
|
import { API } from "./api";
|
||||||
|
|
||||||
const { h } = window;
|
const { h } = window;
|
||||||
@ -174,24 +178,32 @@ export class UI {
|
|||||||
fireEvent.click(GlobalTestState.renderResult.getByToolName(toolName));
|
fireEvent.click(GlobalTestState.renderResult.getByToolName(toolName));
|
||||||
};
|
};
|
||||||
|
|
||||||
static createElement(
|
static createElement<T extends ToolName>(
|
||||||
type: ToolName,
|
type: T,
|
||||||
{
|
{
|
||||||
x = 0,
|
x = 0,
|
||||||
y = x,
|
y = 0,
|
||||||
size = 10,
|
size = 10,
|
||||||
|
width = size,
|
||||||
|
height = width,
|
||||||
}: {
|
}: {
|
||||||
x?: number;
|
x?: number;
|
||||||
y?: number;
|
y?: number;
|
||||||
size?: number;
|
size?: number;
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
},
|
},
|
||||||
) {
|
): T extends "arrow" | "line" | "draw"
|
||||||
|
? ExcalidrawLinearElement
|
||||||
|
: T extends "text"
|
||||||
|
? ExcalidrawTextElement
|
||||||
|
: ExcalidrawElement {
|
||||||
UI.clickTool(type);
|
UI.clickTool(type);
|
||||||
mouse.reset();
|
mouse.reset();
|
||||||
mouse.down(x, y);
|
mouse.down(x, y);
|
||||||
mouse.reset();
|
mouse.reset();
|
||||||
mouse.up(x + size, y + size);
|
mouse.up(x + (width ?? height ?? size), y + (height ?? size));
|
||||||
return h.elements[h.elements.length - 1];
|
return h.elements[h.elements.length - 1] as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
static group(elements: ExcalidrawElement[]) {
|
static group(elements: ExcalidrawElement[]) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user