From 07c95bfdf0d72cc5ee6cd6612632ac91e47274d1 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sat, 27 Apr 2019 22:00:21 -0400
Subject: fixed dragdecorations titling.  fixed some event issues with dragging
 and textbox's context menu on mac

---
 src/client/views/DocumentDecorations.tsx | 116 +++++++++++++++----------------
 1 file changed, 57 insertions(+), 59 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index cacb9aead..d20df5f4a 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -39,30 +39,23 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
     private _downY = 0;
     @observable private _minimizedX = 0;
     @observable private _minimizedY = 0;
-    //@observable private _title: string = this._documents[0].props.Document.Title;
-    @observable private _title: string = this._documents.length > 0 ? this._documents[0].props.Document.Title : "";
+    @observable private _title: string = "";
+    @observable private _edtingTitle = false;
     @observable private _fieldKey: Key = KeyStore.Title;
     @observable private _hidden = false;
     @observable private _opacity = 1;
-    @observable private _dragging = false;
     @observable private _iconifying = false;
     @observable public Interacting = false;
 
-
     constructor(props: Readonly<{}>) {
         super(props);
         DocumentDecorations.Instance = this;
-        this.handleChange = this.handleChange.bind(this);
         this.keyinput = React.createRef();
     }
 
-    @action
-    handleChange = (event: any) => {
-        this._title = event.target.value;
-    }
-
-    @action
-    enterPressed = (e: any) => {
+    @action titleChanged = (event: any) => { this._title = event.target.value; }
+    @action titleBlur = () => { this._edtingTitle = false; }
+    @action titleEntered = (e: any) => {
         var key = e.keyCode || e.which;
         // enter pressed
         if (key === 13) {
@@ -70,32 +63,49 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             if (text[0] === '#') {
                 let command = text.slice(1, text.length);
                 this._fieldKey = new Key(command);
-                // if (command === "Title" || command === "title") {
-                //     this._fieldKey = KeyStore.Title;
-                // }
-                // else if (command === "Width" || command === "width") {
-                //     this._fieldKey = KeyStore.Width;
-                // }
-                this._title = "changed";
-                // TODO: Change field with switch statement
+                this._title = this.getTitle();
             }
             else {
                 if (this._documents.length > 0) {
                     let field = this._documents[0].props.Document.Get(this._fieldKey);
-                    if (field instanceof TextField) {
+                    if (field instanceof NumberField) {
                         this._documents.forEach(d =>
-                            d.props.Document.Set(this._fieldKey, new TextField(this._title)));
-                    }
-                    else if (field instanceof NumberField) {
+                            d.props.Document.SetNumber(this._fieldKey, +this._title));
+                    } else if (field instanceof TextField || true) {
                         this._documents.forEach(d =>
-                            d.props.Document.Set(this._fieldKey, new NumberField(+this._title)));
+                            d.props.Document.SetText(this._fieldKey, this._title));
                     }
-                    this._title = "changed";
                 }
             }
             e.target.blur();
         }
     }
+    @action onTitleDown = (e: React.PointerEvent): void => {
+        this._downX = e.clientX;
+        this._downY = e.clientY;
+        e.stopPropagation();
+        this.onBackgroundDown(e);
+        document.removeEventListener("pointermove", this.onTitleMove);
+        document.removeEventListener("pointerup", this.onTitleUp);
+        document.addEventListener("pointermove", this.onTitleMove);
+        document.addEventListener("pointerup", this.onTitleUp);
+    }
+    @action onTitleMove = (e: PointerEvent): void => {
+        if (Math.abs(e.clientX - this._downX) > 4 || Math.abs(e.clientY - this._downY) > 4) {
+            this.Interacting = true;
+        }
+        if (this.Interacting) this.onBackgroundMove(e);
+        e.stopPropagation();
+    }
+    @action onTitleUp = (e: PointerEvent): void => {
+        if (Math.abs(e.clientX - this._downX) < 4 || Math.abs(e.clientY - this._downY) < 4) {
+            this._title = this.getTitle();
+            this._edtingTitle = true;
+        }
+        document.removeEventListener("pointermove", this.onTitleMove);
+        document.removeEventListener("pointerup", this.onTitleUp);
+        this.onBackgroundUp(e);
+    }
 
     @computed
     get Bounds(): { x: number, y: number, b: number, r: number } {
@@ -114,50 +124,40 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         }, { x: Number.MAX_VALUE, y: Number.MAX_VALUE, r: Number.MIN_VALUE, b: Number.MIN_VALUE });
     }
 
-
-    @computed
-    public get Hidden() { return this._hidden; }
-    public set Hidden(value: boolean) { this._hidden = value; }
-
-    _lastDrag: number[] = [0, 0];
     onBackgroundDown = (e: React.PointerEvent): void => {
         document.removeEventListener("pointermove", this.onBackgroundMove);
-        document.addEventListener("pointermove", this.onBackgroundMove);
         document.removeEventListener("pointerup", this.onBackgroundUp);
+        document.addEventListener("pointermove", this.onBackgroundMove);
         document.addEventListener("pointerup", this.onBackgroundUp);
-        this._lastDrag = [e.clientX, e.clientY];
         e.stopPropagation();
-        if (e.currentTarget.localName !== "input") {
-            e.preventDefault();
-        }
+        e.preventDefault();
     }
 
     @action
     onBackgroundMove = (e: PointerEvent): void => {
         let dragDocView = SelectionManager.SelectedDocuments()[0];
         const [left, top] = dragDocView.props.ScreenToLocalTransform().scale(dragDocView.props.ContentScaling()).inverse().transformPoint(0, 0);
-        let dragData = new DragManager.DocumentDragData(SelectionManager.SelectedDocuments().map(dv => dv.props.Document));
         const [xoff, yoff] = dragDocView.props.ScreenToLocalTransform().scale(dragDocView.props.ContentScaling()).transformDirection(e.x - left, e.y - top);
+        let dragData = new DragManager.DocumentDragData(SelectionManager.SelectedDocuments().map(dv => dv.props.Document));
         dragData.xOffset = xoff;
         dragData.yOffset = yoff;
         dragData.aliasOnDrop = false;
-        let move = SelectionManager.SelectedDocuments()[0].props.moveDocument;
-        dragData.moveDocument = move;
-        this.Interacting = this._dragging = true;
+        dragData.moveDocument = SelectionManager.SelectedDocuments()[0].props.moveDocument;
+        this.Interacting = true;
+        this._hidden = true;
         document.removeEventListener("pointermove", this.onBackgroundMove);
         document.removeEventListener("pointerup", this.onBackgroundUp);
-        this.Hidden = true;
+        document.removeEventListener("pointermove", this.onTitleMove);
+        document.removeEventListener("pointerup", this.onTitleUp);
         DragManager.StartDocumentDrag(SelectionManager.SelectedDocuments().map(docView => docView.ContentDiv!), dragData, e.x, e.y, {
-            handlers: {
-                dragComplete: action(() => this.Interacting = this._dragging = false),
-            },
+            handlers: { dragComplete: action(() => this._hidden = this.Interacting = false) },
             hideSource: true
         });
         e.stopPropagation();
     }
 
+    @action
     onBackgroundUp = (e: PointerEvent): void => {
-        this.Hidden = true;
         document.removeEventListener("pointermove", this.onBackgroundMove);
         document.removeEventListener("pointerup", this.onBackgroundUp);
         e.stopPropagation();
@@ -451,7 +451,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         }
     }
 
-    getValue = (): string => {
+    getTitle = (): string => {
         if (this._documents.length > 0) {
             let field = this._documents[0].props.Document.Get(this._fieldKey);
             if (field instanceof TextField) {
@@ -461,7 +461,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 return (field).GetValue().toString();
             }
         }
-        return this._title;
+        return "-unset-";
     }
 
     changeFlyoutContent = (): void => {
@@ -473,21 +473,17 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
     render() {
         var bounds = this.Bounds;
         let seldoc = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0] : undefined;
-        if (bounds.x === Number.MAX_VALUE || !seldoc) {
-            return (null);
-        }
-        let minimizeIcon = (
-            <div className="documentDecorations-minimizeButton" onPointerDown={this.onMinimizeDown}>
-                {SelectionManager.SelectedDocuments().length == 1 ? IconBox.DocumentIcon(SelectionManager.SelectedDocuments()[0].props.Document.GetText(KeyStore.Layout, "...")) : "..."}
-            </div>);
-
-        if (this.Hidden) {
+        if (bounds.x === Number.MAX_VALUE || !seldoc || this._hidden) {
             return (null);
         }
         if (isNaN(bounds.r) || isNaN(bounds.b) || isNaN(bounds.x) || isNaN(bounds.y)) {
             console.log("DocumentDecorations: Bounds Error");
             return (null);
         }
+        let minimizeIcon = (
+            <div className="documentDecorations-minimizeButton" onPointerDown={this.onMinimizeDown}>
+                {SelectionManager.SelectedDocuments().length == 1 ? IconBox.DocumentIcon(SelectionManager.SelectedDocuments()[0].props.Document.GetText(KeyStore.Layout, "...")) : "..."}
+            </div>);
 
         let linkButton = null;
         if (SelectionManager.SelectedDocuments().length > 0) {
@@ -508,7 +504,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 height: (bounds.b - bounds.y + this._resizeBorderWidth) + "px",
                 left: bounds.x - this._resizeBorderWidth / 2,
                 top: bounds.y - this._resizeBorderWidth / 2,
-                pointerEvents: this._dragging ? "none" : "all",
+                pointerEvents: this.Interacting ? "none" : "all",
                 zIndex: SelectionManager.SelectedDocuments().length > 1 ? 1000 : 0,
             }} onPointerDown={this.onBackgroundDown} onContextMenu={(e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation(); }} >
             </div>
@@ -521,7 +517,9 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             }}>
                 {minimizeIcon}
 
-                <input ref={this.keyinput} className="title" type="text" name="dynbox" value={this.getValue()} onChange={this.handleChange} onPointerDown={this.onBackgroundDown} onKeyPress={this.enterPressed} />
+                {this._edtingTitle ?
+                    <input ref={this.keyinput} className="title" type="text" name="dynbox" value={this._title} onBlur={this.titleBlur} onChange={this.titleChanged} onKeyPress={this.titleEntered} /> :
+                    <div className="title" onPointerDown={this.onTitleDown} >{`${this.getTitle()}`}</div>}
                 <div className="documentDecorations-closeButton" onPointerDown={this.onCloseDown}>X</div>
                 <div id="documentDecorations-topLeftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                 <div id="documentDecorations-topResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
-- 
cgit v1.2.3-70-g09d2

