From 3a269cb5120dbad1002c7cb4005776a25556b6e3 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 1 Jul 2024 14:06:34 -0400
Subject: moved active ink settings to DocumentView from Doc.  Changed how ink
 fill color is set based on what is selected.

---
 src/client/views/nodes/DocumentView.tsx | 50 +++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

(limited to 'src/client/views/nodes/DocumentView.tsx')

diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 7a1f94948..0ded01c80 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1568,6 +1568,56 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
     }
 }
 
+export function ActiveFillColor(): string { 
+    const dv = DocumentView.Selected().lastElement() ?.Document._layout_isSvg ? DocumentView.Selected().lastElement() : undefined;
+    return StrCast(dv?.Document.fillColor, StrCast(ActiveInkPen()?.activeFillColor, "")); 
+} // prettier-ignore
+export function ActiveInkPen(): Doc { return Doc.UserDoc(); } // prettier-ignore
+export function ActiveInkColor(): string { return StrCast(ActiveInkPen()?.activeInkColor, 'black'); } // prettier-ignore
+export function ActiveIsInkMask(): boolean { return BoolCast(ActiveInkPen()?.activeIsInkMask, false); } // prettier-ignore
+export function ActiveInkHideTextLabels(): boolean { return BoolCast(ActiveInkPen().activeInkHideTextLabels, false); } // prettier-ignore
+export function ActiveArrowStart(): string { return StrCast(ActiveInkPen()?.activeArrowStart, ''); } // prettier-ignore
+export function ActiveArrowEnd(): string { return StrCast(ActiveInkPen()?.activeArrowEnd, ''); } // prettier-ignore
+export function ActiveArrowScale(): number { return NumCast(ActiveInkPen()?.activeArrowScale, 1); } // prettier-ignore
+export function ActiveDash(): string { return StrCast(ActiveInkPen()?.activeDash, '0'); } // prettier-ignore
+export function ActiveInkWidth(): number { return Number(ActiveInkPen()?.activeInkWidth); } // prettier-ignore
+export function ActiveInkBezierApprox(): string { return StrCast(ActiveInkPen()?.activeInkBezier); } // prettier-ignore
+export function ActiveEraserWidth(): number { return Number(ActiveInkPen()?.eraserWidth); } // prettier-ignore
+
+export function SetActiveInkWidth(width: string): void {
+    !isNaN(parseInt(width)) && ActiveInkPen() && (ActiveInkPen().activeInkWidth = width);
+}
+export function SetActiveBezierApprox(bezier: string): void {
+    ActiveInkPen() && (ActiveInkPen().activeInkBezier = isNaN(parseInt(bezier)) ? '' : bezier);
+}
+export function SetActiveInkColor(value: string) {
+    ActiveInkPen() && (ActiveInkPen().activeInkColor = value);
+}
+export function SetActiveIsInkMask(value: boolean) {
+    ActiveInkPen() && (ActiveInkPen().activeIsInkMask = value);
+}
+export function SetActiveInkHideTextLabels(value: boolean) {
+    ActiveInkPen() && (ActiveInkPen().activeInkHideTextLabels = value);
+}
+export function SetActiveFillColor(value: string) {
+    ActiveInkPen() && (ActiveInkPen().activeFillColor = value);
+}
+export function SetActiveArrowStart(value: string) {
+    ActiveInkPen() && (ActiveInkPen().activeArrowStart = value);
+}
+export function SetActiveArrowEnd(value: string) {
+    ActiveInkPen() && (ActiveInkPen().activeArrowEnd = value);
+}
+export function SetActiveArrowScale(value: number) {
+    ActiveInkPen() && (ActiveInkPen().activeArrowScale = value);
+}
+export function SetActiveDash(dash: string): void {
+    !isNaN(parseInt(dash)) && ActiveInkPen() && (ActiveInkPen().activeDash = dash);
+}
+export function SetEraserWidth(width: number): void {
+    ActiveInkPen() && (ActiveInkPen().eraserWidth = width);
+}
+
 // eslint-disable-next-line prefer-arrow-callback
 ScriptingGlobals.add(function DocFocusOrOpen(docIn: Doc, optionsIn?: FocusViewOptions, containingDoc?: Doc) {
     return DocumentView.FocusOrOpen(docIn, optionsIn, containingDoc);
-- 
cgit v1.2.3-70-g09d2


From e7e5bbc43feaf00140b42da67a3c001fc8babec7 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 10 Jul 2024 09:21:12 -0400
Subject: fixed undoing bringToFront selections - made longPress observable
 work.  made ink  strokes keep Z index by default when clicked.

---
 src/client/documents/Documents.ts                  |  1 +
 src/client/util/SnappingManager.ts                 |  3 +
 src/client/views/MainView.tsx                      |  6 +-
 .../views/nodes/CollectionFreeFormDocumentView.tsx |  9 ++-
 src/client/views/nodes/DocumentView.tsx            | 65 ++++++++++------------
 5 files changed, 44 insertions(+), 40 deletions(-)

(limited to 'src/client/views/nodes/DocumentView.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 2dcf8a54c..b96fdb4bd 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -849,6 +849,7 @@ export namespace Docs {
             I.text_align = 'center';
             I.rotation = 0;
             I.defaultDoubleClick = 'ignore';
+            I.keepZWhenDragged = true;
             I.author_date = new DateField();
             I.acl_Guest = Doc.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.View;
             // I.acl_Override = SharingPermissions.Unset;
diff --git a/src/client/util/SnappingManager.ts b/src/client/util/SnappingManager.ts
index 1337d271f..cc0366c5b 100644
--- a/src/client/util/SnappingManager.ts
+++ b/src/client/util/SnappingManager.ts
@@ -11,6 +11,7 @@ export class SnappingManager {
         return SnappingManager._manager ?? new SnappingManager();
     }
 
+    @observable _longPress = false;
     @observable _shiftKey = false;
     @observable _ctrlKey = false;
     @observable _metaKey = false;
@@ -43,6 +44,7 @@ export class SnappingManager {
 
     public static get HorizSnapLines() { return this.Instance._horizSnapLines; } // prettier-ignore
     public static get VertSnapLines()  { return this.Instance._vertSnapLines; } // prettier-ignore
+    public static get LongPress()      { return this.Instance._longPress; } // prettier-ignore
     public static get ShiftKey()       { return this.Instance._shiftKey; } // prettier-ignore
     public static get CtrlKey()        { return this.Instance._ctrlKey; } // prettier-ignore
     public static get MetaKey()        { return this.Instance._metaKey; } // prettier-ignore
@@ -58,6 +60,7 @@ export class SnappingManager {
     public static get PropertiesWidth(){ return this.Instance._propertyWid; } // prettier-ignore
     public static get PrintToConsole() { return this.Instance._printToConsole; } // prettier-ignore
 
+    public static SetLongPress      = (press: boolean) => runInAction(() => {this.Instance._longPress = press}); // prettier-ignore
     public static SetShiftKey       = (down: boolean) => runInAction(() => {this.Instance._shiftKey = down}); // prettier-ignore
     public static SetCtrlKey        = (down: boolean) => runInAction(() => {this.Instance._ctrlKey = down}); // prettier-ignore
     public static SetMetaKey        = (down: boolean) => runInAction(() => {this.Instance._metaKey = down}); // prettier-ignore
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 31d88fb87..ef1bcfb64 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -555,16 +555,16 @@ export class MainView extends ObservableReactComponent<{}> {
     private longPressTimer: NodeJS.Timeout | undefined;
     globalPointerClick = action(() => {
         this.longPressTimer && clearTimeout(this.longPressTimer);
-        DocumentView.LongPress = false;
+        SnappingManager.SetLongPress(false);
     });
     globalPointerMove = action((e: PointerEvent) => {
         if (e.movementX > 3 || e.movementY > 3) this.longPressTimer && clearTimeout(this.longPressTimer);
     });
     globalPointerDown = action((e: PointerEvent) => {
-        DocumentView.LongPress = false;
+        SnappingManager.SetLongPress(false);
         this.longPressTimer = setTimeout(
             action(() => {
-                DocumentView.LongPress = true;
+                SnappingManager.SetLongPress(true);
             }),
             1000
         );
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 034a38e9c..29a499035 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -20,6 +20,11 @@ import { DocumentView, DocumentViewProps } from './DocumentView';
 import { FieldViewProps } from './FieldView';
 import { OpenWhere } from './OpenWhere';
 
+export enum GroupActive { // flags for whether a view is activate because of its relationship to a group
+    group = 'group', // this is a group that is activated because it's on an active canvas, but is not part of some other group
+    child = 'child', // this is a group child that is activated because its containing group is activated
+    inactive = 'inactive', // this is a group child but it is not active
+}
 /// Ugh, typescript has no run-time way of iterating through the keys of an interface.  so we need
 /// manaully keep this list of keys in synch wih the fields of the freeFormProps interface
 const freeFormPropsKeys = ['x', 'y', 'z', 'zIndex', 'rotation', 'opacity', 'backgroundColor', 'color', 'highlight', 'width', 'height', 'autoDim', 'transition'];
@@ -274,7 +279,9 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
         if (this._props.isAnyChildContentActive()) return undefined;
         const backColor = this.BackgroundColor;
         const isGroup = this.dataDoc.isGroup && (!backColor || backColor === 'transparent');
-        return isGroup ? (this._props.isDocumentActive?.() ? 'group' : this._props.isGroupActive?.() ? 'child' : 'inactive') : this._props.isGroupActive?.() ? 'child' : undefined;
+        return isGroup ? (this._props.isDocumentActive?.() ? GroupActive.group : 
+                          this._props.isGroupActive?.() ? GroupActive.child : GroupActive.inactive) : 
+               this._props.isGroupActive?.() ? GroupActive.child : undefined; // prettier-ignore
     };
     localRotation = () => this._props.rotation;
     render() {
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 0ded01c80..3cf40c087 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -43,6 +43,7 @@ import { ObserverJsxParser } from '../ObservableReactComponent';
 import { PinProps } from '../PinFuncs';
 import { StyleProp } from '../StyleProp';
 import { ViewBoxInterface } from '../ViewBoxInterface';
+import { GroupActive } from './CollectionFreeFormDocumentView';
 import { DocumentContentsView } from './DocumentContentsView';
 import { DocumentLinksButton } from './DocumentLinksButton';
 import './DocumentView.scss';
@@ -153,7 +154,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
 
     @computed get disableClickScriptFunc() {
         const onScriptDisable = this._props.onClickScriptDisable ?? this._componentView?.onClickScriptDisable?.() ?? this.layoutDoc.onClickScriptDisable;
-        return (DocumentView.LongPress ||
+        return (SnappingManager.LongPress ||
                 onScriptDisable === 'always' ||
                 (onScriptDisable !== 'never' && (this.rootSelected() || this._componentView?.isAnyChildContentActive?.()))); // prettier-ignore
     }
@@ -297,17 +298,15 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
         e.stopPropagation();
     };
     onClick = action((e: React.MouseEvent | React.PointerEvent) => {
-        if (this._props.isGroupActive?.() === 'child' && !this._props.isDocumentActive?.()) return;
-        const documentView = this._docView;
-        if (documentView && !this.Document.ignoreClick && this._props.renderDepth >= 0 && ClientUtils.isClick(e.clientX, e.clientY, this._downX, this._downY, this._downTime)) {
+        if (this._props.isGroupActive?.() === GroupActive.child && !this._props.isDocumentActive?.()) return;
+        if (this._docView && !this.Document.ignoreClick && this._props.renderDepth >= 0 && ClientUtils.isClick(e.clientX, e.clientY, this._downX, this._downY, this._downTime)) {
             let stopPropagate = true;
             let preventDefault = true;
-            !this.layoutDoc._keepZWhenDragged && this._props.bringToFront?.(this.Document);
             const scriptProps = {
                 this: this.Document,
                 _readOnly_: false,
                 scriptContext: this._props.scriptContext,
-                documentView,
+                documentView: this._docView,
                 clientX: e.clientX,
                 clientY: e.clientY,
                 shiftKey: e.shiftKey,
@@ -317,44 +316,39 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
             };
             if (this._doubleTap) {
                 const defaultDblclick = this._props.defaultDoubleClick?.() || this.Document.defaultDoubleClick;
-                if (this.onDoubleClickHdlr?.script) {
-                    UndoManager.RunInBatch(() => this.onDoubleClickHdlr.script.run(scriptProps, console.log).result?.select && this._props.select(false), 'on double click: ' + this.Document.title);
-                } else if (!Doc.IsSystem(this.Document) && defaultDblclick !== 'ignore') {
-                    UndoManager.RunInBatch(() => this._props.addDocTab(this.Document, OpenWhere.lightboxAlways), 'double tap');
-                    DocumentView.DeselectAll();
-                    Doc.UnBrushDoc(this.Document);
-                } else {
-                    this._singleClickFunc?.();
-                }
+                undoable(() => {
+                    if (this.onDoubleClickHdlr?.script) {
+                        this.onDoubleClickHdlr.script.run(scriptProps, console.log).result?.select && this._props.select(false);
+                    } else if (!Doc.IsSystem(this.Document) && defaultDblclick !== 'ignore') {
+                        this._props.addDocTab(this.Document, OpenWhere.lightboxAlways);
+                        DocumentView.DeselectAll();
+                        Doc.UnBrushDoc(this.Document);
+                    } else this._singleClickFunc?.();
+                }, 'on double click: ' + this.Document.title)();
                 this._doubleClickTimeout && clearTimeout(this._doubleClickTimeout);
                 this._doubleClickTimeout = undefined;
                 this._singleClickFunc = undefined;
             } else {
-                let clickFunc: undefined | (() => any);
-                if (!this.disableClickScriptFunc && this.onClickHdlr?.script) {
-                    clickFunc = undoable(() => {
-                        this.onClickHdlr?.script.run(scriptProps, console.log).result?.select && this._props.select(false);
-                    }, 'click ' + this.Document.title);
-                } else {
-                    // onDragStart implies a button doc that we don't want to select when clicking. RootDocument & isTemplateForField implies we're clicking on part of a template instance and we want to select the whole template, not the part
-                    if (this.layoutDoc.onDragStart && !(e.ctrlKey || e.button > 0)) {
-                        stopPropagate = false;
-                    }
-                    preventDefault = false;
-                }
-                const sendToBack = e.altKey ? () => documentView._props.bringToFront?.(this.Document, true) : undefined;
+                const sendToBack = e.altKey ? () => this._props.bringToFront?.(this.Document, true) : undefined;
                 const selectFunc = () => {
+                    !this.layoutDoc._keepZWhenDragged && this._props.bringToFront?.(this.Document);
                     // selecting a view that is part of a template proxies the selection back to the root of the template
                     const templateRoot = !(e.ctrlKey || e.button > 0) && this._props.docViewPath?.().reverse().find(dv => !dv._props.TemplateDataDocument); // prettier-ignore
                     (templateRoot || this._docView)?.select(e.ctrlKey || e.shiftKey, e.metaKey);
                 };
-                this._singleClickFunc = clickFunc ?? sendToBack ?? selectFunc;
-                const waitFordblclick = this._props.waitForDoubleClickToClick?.() ?? this.Document.waitForDoubleClickToClick;
-                if ((clickFunc && waitFordblclick !== 'never') || waitFordblclick === 'always') {
+                const clickFunc = this.onClickFunc?.()?.script ? () => (this.onClickFunc?.()?.script.run(scriptProps, console.log).result as Opt<{ select: boolean }>)?.select && this._props.select(false) : undefined;
+                if (!clickFunc) {
+                    // onDragStart implies a button doc that we don't want to select when clicking. RootDocument & isTemplateForField implies we're clicking on part of a template instance and we want to select the whole template, not the part
+                    if (this.layoutDoc.onDragStart && !(e.ctrlKey || e.button > 0)) stopPropagate = false;
+                    preventDefault = false;
+                }
+                this._singleClickFunc = undoable(clickFunc ?? sendToBack ?? selectFunc, 'click: ' + this.Document.title);
+                const waitForDblClick = this._props.waitForDoubleClickToClick?.() ?? this.Document.waitForDoubleClickToClick;
+                if ((clickFunc && waitForDblClick !== 'never') || waitForDblClick === 'always') {
                     this._doubleClickTimeout && clearTimeout(this._doubleClickTimeout);
                     this._doubleClickTimeout = setTimeout(this._singleClickFunc, 300);
                     // eslint-disable-next-line no-use-before-define
-                } else if (!DocumentView.LongPress) {
+                } else if (!SnappingManager.LongPress) {
                     this._singleClickFunc();
                     this._singleClickFunc = undefined;
                 }
@@ -365,9 +359,9 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
     });
 
     onPointerDown = (e: React.PointerEvent): void => {
-        if (this._props.isGroupActive?.() === 'child' && !this._props.isDocumentActive?.()) return;
+        if (this._props.isGroupActive?.() === GroupActive.child && !this._props.isDocumentActive?.()) return;
         // eslint-disable-next-line no-use-before-define
-        this._longPressSelector = setTimeout(() => DocumentView.LongPress && this._props.select(false), 1000);
+        this._longPressSelector = setTimeout(() => SnappingManager.LongPress && this._props.select(false), 1000);
         if (!DocumentView.DownDocView) DocumentView.DownDocView = this._docView;
 
         this._downX = e.clientX;
@@ -418,7 +412,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
             if (!this.isContentActive()) this._lastTap = Date.now(); // don't want to process the start of a double tap if the doucment is selected
         }
         // eslint-disable-next-line no-use-before-define
-        if (DocumentView.LongPress) e.preventDefault();
+        if (SnappingManager.LongPress) e.preventDefault();
     };
 
     toggleFollowLink = undoable((): void => {
@@ -1124,7 +1118,6 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
     @observable private _htmlOverlayText: Opt<string> = undefined;
     @observable private _isHovering = false;
     @observable private _selected = false;
-    @observable public static LongPress = false;
 
     @computed private get shouldNotScale() {
         return (this.layout_fitWidth && !this.nativeWidth) || this.ComponentView?.isUnstyledView?.();
-- 
cgit v1.2.3-70-g09d2

