From 5f95911a504a47c867198fccc32a75bf22d26056 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 29 Sep 2021 15:15:21 -0400
Subject: added snapping to close curve or to self-snap a vertex to its curve. 
 fixed ink decorations from being clipped when zoomed.  fixed crash with
 zero-length tangent

---
 src/client/views/InkControlPtHandles.tsx | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

(limited to 'src/client/views/InkControlPtHandles.tsx')

diff --git a/src/client/views/InkControlPtHandles.tsx b/src/client/views/InkControlPtHandles.tsx
index f80aca268..249a0fa64 100644
--- a/src/client/views/InkControlPtHandles.tsx
+++ b/src/client/views/InkControlPtHandles.tsx
@@ -42,10 +42,13 @@ export class InkControlPtHandles extends React.Component<InkControlProps> {
             setupMoveUpEvents(this, e,
                 action((e: PointerEvent, down: number[], delta: number[]) => {
                     if (!this.controlUndo) this.controlUndo = UndoManager.StartBatch("drag ink ctrl pt");
-                    InkStrokeProperties.Instance?.moveControl(-delta[0] * screenScale, -delta[1] * screenScale, controlIndex);
+                    InkStrokeProperties.Instance?.moveControl(delta[0] * screenScale, delta[1] * screenScale, controlIndex);
                     return false;
                 }),
                 action(() => {
+                    if (this.controlUndo) {
+                        InkStrokeProperties.Instance?.snapControl(this.props.inkDoc, controlIndex);
+                    }
                     this.controlUndo?.end();
                     this.controlUndo = undefined;
                     UndoManager.FilterBatches(["data", "x", "y", "width", "height"]);
@@ -117,20 +120,21 @@ export class InkControlPtHandles extends React.Component<InkControlProps> {
         }
 
         const screenSpaceLineWidth = this.props.screenSpaceLineWidth;
+        const closed = inkData.lastElement().X === inkData[0].X && inkData.lastElement().Y === inkData[0].Y;
         const nearestScreenPt = this.props.nearestScreenPt();
         const TagType = (broken?: boolean) => broken ? "rect" : "circle";
         const hdl = (control: { X: number, Y: number, I: number }, scale: number, color: string) => {
             const broken = Cast(this.props.inkDoc.brokenInkIndices, listSpec("number"))?.includes(control.I);
-            const Tag = TagType(broken) as keyof JSX.IntrinsicElements;
-            return <circle key={control.I.toString() + scale}
-                x={control.X - screenSpaceLineWidth * 3 * scale}
-                y={control.Y - screenSpaceLineWidth * 3 * scale}
+            const Tag = TagType((control.I === 0 || control.I === inkData.length - 1) && !closed) as keyof JSX.IntrinsicElements;
+            return <Tag key={control.I.toString() + scale}
+                x={control.X - screenSpaceLineWidth * 2 * scale}
+                y={control.Y - screenSpaceLineWidth * 2 * scale}
                 cx={control.X}
                 cy={control.Y}
                 r={screenSpaceLineWidth * 2 * scale}
                 opacity={this.controlUndo ? 0.15 : 1}
-                height={screenSpaceLineWidth * 6 * scale}
-                width={screenSpaceLineWidth * 6 * scale}
+                height={screenSpaceLineWidth * 4 * scale}
+                width={screenSpaceLineWidth * 4 * scale}
                 strokeWidth={screenSpaceLineWidth / 2}
                 stroke={Colors.MEDIUM_BLUE}
                 fill={broken ? Colors.MEDIUM_BLUE : color}
-- 
cgit v1.2.3-70-g09d2

