diff --git a/src/association.ts b/src/association.ts index 57a5d1c..bedce75 100644 --- a/src/association.ts +++ b/src/association.ts @@ -41,7 +41,7 @@ export class Association { currentTargetOutliner = undefined; this._arrow.updateEndToPoint(cursorPosition); } - this._updateArrowDrawing(); + this._updateArrowDrawing(currentTargetOutliner); }, onDrop: () => { if (currentTargetOutliner) { @@ -60,7 +60,7 @@ export class Association { } }); - this._updateArrowDrawing(); + this._updateArrowDrawing(this._valueOutliner); } arrow() { @@ -70,12 +70,12 @@ export class Association { updatePosition() { this._arrow.updateStart(this._arrowStartPosition()); this._arrow.attachEndToBox(this._arrowEndBox()); - this._updateArrowDrawing(); + this._updateArrowDrawing(this._valueOutliner); } - private _updateArrowDrawing() { + private _updateArrowDrawing(targetOutliner: Outliner | undefined) { this._updateArrowEndAreaPosition(); - this._updateArrowMode(); + this._updateArrowModeTargeting(targetOutliner); } private _updateArrowEndAreaPosition() { @@ -83,12 +83,18 @@ export class Association { this._arrowEndArea.style.translate = `${boundStart.x}px ${boundStart.y}px`; } - private _updateArrowMode() { - const ownerOutlinerElement = this._ownerOutliner.domElement(); - const valueOutlinerElement = this._valueOutliner.domElement(); + private _updateArrowModeTargeting(targetOutliner: Outliner | undefined) { const arrowClassList = this._arrow.svgElement().classList; - if (this._valueOutliner === this._ownerOutliner) return; + if (targetOutliner === undefined) { + arrowClassList.remove("arrow-faded", "arrow-hidden"); + return; + } + + const ownerOutlinerElement = this._ownerOutliner.domElement(); + const valueOutlinerElement = targetOutliner.domElement(); + + if (targetOutliner === this._ownerOutliner) return; if (ownerOutlinerElement.compareDocumentPosition(valueOutlinerElement) === Node.DOCUMENT_POSITION_FOLLOWING) { arrowClassList.remove("arrow-faded"); arrowClassList.toggle( diff --git a/tests/outliners_in_dom.test.ts b/tests/outliners_in_dom.test.ts index 240e8ac..e95b48d 100644 --- a/tests/outliners_in_dom.test.ts +++ b/tests/outliners_in_dom.test.ts @@ -802,19 +802,50 @@ describe("The outliners in the world", () => { ) }); - test("the arrow mode is updated when grabbing an association", () => { - const inspectedObject = { x: 1, y: 2 }; - const outlinerBelow = openOutlinerFor("this is below"); - const outliner = openOutlinerFor(inspectedObject, point(0, 100)); - outliner.inspectProperty("x"); - outliner.move(point(1, 1)); - const [associationElement] = visibleAssociationElements(); + describe("arrow mode is updated when grabbing an association", () => { + test("when the source outliner is above the arrow end", () => { + const inspectedObject = { x: 1, y: 2 }; + const outlinerBelow = openOutlinerFor("this is below"); + const outliner = openOutlinerFor(inspectedObject, point(0, 100)); + outliner.inspectProperty("x"); + outliner.move(point(1, 1)); + const [associationElement] = visibleAssociationElements(); - grabAssociation(associationElement) - .hover(outlinerBelow.domElement()); + grabAssociation(associationElement) + .hover(outlinerBelow.domElement()); - const [arrow] = visibleArrowElements(); - expect(arrow).toHaveClass("arrow-faded"); + const [arrow] = visibleArrowElements(); + expect(arrow).toHaveClass("arrow-faded"); + }); + + test("considering the potentially-new target outliner as the target outliner to determine the arrow mode", () => { + const inspectedObject = { x: 1, y: 2 }; + const outliner = openOutlinerFor(inspectedObject, point(10, 10)); + const _valueOutliner = openOutlinerFor(1, point(220, 10)); + outliner.inspectProperty("x"); + const outlinerAbove = openOutlinerFor("this is above", point(10, 50)); + const [associationElement] = visibleAssociationElements(); + + grabAssociation(associationElement) + .hover(outlinerAbove.domElement()); + + const [arrow] = visibleArrowElements(); + expect(arrow).toHaveClass("arrow-hidden"); + }); + + test("the arrow is fully visible if the arrow is pointing to no outliner", () => { + const inspectedObject = { x: 1, y: 2 }; + const outliner = openOutlinerFor(inspectedObject, point(10, 10)); + const _valueOutliner = openOutlinerFor(1, point(10, 50)); + outliner.inspectProperty("x"); + const [associationElement] = visibleAssociationElements(); + + grabAssociation(associationElement) + .move(point(200, 200)); + + const [arrow] = visibleArrowElements(); + expect(arrow).not.toHaveClass("arrow-hidden"); + }); }); test("while redirecting the association, the arrow moves with the cursor even when the view is scrolled", () => {