Skip to content

Commit 45b25d8

Browse files
authored
make sure if both ends are bound we change bend instead (#555)
1 parent ecbbe46 commit 45b25d8

1 file changed

Lines changed: 77 additions & 0 deletions

File tree

apps/obsidian/src/components/canvas/shapes/DiscourseRelationShape.tsx

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,62 @@ export class DiscourseRelationUtil extends ShapeUtil<DiscourseRelationShape> {
472472
const atTranslationStart = shapeAtTranslationStart.get(initialShape);
473473
if (!atTranslationStart) return;
474474

475+
const bindings = getArrowBindings(this.editor, shape);
476+
477+
// If both ends are bound, convert translation to bend changes instead of moving the arrow
478+
if (bindings.start && bindings.end) {
479+
const shapePageTransform = this.editor.getShapePageTransform(shape.id);
480+
const pageDelta = Vec.Sub(
481+
shapePageTransform.applyToPoint(shape),
482+
atTranslationStart.pagePosition,
483+
);
484+
485+
const initialBindings = getArrowBindings(this.editor, initialShape);
486+
const { start: initialStart, end: initialEnd } =
487+
getArrowTerminalsInArrowSpace(
488+
this.editor,
489+
initialShape,
490+
initialBindings,
491+
);
492+
493+
const delta = Vec.Sub(initialEnd, initialStart);
494+
const v = Vec.Per(delta);
495+
const med = Vec.Med(initialEnd, initialStart);
496+
497+
const initialPageTransform = this.editor.getShapePageTransform(
498+
initialShape.id,
499+
);
500+
const arrowSpaceDelta = Vec.Rot(
501+
pageDelta,
502+
-initialPageTransform.rotation(),
503+
);
504+
505+
const translatedMidpoint = Vec.Add(med, arrowSpaceDelta);
506+
const A = Vec.Sub(med, v);
507+
const B = Vec.Add(med, v);
508+
const point = Vec.NearestPointOnLineSegment(
509+
A,
510+
B,
511+
translatedMidpoint,
512+
false,
513+
);
514+
515+
// Calculate new bend based on distance from midpoint
516+
let newBend = Vec.Dist(point, med);
517+
if (Vec.Clockwise(point, initialEnd, med)) {
518+
newBend *= -1;
519+
}
520+
521+
return {
522+
id: shape.id,
523+
type: shape.type,
524+
x: initialShape.x,
525+
y: initialShape.y,
526+
props: { bend: newBend },
527+
};
528+
}
529+
530+
// If not both ends are bound, use normal translation behavior
475531
const shapePageTransform = this.editor.getShapePageTransform(shape.id);
476532
const pageDelta = Vec.Sub(
477533
shapePageTransform.applyToPoint(shape),
@@ -540,6 +596,27 @@ export class DiscourseRelationUtil extends ShapeUtil<DiscourseRelationShape> {
540596
);
541597
const shapePageTransform = this.editor.getShapePageTransform(shape.id);
542598

599+
// If both ends are bound, we'll convert translation to bend changes
600+
// So we don't need to update bindings or unbind
601+
if (bindings.start && bindings.end) {
602+
shapeAtTranslationStart.set(shape, {
603+
pagePosition: shapePageTransform.applyToPoint(shape),
604+
terminalBindings: mapObjectMapValues(
605+
terminalsInArrowSpace,
606+
(terminalName, point) => {
607+
const binding = bindings[terminalName];
608+
if (!binding) return null;
609+
return {
610+
binding,
611+
shapePosition: point,
612+
pagePosition: shapePageTransform.applyToPoint(point),
613+
};
614+
},
615+
),
616+
});
617+
return;
618+
}
619+
543620
// If at least one bound shape is in the selection, do nothing;
544621
// If no bound shapes are in the selection, unbind any bound shapes
545622

0 commit comments

Comments
 (0)