From 16c2a900e9116474caa67e4d5de15e2c51477292 Mon Sep 17 00:00:00 2001
From: vkalev <vjk1883@gmail.com>
Date: Tue, 27 Jul 2021 18:54:53 -0400
Subject: changing format of controls/handles + adding color enums

---
 src/client/views/InkControls.tsx | 73 ++++++++++++++++++++++------------------
 1 file changed, 41 insertions(+), 32 deletions(-)

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

diff --git a/src/client/views/InkControls.tsx b/src/client/views/InkControls.tsx
index 23f22c774..090af10cc 100644
--- a/src/client/views/InkControls.tsx
+++ b/src/client/views/InkControls.tsx
@@ -6,8 +6,13 @@ import { setupMoveUpEvents, emptyFunction } from "../../Utils";
 import { UndoManager } from "../util/UndoManager";
 import { ControlPoint, InkData, PointData } from "../../fields/InkField";
 import { Transform } from "../util/Transform";
+import { Colors } from "./global/globalEnums";
+import { Doc } from "../../fields/Doc";
+import { listSpec } from "../../fields/Schema";
+import { Cast } from "../../fields/Types";
 
 export interface InkControlProps {
+    inkDoc: Doc;
     data: InkData;
     addedPoints: PointData[];
     format: number[];
@@ -30,19 +35,22 @@ export class InkControls extends React.Component<InkControlProps> {
             const controlUndo = UndoManager.StartBatch("DocDecs set radius");
             const screenScale = this.props.ScreenToLocalTransform().Scale;
             const order = controlIndex % 4;
-            const handleIndexA  = order === 2 ? controlIndex - 1 : controlIndex - 2;
+            const handleIndexA = order === 2 ? controlIndex - 1 : controlIndex - 2;
             const handleIndexB = order === 2 ? controlIndex + 2 : controlIndex + 1;
+            const brokenIndices = Cast(this.props.inkDoc, listSpec("number"));
             setupMoveUpEvents(this, e,
                 (e: PointerEvent, down: number[], delta: number[]) => {
                     InkStrokeProperties.Instance?.moveControl(-delta[0] * screenScale, -delta[1] * screenScale, controlIndex);
                     return false;
                 },
-                () => controlUndo?.end(), 
-                emptyFunction);
-                // action((e: PointerEvent, doubleTap: boolean | undefined) =>
-                // { if (doubleTap && InkStrokeProperties.Instance?._brokenIndices.includes(controlIndex)) {
-                //     InkStrokeProperties.Instance?.snapHandleTangent(controlIndex, handleIndexA, handleIndexB);
-                // }}));
+                () => controlUndo?.end(),
+                brokenIndices ?
+                    action((e: PointerEvent, doubleTap: boolean | undefined) => {
+                        if (doubleTap && brokenIndices.includes(controlIndex)) {
+                            InkStrokeProperties.Instance?.snapHandleTangent(controlIndex, handleIndexA, handleIndexB);
+                        }
+                    })
+                    : emptyFunction);
         }
     }
 
@@ -75,7 +83,7 @@ export class InkControls extends React.Component<InkControlProps> {
     @action onLeaveControl = () => { this._overControl = -1; };
     @action onEnterAddPoint = (i: number) => { this._overAddPoint = i; };
     @action onLeaveAddPoint = () => { this._overAddPoint = -1; };
- 
+
     render() {
         const formatInstance = InkStrokeProperties.Instance;
         if (!formatInstance) return (null);
@@ -90,41 +98,42 @@ export class InkControls extends React.Component<InkControlProps> {
             }
         }
         const addedPoints = this.props.addedPoints;
-        const [left, top, scaleX, scaleY, strokeWidth, dotsize] = this.props.format;
+        const [left, top, scaleX, scaleY, strokeWidth] = this.props.format;
 
         return (
             <>
                 {addedPoints.map((pts, i) =>
                     <svg height="10" width="10" key={`add${i}`}>
-                        <circle 
-                            cx={(pts.X - left - strokeWidth / 2) * scaleX + strokeWidth / 2} 
-                            cy={(pts.Y - top - strokeWidth / 2) * scaleY + strokeWidth / 2} 
-                            r={strokeWidth / 2} 
-                            stroke={this._overAddPoint === i ? "#1F85DE" : "transparent"} 
-                            strokeWidth={dotsize / 4} fill={this._overAddPoint === i ? "#1F85DE" : "transparent"}
-                            onPointerDown={() => { formatInstance?.addPoints(pts.X, pts.Y, addedPoints, i, controlPoints); }} 
-                            onMouseEnter={() => this.onEnterAddPoint(i)} 
-                            onMouseLeave={this.onLeaveAddPoint} 
-                            pointerEvents="all" 
+                        <circle
+                            cx={(pts.X - left - strokeWidth / 2) * scaleX + strokeWidth / 2}
+                            cy={(pts.Y - top - strokeWidth / 2) * scaleY + strokeWidth / 2}
+                            r={strokeWidth / 1.5}
+                            stroke={this._overAddPoint === i ? Colors.MEDIUM_BLUE : "transparent"}
+                            strokeWidth={0} fill={this._overAddPoint === i ? Colors.MEDIUM_BLUE : "transparent"}
+                            onPointerDown={() => { formatInstance?.addPoints(pts.X, pts.Y, addedPoints, i, controlPoints); }}
+                            onMouseEnter={() => this.onEnterAddPoint(i)}
+                            onMouseLeave={this.onLeaveAddPoint}
+                            pointerEvents="all"
                             cursor="all-scroll"
                         />
                     </svg>
                 )}
                 {controlPoints.map((control, i) =>
                     <svg height="10" width="10" key={`ctrl${i}`}>
-                        <rect 
-                            x={(control.X - left - strokeWidth / 2) * scaleX} 
-                            y={(control.Y - top - strokeWidth / 2) * scaleY} 
-                            height={this._overControl === i ? strokeWidth * 1.5 : strokeWidth} 
-                            width={this._overControl === i ? strokeWidth * 1.5 : strokeWidth} 
-                            strokeWidth={strokeWidth / 6} stroke="#1F85DE" 
-                            fill={formatInstance?._currentPoint === control.I ? "#1F85DE" : "white"}
-                            onPointerDown={(e) => { 
-                                this.changeCurrPoint(control.I); 
-                                this.onControlDown(e, control.I); }} 
-                            onMouseEnter={() => this.onEnterControl(i)} 
-                            onMouseLeave={this.onLeaveControl} 
-                            pointerEvents="all" 
+                        <rect
+                            x={(control.X - left - strokeWidth / 2) * scaleX}
+                            y={(control.Y - top - strokeWidth / 2) * scaleY}
+                            height={this._overControl === i ? strokeWidth * 1.5 : strokeWidth}
+                            width={this._overControl === i ? strokeWidth * 1.5 : strokeWidth}
+                            strokeWidth={strokeWidth / 6} stroke={Colors.MEDIUM_BLUE}
+                            fill={formatInstance?._currentPoint === control.I ? Colors.MEDIUM_BLUE : Colors.WHITE}
+                            onPointerDown={(e) => {
+                                this.changeCurrPoint(control.I);
+                                this.onControlDown(e, control.I);
+                            }}
+                            onMouseEnter={() => this.onEnterControl(i)}
+                            onMouseLeave={this.onLeaveControl}
+                            pointerEvents="all"
                             cursor="default"
                         />
                     </svg>
-- 
cgit v1.2.3-70-g09d2


From ea6000690022d43b6bc8e1a546d28729a59faf7b Mon Sep 17 00:00:00 2001
From: vkalev <vjk1883@gmail.com>
Date: Wed, 28 Jul 2021 13:14:10 -0400
Subject: snapping broken tangency added

---
 src/client/views/InkControls.tsx        | 14 ++++++--------
 src/client/views/InkHandles.tsx         |  1 +
 src/client/views/InkStrokeProperties.ts | 18 +++++++++++-------
 3 files changed, 18 insertions(+), 15 deletions(-)

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

diff --git a/src/client/views/InkControls.tsx b/src/client/views/InkControls.tsx
index 090af10cc..6213a4075 100644
--- a/src/client/views/InkControls.tsx
+++ b/src/client/views/InkControls.tsx
@@ -37,20 +37,18 @@ export class InkControls extends React.Component<InkControlProps> {
             const order = controlIndex % 4;
             const handleIndexA = order === 2 ? controlIndex - 1 : controlIndex - 2;
             const handleIndexB = order === 2 ? controlIndex + 2 : controlIndex + 1;
-            const brokenIndices = Cast(this.props.inkDoc, listSpec("number"));
+            const brokenIndices = Cast(this.props.inkDoc.brokenInkIndices, listSpec("number"));
             setupMoveUpEvents(this, e,
                 (e: PointerEvent, down: number[], delta: number[]) => {
                     InkStrokeProperties.Instance?.moveControl(-delta[0] * screenScale, -delta[1] * screenScale, controlIndex);
                     return false;
                 },
                 () => controlUndo?.end(),
-                brokenIndices ?
-                    action((e: PointerEvent, doubleTap: boolean | undefined) => {
-                        if (doubleTap && brokenIndices.includes(controlIndex)) {
-                            InkStrokeProperties.Instance?.snapHandleTangent(controlIndex, handleIndexA, handleIndexB);
-                        }
-                    })
-                    : emptyFunction);
+                action((e: PointerEvent, doubleTap: boolean | undefined) => {
+                    if (doubleTap && brokenIndices && brokenIndices.includes(controlIndex)) {
+                        InkStrokeProperties.Instance?.snapHandleTangent(controlIndex, handleIndexA, handleIndexB);
+                    }
+                }));
         }
     }
 
diff --git a/src/client/views/InkHandles.tsx b/src/client/views/InkHandles.tsx
index 6e890e184..f1eb4b9db 100644
--- a/src/client/views/InkHandles.tsx
+++ b/src/client/views/InkHandles.tsx
@@ -51,6 +51,7 @@ export class InkHandles extends React.Component<InkHandlesProps> {
     onBreakTangent = (e: KeyboardEvent, controlIndex: number) => {
         const doc: Doc = this.props.inkDoc;
         if (["Alt"].includes(e.key)) {
+            e.stopPropagation();
             if (doc) {
                 const brokenIndices = Cast(doc.brokenInkIndices, listSpec("number")) || new List;
                 if (brokenIndices && !brokenIndices.includes(controlIndex)) {
diff --git a/src/client/views/InkStrokeProperties.ts b/src/client/views/InkStrokeProperties.ts
index de8cf80bd..76ca5b5ec 100644
--- a/src/client/views/InkStrokeProperties.ts
+++ b/src/client/views/InkStrokeProperties.ts
@@ -257,6 +257,11 @@ export class InkStrokeProperties {
             return newPoints;
         })
 
+    /**
+     * Snaps a control point with broken tangency back to synced rotation.
+     * @param handleIndexA The handle point that retains its current position.
+     * @param handleIndexB The handle point that is rotated to be 180 degrees from its opposite.
+     */
     snapHandleTangent = (controlIndex: number, handleIndexA: number, handleIndexB: number) => {
         this.applyFunction((doc: Doc, ink: InkData) => {
             const brokenIndices = Cast(doc.brokenInkIndices, listSpec("number"));
@@ -278,13 +283,12 @@ export class InkStrokeProperties {
      */
     @action
     rotatePoint = (target: PointData, origin: PointData, angle: number) => {
-        target.X -= origin.X;
-        target.Y -= origin.Y;
-        const newX = Math.cos(angle) * target.X - Math.sin(angle) * target.Y;
-        const newY = Math.sin(angle) * target.X + Math.cos(angle) * target.Y;
-        target.X = newX + origin.X;
-        target.Y = newY + origin.Y;
-        return target;
+        let rotatedTarget = { X: target.X - origin.X, Y: target.Y - origin.Y };
+        const newX = Math.cos(angle) * rotatedTarget.X - Math.sin(angle) * rotatedTarget.Y;
+        const newY = Math.sin(angle) * rotatedTarget.X + Math.cos(angle) * rotatedTarget.Y;
+        rotatedTarget.X = newX + origin.X;
+        rotatedTarget.Y = newY + origin.Y;
+        return rotatedTarget;
     }
 
     /**
-- 
cgit v1.2.3-70-g09d2

