rebind arrow on rotation (#2096)

This commit is contained in:
David Luzar 2020-08-29 14:16:40 +02:00 committed by GitHub
parent 0e28177ccc
commit 26ef235019
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 101 additions and 42 deletions

View File

@ -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);
} }
} }

View File

@ -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,

View 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);
});
});

View File

@ -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[]) {