From 1b592f74a7df8f6dd7b2881032725f26aedff403 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 28 Mar 2024 11:38:56 -0400
Subject: fixed keyvaluebox to show props document, never the doc in the
 fieldKey slot.  changed computedFIelds to do mobx caching.  changed text
 boxes to do updating from templates based on a fieldKey_autoUpdate flag
 combined with modification timestamps.  enabled comparison box to work with
 text fields in addition to docs.

---
 src/client/views/InkControlPtHandles.tsx | 85 ++++++++++++++++++--------------
 1 file changed, 48 insertions(+), 37 deletions(-)

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

diff --git a/src/client/views/InkControlPtHandles.tsx b/src/client/views/InkControlPtHandles.tsx
index 31b13d2c8..01d52135a 100644
--- a/src/client/views/InkControlPtHandles.tsx
+++ b/src/client/views/InkControlPtHandles.tsx
@@ -1,5 +1,5 @@
 import * as React from 'react';
-import { action, observable } from 'mobx';
+import { action, makeObservable, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import { Doc } from '../../fields/Doc';
 import { ControlPoint, InkData, PointData } from '../../fields/InkField';
@@ -13,6 +13,7 @@ import { Colors } from './global/globalEnums';
 import { InkingStroke } from './InkingStroke';
 import { InkStrokeProperties } from './InkStrokeProperties';
 import { SnappingManager } from '../util/SnappingManager';
+import { ObservableReactComponent } from './ObservableReactComponent';
 
 export interface InkControlProps {
     inkDoc: Doc;
@@ -24,10 +25,15 @@ export interface InkControlProps {
 }
 
 @observer
-export class InkControlPtHandles extends React.Component<InkControlProps> {
+export class InkControlPtHandles extends ObservableReactComponent<InkControlProps> {
     @observable private _overControl = -1;
     get docView() {
-        return this.props.inkView.DocumentView?.();
+        return this._props.inkView.DocumentView?.();
+    }
+
+    constructor(props: InkControlProps) {
+        super(props);
+        makeObservable(this);
     }
 
     componentDidMount() {
@@ -42,51 +48,51 @@ export class InkControlPtHandles extends React.Component<InkControlProps> {
      */
     @action
     onControlDown = (e: React.PointerEvent, controlIndex: number): void => {
-        const ptFromScreen = this.props.inkView.ptFromScreen;
+        const ptFromScreen = this._props.inkView.ptFromScreen;
         if (ptFromScreen) {
             const order = controlIndex % 4;
-            const handleIndexA = ((order === 3 ? controlIndex - 1 : controlIndex - 2) + this.props.inkCtrlPoints.length) % this.props.inkCtrlPoints.length;
-            const handleIndexB = (order === 3 ? controlIndex + 2 : controlIndex + 1) % this.props.inkCtrlPoints.length;
-            const brokenIndices = Cast(this.props.inkDoc.brokenInkIndices, listSpec('number'));
+            const handleIndexA = ((order === 3 ? controlIndex - 1 : controlIndex - 2) + this._props.inkCtrlPoints.length) % this._props.inkCtrlPoints.length;
+            const handleIndexB = (order === 3 ? controlIndex + 2 : controlIndex + 1) % this._props.inkCtrlPoints.length;
+            const brokenIndices = Cast(this._props.inkDoc.brokenInkIndices, listSpec('number'));
             const wasSelected = InkStrokeProperties.Instance._currentPoint === controlIndex;
             if (!wasSelected) InkStrokeProperties.Instance._currentPoint = -1;
-            const origInk = this.props.inkCtrlPoints.slice();
+            const origInk = this._props.inkCtrlPoints.slice();
             setupMoveUpEvents(
                 this,
                 e,
                 action((e: PointerEvent, down: number[], delta: number[]) => {
-                    if (!this.props.inkView.controlUndo) this.props.inkView.controlUndo = UndoManager.StartBatch('drag ink ctrl pt');
+                    if (!this._props.inkView.controlUndo) this._props.inkView.controlUndo = UndoManager.StartBatch('drag ink ctrl pt');
                     const inkMoveEnd = ptFromScreen({ X: delta[0], Y: delta[1] });
                     const inkMoveStart = ptFromScreen({ X: 0, Y: 0 });
                     this.docView && InkStrokeProperties.Instance.moveControlPtHandle(this.docView, inkMoveEnd.X - inkMoveStart.X, inkMoveEnd.Y - inkMoveStart.Y, controlIndex, origInk);
                     return false;
                 }),
                 action(() => {
-                    if (this.props.inkView.controlUndo && this.docView) {
+                    if (this._props.inkView.controlUndo && this.docView) {
                         InkStrokeProperties.Instance.snapControl(this.docView, controlIndex);
                     }
-                    this.props.inkView.controlUndo?.end();
-                    this.props.inkView.controlUndo = undefined;
+                    this._props.inkView.controlUndo?.end();
+                    this._props.inkView.controlUndo = undefined;
                     UndoManager.FilterBatches(['data', 'x', 'y', 'width', 'height']);
                 }),
                 action((e: PointerEvent, doubleTap: boolean | undefined) => {
-                    const equivIndex = controlIndex === 0 ? this.props.inkCtrlPoints.length - 1 : controlIndex === this.props.inkCtrlPoints.length - 1 ? 0 : controlIndex;
+                    const equivIndex = controlIndex === 0 ? this._props.inkCtrlPoints.length - 1 : controlIndex === this._props.inkCtrlPoints.length - 1 ? 0 : controlIndex;
                     if (doubleTap || e.button === 2) {
                         if (!brokenIndices?.includes(equivIndex) && !brokenIndices?.includes(controlIndex)) {
                             if (brokenIndices) brokenIndices.push(controlIndex);
-                            else this.props.inkDoc.brokenInkIndices = new List<number>([controlIndex]);
+                            else this._props.inkDoc.brokenInkIndices = new List<number>([controlIndex]);
                         } else {
                             if (brokenIndices?.includes(equivIndex)) {
-                                if (!this.props.inkView.controlUndo) this.props.inkView.controlUndo = UndoManager.StartBatch('make smooth');
+                                if (!this._props.inkView.controlUndo) this._props.inkView.controlUndo = UndoManager.StartBatch('make smooth');
                                 this.docView && InkStrokeProperties.Instance.snapHandleTangent(this.docView, equivIndex, handleIndexA, handleIndexB);
                             }
                             if (equivIndex !== controlIndex && brokenIndices?.includes(controlIndex)) {
-                                if (!this.props.inkView.controlUndo) this.props.inkView.controlUndo = UndoManager.StartBatch('make smooth');
+                                if (!this._props.inkView.controlUndo) this._props.inkView.controlUndo = UndoManager.StartBatch('make smooth');
                                 this.docView && InkStrokeProperties.Instance.snapHandleTangent(this.docView, controlIndex, handleIndexA, handleIndexB);
                             }
                         }
-                        this.props.inkView.controlUndo?.end();
-                        this.props.inkView.controlUndo = undefined;
+                        this._props.inkView.controlUndo?.end();
+                        this._props.inkView.controlUndo = undefined;
                     }
                     this.changeCurrPoint(controlIndex);
                 }),
@@ -126,14 +132,14 @@ export class InkControlPtHandles extends React.Component<InkControlProps> {
 
     render() {
         // Accessing the current ink's data and extracting all control points.
-        const scrData = this.props.screenCtrlPoints;
+        const scrData = this._props.screenCtrlPoints;
         const sreenCtrlPoints: ControlPoint[] = [];
         for (let i = 0; i <= scrData.length - 4; i += 4) {
             sreenCtrlPoints.push({ ...scrData[i], I: i });
             sreenCtrlPoints.push({ ...scrData[i + 3], I: i + 3 });
         }
 
-        const inkData = this.props.inkCtrlPoints;
+        const inkData = this._props.inkCtrlPoints;
         const inkCtrlPts: ControlPoint[] = [];
         for (let i = 0; i <= inkData.length - 4; i += 4) {
             inkCtrlPts.push({ ...inkData[i], I: i });
@@ -141,23 +147,23 @@ export class InkControlPtHandles extends React.Component<InkControlProps> {
         }
 
         const closed = InkingStroke.IsClosed(inkData);
-        const nearestScreenPt = this.props.nearestScreenPt();
+        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 broken = Cast(this._props.inkDoc.brokenInkIndices, listSpec('number'))?.includes(control.I);
             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 - this.props.screenSpaceLineWidth * 2 * scale}
-                    y={control.Y - this.props.screenSpaceLineWidth * 2 * scale}
+                    x={control.X - this._props.screenSpaceLineWidth * 2 * scale}
+                    y={control.Y - this._props.screenSpaceLineWidth * 2 * scale}
                     cx={control.X}
                     cy={control.Y}
-                    r={this.props.screenSpaceLineWidth * 2 * scale}
-                    opacity={this.props.inkView.controlUndo ? 0.35 : 1}
-                    height={this.props.screenSpaceLineWidth * 4 * scale}
-                    width={this.props.screenSpaceLineWidth * 4 * scale}
-                    strokeWidth={this.props.screenSpaceLineWidth / 2}
+                    r={this._props.screenSpaceLineWidth * 2 * scale}
+                    opacity={this._props.inkView.controlUndo ? 0.35 : 1}
+                    height={this._props.screenSpaceLineWidth * 4 * scale}
+                    width={this._props.screenSpaceLineWidth * 4 * scale}
+                    strokeWidth={this._props.screenSpaceLineWidth / 2}
                     stroke={Colors.MEDIUM_BLUE}
                     fill={broken ? Colors.MEDIUM_BLUE : color}
                     onPointerDown={(e: React.PointerEvent) => this.onControlDown(e, control.I)}
@@ -170,7 +176,7 @@ export class InkControlPtHandles extends React.Component<InkControlProps> {
         };
         return (
             <svg>
-                {!nearestScreenPt ? null : <circle key={'npt'} cx={nearestScreenPt.X} cy={nearestScreenPt.Y} r={this.props.screenSpaceLineWidth * 2} fill={'#00007777'} stroke={'#00007777'} strokeWidth={0} pointerEvents="none" />}
+                {!nearestScreenPt ? null : <circle key={'npt'} cx={nearestScreenPt.X} cy={nearestScreenPt.Y} r={this._props.screenSpaceLineWidth * 2} fill={'#00007777'} stroke={'#00007777'} strokeWidth={0} pointerEvents="none" />}
                 {sreenCtrlPoints.map(control => hdl(control, this._overControl !== control.I ? 1 : 3 / 2, Colors.WHITE))}
             </svg>
         );
@@ -185,10 +191,15 @@ export interface InkEndProps {
     endPt: () => PointData;
 }
 @observer
-export class InkEndPtHandles extends React.Component<InkEndProps> {
+export class InkEndPtHandles extends ObservableReactComponent<InkEndProps> {
     @observable _overStart: boolean = false;
     @observable _overEnd: boolean = false;
 
+    constructor(props: InkEndProps) {
+        super(props);
+        makeObservable(this);
+    }
+
     _throttle = 0; // need to throttle dragging since the position may change when the control points change.  this allows the stroke to settle so that we don't get increasingly bad jitter
     @action
     dragRotate = (e: React.PointerEvent, pt1: () => { X: number; Y: number }, pt2: () => { X: number; Y: number }) => {
@@ -198,7 +209,7 @@ export class InkEndPtHandles extends React.Component<InkEndProps> {
             e,
             action(e => {
                 if (this._throttle++ % 2 !== 0) return false;
-                if (!this.props.inkView.controlUndo) this.props.inkView.controlUndo = UndoManager.StartBatch('stretch ink');
+                if (!this._props.inkView.controlUndo) this._props.inkView.controlUndo = UndoManager.StartBatch('stretch ink');
                 // compute stretch factor by finding scaling along axis between start and end points
                 const p1 = pt1();
                 const p2 = pt2();
@@ -216,8 +227,8 @@ export class InkEndPtHandles extends React.Component<InkEndProps> {
             }),
             action(() => {
                 SnappingManager.SetIsDragging(false);
-                this.props.inkView.controlUndo?.end();
-                this.props.inkView.controlUndo = undefined;
+                this._props.inkView.controlUndo?.end();
+                this._props.inkView.controlUndo = undefined;
                 UndoManager.FilterBatches(['stroke', 'x', 'y', 'width', 'height']);
             }),
             returnFalse
@@ -230,7 +241,7 @@ export class InkEndPtHandles extends React.Component<InkEndProps> {
                 key={key}
                 cx={pt.X}
                 cy={pt.Y}
-                r={this.props.screenSpaceLineWidth * 2}
+                r={this._props.screenSpaceLineWidth * 2}
                 fill={this._overStart ? '#aaaaaa' : '#99999977'}
                 stroke={'#00007777'}
                 strokeWidth={0}
@@ -242,8 +253,8 @@ export class InkEndPtHandles extends React.Component<InkEndProps> {
         );
         return (
             <svg>
-                {hdl('start', this.props.startPt(), e => this.dragRotate(e, this.props.startPt, this.props.endPt))}
-                {hdl('end', this.props.endPt(), e => this.dragRotate(e, this.props.endPt, this.props.startPt))}
+                {hdl('start', this._props.startPt(), e => this.dragRotate(e, this._props.startPt, this._props.endPt))}
+                {hdl('end', this._props.endPt(), e => this.dragRotate(e, this._props.endPt, this._props.startPt))}
             </svg>
         );
     }
-- 
cgit v1.2.3-70-g09d2

