From fd8e6bf2cacf8bed7c3363eeb777c731741266d5 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Thu, 11 Apr 2019 20:19:57 -0400
Subject: made COLLECTION_BORDER_WIDTH a CSS variable accessible from code. 
 changed global css variable file name

---
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 31 ++++++++++++----------
 1 file changed, 17 insertions(+), 14 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 01ebbe0e1..e38e71a68 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1,31 +1,31 @@
-import { action, computed, observable, trace, ObservableSet, runInAction } from "mobx";
+import { action, computed, observable, runInAction } from "mobx";
 import { observer } from "mobx-react";
+import Measure from "react-measure";
 import { Document } from "../../../../fields/Document";
 import { FieldWaiting } from "../../../../fields/Field";
 import { KeyStore } from "../../../../fields/KeyStore";
+import { NumberField } from "../../../../fields/NumberField";
 import { TextField } from "../../../../fields/TextField";
+import { emptyFunction, returnFalse } from "../../../../Utils";
+import { DocumentManager } from "../../../util/DocumentManager";
 import { DragManager } from "../../../util/DragManager";
+import { SelectionManager } from "../../../util/SelectionManager";
 import { Transform } from "../../../util/Transform";
 import { undoBatch } from "../../../util/UndoManager";
+import * as globalCssVariables from "../../../views/globalCssVariables.scss";
 import { InkingCanvas } from "../../InkingCanvas";
+import { Main } from "../../Main";
 import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDocumentView";
 import { DocumentContentsView } from "../../nodes/DocumentContentsView";
 import { DocumentViewProps } from "../../nodes/DocumentView";
-import { COLLECTION_BORDER_WIDTH } from "../CollectionBaseView";
 import { CollectionSubView } from "../CollectionSubView";
 import { CollectionFreeFormLinksView } from "./CollectionFreeFormLinksView";
+import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCursors";
 import "./CollectionFreeFormView.scss";
 import { MarqueeView } from "./MarqueeView";
+import { PreviewCursor } from "./PreviewCursor";
 import React = require("react");
 import v5 = require("uuid/v5");
-import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCursors";
-import { PreviewCursor } from "./PreviewCursor";
-import { DocumentManager } from "../../../util/DocumentManager";
-import { SelectionManager } from "../../../util/SelectionManager";
-import { NumberField } from "../../../../fields/NumberField";
-import { Main } from "../../Main";
-import Measure from "react-measure";
-import { returnFalse, emptyFunction } from "../../../../Utils";
 
 @observer
 export class CollectionFreeFormView extends CollectionSubView {
@@ -297,8 +297,12 @@ export class CollectionFreeFormView extends CollectionSubView {
                 layoutKey={KeyStore.OverlayLayout} isTopMost={this.props.isTopMost} isSelected={returnFalse} select={emptyFunction} />);
     }
 
-    getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH).translate(-this.centeringShiftX, -this.centeringShiftY).transform(this.getLocalTransform());
-    getContainerTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH);
+    @computed
+    get borderWidth() {
+        return this.isAnnotationOverlay ? 0 : globalCssVariables.COLLECTION_BORDER_WIDTH;
+    }
+    getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth, -this.borderWidth).translate(-this.centeringShiftX, -this.centeringShiftY).transform(this.getLocalTransform());
+    getContainerTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth, -this.borderWidth);
     getLocalTransform = (): Transform => Transform.Identity().scale(1 / this.scale).translate(this.panX, this.panY);
     noScaling = () => 1;
     childViews = () => this.views;
@@ -317,8 +321,7 @@ export class CollectionFreeFormView extends CollectionSubView {
                     <div className={`collectionfreeformview-measure`} ref={measureRef}>
                         <div className={`collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`}
                             onPointerDown={this.onPointerDown} onPointerMove={(e) => super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY))}
-                            onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} onWheel={this.onPointerWheel}
-                            style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }} ref={this.createDropTarget}>
+                            onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} onWheel={this.onPointerWheel} ref={this.createDropTarget}>
                             <MarqueeView container={this} activeDocuments={this.getActiveDocuments} selectDocuments={this.selectDocuments}
                                 addDocument={this.addDocument} removeDocument={this.props.removeDocument}
                                 getContainerTransform={this.getContainerTransform} getTransform={this.getTransform}>
-- 
cgit v1.2.3-70-g09d2


From c694f7d7d9fbb88f2b2fa6ebb6093e9265a0b0b7 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 12 Apr 2019 16:04:08 -0400
Subject: moved previewcursor to main

---
 src/client/views/Main.tsx                          | 37 +++++++++++++++++
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  3 +-
 .../collectionFreeForm/PreviewCursor.tsx           | 47 +++-------------------
 3 files changed, 44 insertions(+), 43 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 419de6fc1..ac00be63c 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -40,7 +40,43 @@ import { DocumentView } from './nodes/DocumentView';
 import { FormattedTextBox } from './nodes/FormattedTextBox';
 import { REPLCommand } from 'repl';
 import { Key } from '../../fields/Key';
+import { truncate } from 'fs';
 
+
+export interface PromptProps {
+}
+
+@observer
+export class PreviewCursorPrompt extends React.Component<PromptProps> {
+    private _prompt = React.createRef<HTMLDivElement>();
+    //when focus is lost, this will remove the preview cursor
+    @action onBlur = (): void => {
+        PreviewCursorPrompt.Visible = false;
+        PreviewCursorPrompt.hide();
+    }
+
+    @observable static clickPoint = [0, 0];
+    @observable public static Visible = false;
+    @observable public static hide = () => { };
+    @action
+    public static Show(hide: any, x: number, y: number) {
+        this.clickPoint = [x, y];
+        this.hide = hide;
+        setTimeout(action(() => this.Visible = true), (1));
+    }
+    render() {
+        if (!PreviewCursorPrompt.clickPoint)
+            return (null);
+        if (PreviewCursorPrompt.Visible && this._prompt.current) {
+            this._prompt.current.focus();
+        }
+        let p = PreviewCursorPrompt.clickPoint;
+        return <div className="previewCursor" id="previewCursor" onBlur={this.onBlur} tabIndex={0} ref={this._prompt}
+            style={{ transform: `translate(${p[0]}px, ${p[1]}px)`, opacity: PreviewCursorPrompt.Visible ? 1 : 0 }}>
+            I
+        </div >;
+    }
+}
 @observer
 export class Main extends React.Component {
     // dummy initializations keep the compiler happy
@@ -392,6 +428,7 @@ export class Main extends React.Component {
                         {({ measureRef }) =>
                             <div ref={measureRef} id="mainContent-div">
                                 {this.mainContent}
+                                <PreviewCursorPrompt />
                             </div>
                         }
                     </Measure>
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index e38e71a68..dae62f126 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -325,8 +325,7 @@ export class CollectionFreeFormView extends CollectionSubView {
                             <MarqueeView container={this} activeDocuments={this.getActiveDocuments} selectDocuments={this.selectDocuments}
                                 addDocument={this.addDocument} removeDocument={this.props.removeDocument}
                                 getContainerTransform={this.getContainerTransform} getTransform={this.getTransform}>
-                                <PreviewCursor container={this} addLiveTextDocument={this.addLiveTextBox}
-                                    getContainerTransform={this.getContainerTransform} getTransform={this.getTransform} >
+                                <PreviewCursor container={this} addLiveTextDocument={this.addLiveTextBox} getTransform={this.getTransform} >
                                     <div className="collectionfreeformview" ref={this._canvasRef}
                                         style={{ transform: `translate(${dx}px, ${dy}px) scale(${zoom}, ${zoom}) translate(${panx}px, ${pany}px)` }}>
                                         {blay}
diff --git a/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx b/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx
index 8eabb020a..64da8ecc6 100644
--- a/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx
+++ b/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx
@@ -6,12 +6,11 @@ import { Transform } from "../../../util/Transform";
 import { CollectionFreeFormView } from "./CollectionFreeFormView";
 import "./PreviewCursor.scss";
 import React = require("react");
-import { interfaceDeclaration } from "babel-types";
+import { Main, PreviewCursorPrompt } from "../../Main";
 
 
 export interface PreviewCursorProps {
     getTransform: () => Transform;
-    getContainerTransform: () => Transform;
     container: CollectionFreeFormView;
     addLiveTextDocument: (doc: Document) => void;
 }
@@ -20,7 +19,6 @@ export interface PreviewCursorProps {
 export class PreviewCursor extends React.Component<PreviewCursorProps>  {
     @observable _lastX: number = 0;
     @observable _lastY: number = 0;
-    @observable public _visible: boolean = false;
     @observable public DownX: number = 0;
     @observable public DownY: number = 0;
     _showOnUp: boolean = false;
@@ -46,17 +44,14 @@ export class PreviewCursor extends React.Component<PreviewCursorProps>  {
     onPointerMove = (e: PointerEvent): void => {
         if (Math.abs(this.DownX - e.clientX) > 4 || Math.abs(this.DownY - e.clientY) > 4) {
             this._showOnUp = false;
-            this._visible = false;
+            PreviewCursorPrompt.Visible = false;
         }
     }
 
-    @action
     onPointerUp = (e: PointerEvent): void => {
         if (this._showOnUp) {
+            PreviewCursorPrompt.Show(this.hideCursor, this.DownX, this.DownY);
             document.addEventListener("keypress", this.onKeyPress, false);
-            this._lastX = this.DownX;
-            this._lastY = this.DownY;
-            this._visible = true;
         }
         this.cleanupInteractions();
     }
@@ -69,52 +64,22 @@ export class PreviewCursor extends React.Component<PreviewCursorProps>  {
         //if not these keys, make a textbox if preview cursor is active!
         if (!e.ctrlKey && !e.altKey && !e.defaultPrevented && !(e as any).DASHFormattedTextBoxHandled) {
             //make textbox and add it to this collection
-            let [x, y] = this.props.getTransform().transformPoint(this._lastX, this._lastY);
+            let [x, y] = this.props.getTransform().transformPoint(this.DownX, this.DownY);
             let newBox = Documents.TextDocument({ width: 200, height: 100, x: x, y: y, title: "typed text" });
             this.props.addLiveTextDocument(newBox);
-            document.removeEventListener("keypress", this.onKeyPress, false);
-            this._visible = false;
+            PreviewCursorPrompt.Visible = false;
             e.stopPropagation();
         }
     }
 
-    getPoint = () => this.props.getContainerTransform().transformPoint(this._lastX, this._lastY);
-    getVisible = () => this._visible;
-    setVisible = (v: boolean) => {
-        this._visible = v;
+    hideCursor = () => {
         document.removeEventListener("keypress", this.onKeyPress, false);
     }
     render() {
         return (
             <div className="previewCursorView" onPointerDown={this.onPointerDown}>
                 {this.props.children}
-                <PreviewCursorPrompt setVisible={this.setVisible} getPoint={this.getPoint} getVisible={this.getVisible} />
             </div>
         );
     }
-}
-
-export interface PromptProps {
-    getPoint: () => number[];
-    getVisible: () => boolean;
-    setVisible: (v: boolean) => void;
-}
-
-@observer
-export class PreviewCursorPrompt extends React.Component<PromptProps> {
-    private _promptRef = React.createRef<HTMLDivElement>();
-
-    //when focus is lost, this will remove the preview cursor
-    @action onBlur = (): void => this.props.setVisible(false);
-
-    render() {
-        let p = this.props.getPoint();
-        if (this.props.getVisible() && this._promptRef.current) {
-            this._promptRef.current.focus();
-        }
-        return <div className="previewCursor" id="previewCursor" onBlur={this.onBlur} tabIndex={0} ref={this._promptRef}
-            style={{ transform: `translate(${p[0]}px, ${p[1]}px)`, opacity: this.props.getVisible() ? 1 : 0 }}>
-            I
-        </div >;
-    }
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 83f269b77aa23b641c0ec6b09fe5696936fb221b Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 12 Apr 2019 16:38:13 -0400
Subject: added undo for creating links.  cleaned up some other code.

---
 .../views/collections/CollectionSchemaView.tsx     | 12 +++--
 src/client/views/collections/CollectionSubView.tsx | 51 +++++++++-------------
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  4 +-
 src/client/views/nodes/DocumentView.tsx            | 14 ++++--
 4 files changed, 38 insertions(+), 43 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 4cf187963..162a39170 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -2,16 +2,17 @@ import React = require("react");
 import { library } from '@fortawesome/fontawesome-svg-core';
 import { faCog, faPlus } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, observable, trace, untracked } from "mobx";
+import { action, computed, observable, untracked } from "mobx";
 import { observer } from "mobx-react";
 import Measure from "react-measure";
 import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table";
 import "react-table/react-table.css";
 import { Document } from "../../../fields/Document";
-import { Field, Opt, FieldWaiting } from "../../../fields/Field";
+import { Field, Opt } from "../../../fields/Field";
 import { Key } from "../../../fields/Key";
 import { KeyStore } from "../../../fields/KeyStore";
 import { ListField } from "../../../fields/ListField";
+import { emptyDocFunction, emptyFunction, returnFalse } from "../../../Utils";
 import { Server } from "../../Server";
 import { SetupDrag } from "../../util/DragManager";
 import { CompileScript, ToField } from "../../util/Scripting";
@@ -22,11 +23,8 @@ import { EditableView } from "../EditableView";
 import { DocumentView } from "../nodes/DocumentView";
 import { FieldView, FieldViewProps } from "../nodes/FieldView";
 import "./CollectionSchemaView.scss";
-import { CollectionView } from "./CollectionView";
 import { CollectionSubView } from "./CollectionSubView";
-import { TextField } from "../../../fields/TextField";
-import * as globalCssVariables from "../../views/globalCssVariables.scss";
-import { emptyFunction, returnFalse, emptyDocFunction } from "../../../Utils";
+import { COLLECTION_BORDER_WIDTH } from "../../views/globalCssVariables.scss";
 
 
 // bcz: need to add drag and drop of rows and columns.  This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657
@@ -246,7 +244,7 @@ export class CollectionSchemaView extends CollectionSubView {
     }
 
     @computed
-    get borderWidth() { return globalCssVariables.COLLECTION_BORDER_WIDTH; }
+    get borderWidth() { return COLLECTION_BORDER_WIDTH; }
     getContentScaling = (): number => this._contentScaling;
     getPanelWidth = (): number => this._panelWidth;
     getPanelHeight = (): number => this._panelHeight;
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 6a6a6c900..d91db68bb 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -166,22 +166,16 @@ export class CollectionSubView extends React.Component<SubCollectionViewProps> {
             let item = e.dataTransfer.items[i];
             if (item.kind === "string" && item.type.indexOf("uri") !== -1) {
                 let str: string;
-                let prom = new Promise<string>(res =>
-                    e.dataTransfer.items[i].getAsString(res)).then(action((s: string) => {
-                        str = s;
-                        return rp.head(ServerUtils.prepend(RouteStore.corsProxy + "/" + s));
-                    })).then(res => {
-                        let type = res.headers["content-type"];
+                let prom = new Promise<string>(resolve => e.dataTransfer.items[i].getAsString(resolve))
+                    .then(action((s: string) => rp.head(ServerUtils.prepend(RouteStore.corsProxy + "/" + (str = s)))))
+                    .then(result => {
+                        let type = result.headers["content-type"];
                         if (type) {
-                            this.getDocumentFromType(type, str, { ...options, width: 300, nativeWidth: 300 }).then(doc => {
-                                if (doc) {
-                                    this.props.addDocument(doc, false);
-                                }
-                            });
+                            this.getDocumentFromType(type, str, { ...options, width: 300, nativeWidth: 300 })
+                                .then(doc => doc && this.props.addDocument(doc, false));
                         }
                     });
                 promises.push(prom);
-                // this.props.addDocument(Documents.WebDocument(s, { ...options, width: 300, height: 300 }), false)
             }
             let type = item.type;
             if (item.kind === "file") {
@@ -197,33 +191,30 @@ export class CollectionSubView extends React.Component<SubCollectionViewProps> {
                     method: 'POST',
                     body: formData
                 }).then(async (res: Response) => {
-                    const json = await res.json();
-                    json.map((file: any) => {
+                    (await res.json()).map(action((file: any) => {
                         let path = window.location.origin + file;
-                        runInAction(() => {
-                            let docPromise = this.getDocumentFromType(type, path, { ...options, nativeWidth: 300, width: 300, title: dropFileName });
+                        let docPromise = this.getDocumentFromType(type, path, { ...options, nativeWidth: 300, width: 300, title: dropFileName });
 
-                            docPromise.then(doc => runInAction(() => {
-                                let docs = this.props.Document.GetT(KeyStore.Data, ListField);
-                                if (docs !== FieldWaiting) {
-                                    if (!docs) {
-                                        docs = new ListField<Document>();
-                                        this.props.Document.Set(KeyStore.Data, docs);
-                                    }
-                                    if (doc) {
-                                        docs.Data.push(doc);
-                                    }
+                        docPromise.then(action((doc?: Document) => {
+                            let docs = this.props.Document.GetT(KeyStore.Data, ListField);
+                            if (docs !== FieldWaiting) {
+                                if (!docs) {
+                                    docs = new ListField<Document>();
+                                    this.props.Document.Set(KeyStore.Data, docs);
                                 }
-                            }));
-                        });
-                    });
+                                if (doc) {
+                                    docs.Data.push(doc);
+                                }
+                            }
+                        }));
+                    }));
                 });
                 promises.push(prom);
             }
         }
 
         if (promises.length) {
-            Promise.all(promises).catch(emptyFunction).then(() => batch.end());
+            Promise.all(promises).finally(() => batch.end());
         } else {
             batch.end();
         }
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index dae62f126..98ebbf1b3 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -12,7 +12,7 @@ import { DragManager } from "../../../util/DragManager";
 import { SelectionManager } from "../../../util/SelectionManager";
 import { Transform } from "../../../util/Transform";
 import { undoBatch } from "../../../util/UndoManager";
-import * as globalCssVariables from "../../../views/globalCssVariables.scss";
+import { COLLECTION_BORDER_WIDTH } from "../../../views/globalCssVariables.scss";
 import { InkingCanvas } from "../../InkingCanvas";
 import { Main } from "../../Main";
 import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDocumentView";
@@ -299,7 +299,7 @@ export class CollectionFreeFormView extends CollectionSubView {
 
     @computed
     get borderWidth() {
-        return this.isAnnotationOverlay ? 0 : globalCssVariables.COLLECTION_BORDER_WIDTH;
+        return this.isAnnotationOverlay ? 0 : COLLECTION_BORDER_WIDTH;
     }
     getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth, -this.borderWidth).translate(-this.centeringShiftX, -this.centeringShiftY).transform(this.getLocalTransform());
     getContainerTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth, -this.borderWidth);
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 06182d1a6..4d7a85316 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -20,6 +20,7 @@ import { ContextMenu } from "../ContextMenu";
 import { DocumentContentsView } from "./DocumentContentsView";
 import "./DocumentView.scss";
 import React = require("react");
+import { undoBatch, UndoManager } from "../../util/UndoManager";
 
 
 export interface DocumentViewProps {
@@ -238,6 +239,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         SelectionManager.DeselectAll();
     }
 
+    @undoBatch
     @action
     drop = (e: Event, de: DragManager.DropEvent) => {
         if (de.data instanceof DragManager.LinkDragData) {
@@ -248,6 +250,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
             destDoc.GetTAsync(KeyStore.Prototype, Document).then(protoDest =>
                 sourceDoc.GetTAsync(KeyStore.Prototype, Document).then(protoSrc =>
                     runInAction(() => {
+                        let batch = UndoManager.StartBatch("document view drop");
                         linkDoc.Set(KeyStore.Title, new TextField("New Link"));
                         linkDoc.Set(KeyStore.LinkDescription, new TextField(""));
                         linkDoc.Set(KeyStore.LinkTags, new TextField("Default"));
@@ -256,20 +259,23 @@ export class DocumentView extends React.Component<DocumentViewProps> {
                         let srcTarg = protoSrc ? protoSrc : sourceDoc;
                         linkDoc.Set(KeyStore.LinkedToDocs, dstTarg);
                         linkDoc.Set(KeyStore.LinkedFromDocs, srcTarg);
-                        dstTarg.GetOrCreateAsync(
+                        const prom1 = new Promise(resolve => dstTarg.GetOrCreateAsync(
                             KeyStore.LinkedFromDocs,
                             ListField,
                             field => {
                                 (field as ListField<Document>).Data.push(linkDoc);
+                                resolve();
                             }
-                        );
-                        srcTarg.GetOrCreateAsync(
+                        ));
+                        const prom2 = new Promise(resolve => srcTarg.GetOrCreateAsync(
                             KeyStore.LinkedToDocs,
                             ListField,
                             field => {
                                 (field as ListField<Document>).Data.push(linkDoc);
+                                resolve();
                             }
-                        );
+                        ));
+                        Promise.all([prom1, prom2]).finally(() => batch.end());
                     })
                 )
             );
-- 
cgit v1.2.3-70-g09d2


From 5557c3b87df3119a3e53d2edb4bbdb9ae1deafc4 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 12 Apr 2019 18:28:54 -0400
Subject: fixed brushing

---
 src/client/Server.ts                               |  3 +++
 src/client/northstar/dash-nodes/HistogramBox.tsx   |  4 ----
 src/client/util/DocumentManager.ts                 |  7 ++++--
 src/client/views/Main.tsx                          | 16 ++++++++-----
 .../views/collections/CollectionBaseView.tsx       | 11 +++++----
 .../CollectionFreeFormLinksView.tsx                | 26 +++++++++++++---------
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  1 +
 src/fields/Document.ts                             |  4 ++--
 8 files changed, 42 insertions(+), 30 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/Server.ts b/src/client/Server.ts
index 3bbbebe72..fb5ad1c52 100644
--- a/src/client/Server.ts
+++ b/src/client/Server.ts
@@ -123,6 +123,9 @@ export class Server {
                             callback(fieldfromserver);
                         }
                     }
+                    if (!fieldfromserver && callback) {
+                        console.log("Why didn't we get a field?")
+                    }
                 }));
         }
     }
diff --git a/src/client/northstar/dash-nodes/HistogramBox.tsx b/src/client/northstar/dash-nodes/HistogramBox.tsx
index 7df59ef07..2084fc346 100644
--- a/src/client/northstar/dash-nodes/HistogramBox.tsx
+++ b/src/client/northstar/dash-nodes/HistogramBox.tsx
@@ -47,10 +47,6 @@ export class HistogramBox extends React.Component<FieldViewProps> {
             this.BinRanges[1] instanceof AggregateBinRange ? ChartType.VerticalBar : ChartType.HeatMap;
     }
 
-    constructor(props: FieldViewProps) {
-        super(props);
-    }
-
     @action
     dropX = (e: Event, de: DragManager.DropEvent) => {
         if (de.data instanceof DragManager.DocumentDragData) {
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index f38b8ca75..b62287de8 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -28,8 +28,11 @@ export class DocumentManager {
     }
 
     public getAllDocumentViews(collection: Document) {
-        return this.DocumentViews.filter(dv =>
-            dv.props.ContainingCollectionView && dv.props.ContainingCollectionView.props.Document === collection);
+        return this.DocumentViews.filter(dv => {
+            console.log((dv.props.ContainingCollectionView && dv.props.ContainingCollectionView.props.Document ?
+                dv.props.ContainingCollectionView.props.Document.Title : "--") + " = " + collection.Title);
+            return dv.props.ContainingCollectionView && dv.props.ContainingCollectionView.props.Document === collection;
+        });
     }
 
     public getDocumentView(toFind: Document): DocumentView | null {
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index ac00be63c..3cf8f7c26 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -448,11 +448,11 @@ export class Main extends React.Component {
     @action AddToNorthstarCatalog(ctlog: Catalog) {
         CurrentUserUtils.NorthstarDBCatalog = CurrentUserUtils.NorthstarDBCatalog ? CurrentUserUtils.NorthstarDBCatalog : ctlog;
         if (ctlog && ctlog.schemas) {
-            this._northstarSchemas.push(...ctlog.schemas.map(schema => {
-                let schemaDoc = Documents.TreeDocument([], { width: 50, height: 100, title: schema.displayName! });
-                let schemaDocuments = schemaDoc.GetList(KeyStore.Data, [] as Document[]);
+            ctlog.schemas.map(schema => {
+                let promises: Promise<void>[] = [];
+                let schemaDocuments: Document[] = [];
                 CurrentUserUtils.GetAllNorthstarColumnAttributes(schema).map(attr => {
-                    Server.GetField(attr.displayName! + ".alias", action((field: Opt<Field>) => {
+                    let prom = Server.GetField(attr.displayName! + ".alias").then(action((field: Opt<Field>) => {
                         if (field instanceof Document) {
                             schemaDocuments.push(field);
                         } else {
@@ -464,9 +464,13 @@ export class Main extends React.Component {
                             schemaDocuments.push(Documents.HistogramDocument(histoOp, { width: 200, height: 200, title: attr.displayName! }, undefined, attr.displayName! + ".alias"));
                         }
                     }));
+                    promises.push(prom);
                 });
-                return schemaDoc;
-            }));
+                Promise.all(promises).finally(() => {
+                    let schemaDoc = Documents.TreeDocument(schemaDocuments, { width: 50, height: 100, title: schema.displayName! });
+                    this._northstarSchemas.push(schemaDoc);
+                })
+            })
         }
     }
     async initializeNorthstar(): Promise<void> {
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 0ace700ce..b5eaab349 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -8,8 +8,6 @@ import { ListField } from '../../../fields/ListField';
 import { NumberField } from '../../../fields/NumberField';
 import { ContextMenu } from '../ContextMenu';
 import { FieldViewProps } from '../nodes/FieldView';
-import { CompileScript } from '../../util/Scripting';
-import { ScriptField } from '../../../fields/ScriptField';
 
 export enum CollectionViewType {
     Invalid,
@@ -37,15 +35,15 @@ export interface CollectionViewProps extends FieldViewProps {
 
 @observer
 export class CollectionBaseView extends React.Component<CollectionViewProps> {
-    get collectionViewType(): CollectionViewType {
+    get collectionViewType(): CollectionViewType | undefined {
         let Document = this.props.Document;
         let viewField = Document.GetT(KeyStore.ViewType, NumberField);
         if (viewField === FieldWaiting) {
-            return CollectionViewType.Invalid;
+            return undefined;
         } else if (viewField) {
             return viewField.Data;
         } else {
-            return CollectionViewType.Freeform;
+            return CollectionViewType.Invalid;
         }
     }
 
@@ -181,9 +179,10 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
             active: this.active,
             onActiveChanged: this.onActiveChanged,
         };
+        const viewtype = this.collectionViewType;
         return (
             <div className={this.props.className || "collectionView-cont"} onContextMenu={this.props.onContextMenu} ref={this.props.contentRef}>
-                {this.props.children(this.collectionViewType, props)}
+                {viewtype !== undefined ? this.props.children(viewtype, props) : (null)}
             </div>
         );
     }
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
index cf058090d..40d7b25d3 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
@@ -1,4 +1,4 @@
-import { computed, reaction } from "mobx";
+import { computed, reaction, trace, IReactionDisposer } from "mobx";
 import { observer } from "mobx-react";
 import { Document } from "../../../../fields/Document";
 import { FieldWaiting } from "../../../../fields/Field";
@@ -15,18 +15,19 @@ import React = require("react");
 @observer
 export class CollectionFreeFormLinksView extends React.Component<CollectionViewProps> {
 
-    HackToAvoidReactionFiringUnnecessarily?: Document = undefined;
+    _brushReactionDisposer?: IReactionDisposer;
     componentDidMount() {
-        this.HackToAvoidReactionFiringUnnecessarily = this.props.Document;
-        reaction(() =>
-            DocumentManager.Instance.getAllDocumentViews(this.HackToAvoidReactionFiringUnnecessarily!).
-                map(dv => dv.props.Document.GetNumber(KeyStore.X, 0)),
+        this._brushReactionDisposer = reaction(() => {
+            // trace();
+            return this.props.Document.GetList<Document>(this.props.fieldKey, []).map(doc => doc.GetNumber(KeyStore.X, 0));
+        },
             () => {
-                let views = DocumentManager.Instance.getAllDocumentViews(this.props.Document);
+                console.log("title = " + this.props.Document.Title);
+                let views = this.props.Document.GetList<Document>(this.props.fieldKey, []);
                 for (let i = 0; i < views.length; i++) {
                     for (let j = 0; j < views.length; j++) {
-                        let srcDoc = views[j].props.Document;
-                        let dstDoc = views[i].props.Document;
+                        let srcDoc = views[j];
+                        let dstDoc = views[i];
                         let x1 = srcDoc.GetNumber(KeyStore.X, 0);
                         let x1w = srcDoc.GetNumber(KeyStore.Width, -1);
                         let x2 = dstDoc.GetNumber(KeyStore.X, 0);
@@ -53,7 +54,7 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
                             linkDoc.SetText(KeyStore.LinkDescription, "Brush between " + srcTarg.Title + " and " + dstTarg.Title);
                             linkDoc.SetData(KeyStore.BrushingDocs, [dstTarg, srcTarg], ListField);
 
-                            brushAction = brushAction = (field: ListField<Document>) => {
+                            brushAction = (field: ListField<Document>) => {
                                 if (findBrush(field) === -1) {
                                     console.log("ADD BRUSH " + srcTarg.Title + " " + dstTarg.Title);
                                     (findBrush(field) === -1) && field.Data.push(linkDoc);
@@ -67,6 +68,11 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
                 }
             });
     }
+    componentWillUnmount() {
+        if (this._brushReactionDisposer) {
+            this._brushReactionDisposer();
+        }
+    }
     documentAnchors(view: DocumentView) {
         let equalViews = [view];
         let containerDoc = view.props.Document.GetT(KeyStore.AnnotationOn, Document);
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 98ebbf1b3..6b9f4fdfd 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -315,6 +315,7 @@ export class CollectionFreeFormView extends CollectionSubView {
         const blay = this.backgroundView;
         const olay = this.overlayView;
 
+        console.log("tv = " + this.props.Document.Title);
         return (
             <Measure onResize={(r: any) => runInAction(() => { this._pwidth = r.entry.width; this._pheight = r.entry.height; })}>
                 {({ measureRef }) => (
diff --git a/src/fields/Document.ts b/src/fields/Document.ts
index 60eaf5b51..628fe684c 100644
--- a/src/fields/Document.ts
+++ b/src/fields/Document.ts
@@ -41,14 +41,14 @@ export class Document extends Field {
     @computed
     public get Title(): string {
         let title = this.Get(KeyStore.Title, true);
-        if (title) {
+        if (title || title === FieldWaiting) {
             if (title !== FieldWaiting && title instanceof TextField) {
                 return title.Data;
             }
             else return "-waiting-";
         }
         let parTitle = this.GetT(KeyStore.Title, TextField);
-        if (parTitle) {
+        if (parTitle || parTitle === FieldWaiting) {
             if (parTitle !== FieldWaiting) return parTitle.Data + ".alias";
             else return "-waiting-.alias";
         }
-- 
cgit v1.2.3-70-g09d2


From 9c162a938e861509e2e32e7b63409f037e2da284 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 12 Apr 2019 18:34:17 -0400
Subject: removed log stuff

---
 src/client/Server.ts                                                | 3 ---
 src/client/util/DocumentManager.ts                                  | 6 +-----
 .../collections/collectionFreeForm/CollectionFreeFormLinksView.tsx  | 6 +-----
 .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 1 -
 4 files changed, 2 insertions(+), 14 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/Server.ts b/src/client/Server.ts
index fb5ad1c52..3bbbebe72 100644
--- a/src/client/Server.ts
+++ b/src/client/Server.ts
@@ -123,9 +123,6 @@ export class Server {
                             callback(fieldfromserver);
                         }
                     }
-                    if (!fieldfromserver && callback) {
-                        console.log("Why didn't we get a field?")
-                    }
                 }));
         }
     }
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index b62287de8..3e093c8dc 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -28,11 +28,7 @@ export class DocumentManager {
     }
 
     public getAllDocumentViews(collection: Document) {
-        return this.DocumentViews.filter(dv => {
-            console.log((dv.props.ContainingCollectionView && dv.props.ContainingCollectionView.props.Document ?
-                dv.props.ContainingCollectionView.props.Document.Title : "--") + " = " + collection.Title);
-            return dv.props.ContainingCollectionView && dv.props.ContainingCollectionView.props.Document === collection;
-        });
+        return this.DocumentViews.filter(dv => dv.props.ContainingCollectionView && dv.props.ContainingCollectionView.props.Document === collection);
     }
 
     public getDocumentView(toFind: Document): DocumentView | null {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
index 40d7b25d3..647c83d4d 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
@@ -17,12 +17,8 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
 
     _brushReactionDisposer?: IReactionDisposer;
     componentDidMount() {
-        this._brushReactionDisposer = reaction(() => {
-            // trace();
-            return this.props.Document.GetList<Document>(this.props.fieldKey, []).map(doc => doc.GetNumber(KeyStore.X, 0));
-        },
+        this._brushReactionDisposer = reaction(() => this.props.Document.GetList<Document>(this.props.fieldKey, []).map(doc => doc.GetNumber(KeyStore.X, 0)),
             () => {
-                console.log("title = " + this.props.Document.Title);
                 let views = this.props.Document.GetList<Document>(this.props.fieldKey, []);
                 for (let i = 0; i < views.length; i++) {
                     for (let j = 0; j < views.length; j++) {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 6b9f4fdfd..98ebbf1b3 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -315,7 +315,6 @@ export class CollectionFreeFormView extends CollectionSubView {
         const blay = this.backgroundView;
         const olay = this.overlayView;
 
-        console.log("tv = " + this.props.Document.Title);
         return (
             <Measure onResize={(r: any) => runInAction(() => { this._pwidth = r.entry.width; this._pheight = r.entry.height; })}>
                 {({ measureRef }) => (
-- 
cgit v1.2.3-70-g09d2


From db9ee4f0d710d132e33e48cf6f105fd945941003 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Fri, 12 Apr 2019 21:18:30 -0400
Subject: combined preview cursor with marquee.  moved preview cursor prompt to
 its own file.

---
 src/client/views/DocumentDecorations.scss          |  2 +
 src/client/views/Main.scss                         |  2 +-
 src/client/views/Main.tsx                          | 39 +---------
 src/client/views/PreviewCursor.scss                |  9 +++
 src/client/views/PreviewCursor.tsx                 | 37 ++++++++++
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 33 ++++-----
 .../collections/collectionFreeForm/MarqueeView.tsx | 43 +++++++++--
 .../collectionFreeForm/PreviewCursor.scss          | 27 -------
 .../collectionFreeForm/PreviewCursor.tsx           | 85 ----------------------
 9 files changed, 103 insertions(+), 174 deletions(-)
 create mode 100644 src/client/views/PreviewCursor.scss
 create mode 100644 src/client/views/PreviewCursor.tsx
 delete mode 100644 src/client/views/collections/collectionFreeForm/PreviewCursor.scss
 delete mode 100644 src/client/views/collections/collectionFreeForm/PreviewCursor.tsx

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss
index ce84b6106..c1a949639 100644
--- a/src/client/views/DocumentDecorations.scss
+++ b/src/client/views/DocumentDecorations.scss
@@ -78,6 +78,7 @@
     grid-column-end: 6;
     pointer-events: all;
     text-align: center;
+    cursor: pointer;
 }
 .documentDecorations-minimizeButton {
     background:$alt-accent;
@@ -86,6 +87,7 @@
     grid-column-end: 3;
     pointer-events: all;
     text-align: center;
+    cursor: pointer;
 }
 .documentDecorations-background {
     background: lightblue;
diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss
index f3af26f37..13cadb10d 100644
--- a/src/client/views/Main.scss
+++ b/src/client/views/Main.scss
@@ -184,7 +184,7 @@ button:hover {
         position:absolute;
         top: 0;
         left: 0;
-}
+    }
 }
 #mainContent-div {
     width:100%;
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 80e19c4f5..ed61aa5a7 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -40,44 +40,9 @@ import { DocumentView } from './nodes/DocumentView';
 import { FormattedTextBox } from './nodes/FormattedTextBox';
 import { REPLCommand } from 'repl';
 import { Key } from '../../fields/Key';
-import { truncate } from 'fs';
+import { PreviewCursor } from './PreviewCursor';
 
 
-export interface PromptProps {
-}
-
-@observer
-export class PreviewCursorPrompt extends React.Component<PromptProps> {
-    private _prompt = React.createRef<HTMLDivElement>();
-    //when focus is lost, this will remove the preview cursor
-    @action onBlur = (): void => {
-        PreviewCursorPrompt.Visible = false;
-        PreviewCursorPrompt.hide();
-    }
-
-    @observable static clickPoint = [0, 0];
-    @observable public static Visible = false;
-    @observable public static hide = () => { };
-    @action
-    public static Show(hide: any, x: number, y: number) {
-        this.clickPoint = [x, y];
-        this.hide = hide;
-        setTimeout(action(() => this.Visible = true), (1));
-    }
-    render() {
-        if (!PreviewCursorPrompt.clickPoint) {
-            return (null);
-        }
-        if (PreviewCursorPrompt.Visible && this._prompt.current) {
-            this._prompt.current.focus();
-        }
-        let p = PreviewCursorPrompt.clickPoint;
-        return <div className="previewCursor" id="previewCursor" onBlur={this.onBlur} tabIndex={0} ref={this._prompt}
-            style={{ transform: `translate(${p[0]}px, ${p[1]}px)`, opacity: PreviewCursorPrompt.Visible ? 1 : 0 }}>
-            I
-        </div >;
-    }
-}
 @observer
 export class Main extends React.Component {
     // dummy initializations keep the compiler happy
@@ -429,7 +394,7 @@ export class Main extends React.Component {
                         {({ measureRef }) =>
                             <div ref={measureRef} id="mainContent-div">
                                 {this.mainContent}
-                                <PreviewCursorPrompt />
+                                <PreviewCursor />
                             </div>
                         }
                     </Measure>
diff --git a/src/client/views/PreviewCursor.scss b/src/client/views/PreviewCursor.scss
new file mode 100644
index 000000000..20f9b9a49
--- /dev/null
+++ b/src/client/views/PreviewCursor.scss
@@ -0,0 +1,9 @@
+
+.previewCursor {
+    color: black;
+    position: absolute;
+    transform-origin: left top;
+    top: 0;
+    left:0;
+    pointer-events: none;
+}
\ No newline at end of file
diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx
new file mode 100644
index 000000000..ff8434681
--- /dev/null
+++ b/src/client/views/PreviewCursor.tsx
@@ -0,0 +1,37 @@
+import { action, observable } from 'mobx';
+import { observer } from 'mobx-react';
+import "normalize.css";
+import * as React from 'react';
+import "./PreviewCursor.scss";
+
+@observer
+export class PreviewCursor extends React.Component<{}> {
+    private _prompt = React.createRef<HTMLDivElement>();
+    //when focus is lost, this will remove the preview cursor
+    @action onBlur = (): void => {
+        PreviewCursor.Visible = false;
+        PreviewCursor.hide();
+    }
+
+    @observable static clickPoint = [0, 0];
+    @observable public static Visible = false;
+    @observable public static hide = () => { };
+    @action
+    public static Show(hide: any, x: number, y: number) {
+        this.clickPoint = [x, y];
+        this.hide = hide;
+        setTimeout(action(() => this.Visible = true), (1));
+    }
+    render() {
+        if (!PreviewCursor.clickPoint) {
+            return (null);
+        }
+        if (PreviewCursor.Visible && this._prompt.current) {
+            this._prompt.current.focus();
+        }
+        return <div className="previewCursor" id="previewCursor" onBlur={this.onBlur} tabIndex={0} ref={this._prompt}
+            style={{ transform: `translate(${PreviewCursor.clickPoint[0]}px, ${PreviewCursor.clickPoint[1]}px)`, opacity: PreviewCursor.Visible ? 1 : 0 }}>
+            I
+        </div >;
+    }
+}
\ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 98ebbf1b3..e19dc98fa 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -23,7 +23,6 @@ import { CollectionFreeFormLinksView } from "./CollectionFreeFormLinksView";
 import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCursors";
 import "./CollectionFreeFormView.scss";
 import { MarqueeView } from "./MarqueeView";
-import { PreviewCursor } from "./PreviewCursor";
 import React = require("react");
 import v5 = require("uuid/v5");
 
@@ -311,9 +310,9 @@ export class CollectionFreeFormView extends CollectionSubView {
         const [dx, dy] = [this.centeringShiftX, this.centeringShiftY];
         const panx: number = -this.props.Document.GetNumber(KeyStore.PanX, 0);
         const pany: number = -this.props.Document.GetNumber(KeyStore.PanY, 0);
-        const zoom: number = this.zoomScaling;
-        const blay = this.backgroundView;
-        const olay = this.overlayView;
+        const zoom: number = this.zoomScaling;// needs to be a variable outside of the <Measure> otherwise, reactions won't fire
+        const backgroundView = this.backgroundView; // needs to be a variable outside of the <Measure> otherwise, reactions won't fire
+        const overlayView = this.overlayView;// needs to be a variable outside of the <Measure> otherwise, reactions won't fire
 
         return (
             <Measure onResize={(r: any) => runInAction(() => { this._pwidth = r.entry.width; this._pheight = r.entry.height; })}>
@@ -323,21 +322,19 @@ export class CollectionFreeFormView extends CollectionSubView {
                             onPointerDown={this.onPointerDown} onPointerMove={(e) => super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY))}
                             onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} onWheel={this.onPointerWheel} ref={this.createDropTarget}>
                             <MarqueeView container={this} activeDocuments={this.getActiveDocuments} selectDocuments={this.selectDocuments}
-                                addDocument={this.addDocument} removeDocument={this.props.removeDocument}
+                                addDocument={this.addDocument} removeDocument={this.props.removeDocument} addLiveTextDocument={this.addLiveTextBox}
                                 getContainerTransform={this.getContainerTransform} getTransform={this.getTransform}>
-                                <PreviewCursor container={this} addLiveTextDocument={this.addLiveTextBox} getTransform={this.getTransform} >
-                                    <div className="collectionfreeformview" ref={this._canvasRef}
-                                        style={{ transform: `translate(${dx}px, ${dy}px) scale(${zoom}, ${zoom}) translate(${panx}px, ${pany}px)` }}>
-                                        {blay}
-                                        <CollectionFreeFormLinksView {...this.props}>
-                                            <InkingCanvas getScreenTransform={this.getTransform} Document={this.props.Document} >
-                                                {this.childViews}
-                                            </InkingCanvas>
-                                        </CollectionFreeFormLinksView>
-                                        <CollectionFreeFormRemoteCursors {...this.props} />
-                                    </div>
-                                    {olay}
-                                </PreviewCursor>
+                                <div className="collectionfreeformview" ref={this._canvasRef}
+                                    style={{ transform: `translate(${dx}px, ${dy}px) scale(${zoom}, ${zoom}) translate(${panx}px, ${pany}px)` }}>
+                                    {backgroundView}
+                                    <CollectionFreeFormLinksView {...this.props}>
+                                        <InkingCanvas getScreenTransform={this.getTransform} Document={this.props.Document} >
+                                            {this.childViews}
+                                        </InkingCanvas>
+                                    </CollectionFreeFormLinksView>
+                                    <CollectionFreeFormRemoteCursors {...this.props} />
+                                </div>
+                                {overlayView}
                             </MarqueeView>
                         </div>
                     </div>)}
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 1e6faafb3..9c0d75c22 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -1,4 +1,4 @@
-import { action, computed, observable, trace } from "mobx";
+import { action, computed, observable } from "mobx";
 import { observer } from "mobx-react";
 import { Document } from "../../../../fields/Document";
 import { FieldWaiting } from "../../../../fields/Field";
@@ -8,9 +8,9 @@ import { Documents } from "../../../documents/Documents";
 import { SelectionManager } from "../../../util/SelectionManager";
 import { Transform } from "../../../util/Transform";
 import { InkingCanvas } from "../../InkingCanvas";
+import { PreviewCursor } from "../../PreviewCursor";
 import { CollectionFreeFormView } from "./CollectionFreeFormView";
 import "./MarqueeView.scss";
-import { PreviewCursor } from "./PreviewCursor";
 import React = require("react");
 
 interface MarqueeViewProps {
@@ -21,6 +21,7 @@ interface MarqueeViewProps {
     activeDocuments: () => Document[];
     selectDocuments: (docs: Document[]) => void;
     removeDocument: (doc: Document) => boolean;
+    addLiveTextDocument: (doc: Document) => void;
 }
 
 @observer
@@ -32,6 +33,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
     @observable _downY: number = 0;
     @observable _used: boolean = false;
     @observable _visible: boolean = false;
+    _showOnUp: boolean = false;
     static DRAG_THRESHOLD = 4;
 
     @action
@@ -46,12 +48,32 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
         this._visible = false;
     }
 
+    @action
+    onKeyPress = (e: KeyboardEvent) => {
+        // Mixing events between React and Native is finicky.  In FormattedTextBox, we set the
+        // DASHFormattedTextBoxHandled flag when a text box consumes a key press so that we can ignore
+        // the keyPress here.
+        //if not these keys, make a textbox if preview cursor is active!
+        if (!e.ctrlKey && !e.altKey && !e.defaultPrevented && !(e as any).DASHFormattedTextBoxHandled) {
+            //make textbox and add it to this collection
+            let [x, y] = this.props.getTransform().transformPoint(this._downX, this._downY);
+            let newBox = Documents.TextDocument({ width: 200, height: 100, x: x, y: y, title: "typed text" });
+            this.props.addLiveTextDocument(newBox);
+            PreviewCursor.Visible = false;
+            e.stopPropagation();
+        }
+    }
+    hideCursor = () => {
+        document.removeEventListener("keypress", this.onKeyPress, false);
+    }
     @action
     onPointerDown = (e: React.PointerEvent): void => {
         if (e.buttons === 1 && !e.altKey && !e.metaKey && this.props.container.props.active()) {
             this._downX = this._lastX = e.pageX;
             this._downY = this._lastY = e.pageY;
             this._used = false;
+            this._showOnUp = true;
+            document.removeEventListener("keypress", this.onKeyPress, false);
             document.addEventListener("pointermove", this.onPointerMove, true);
             document.addEventListener("pointerup", this.onPointerUp, true);
             document.addEventListener("keydown", this.marqueeCommand, true);
@@ -63,6 +85,10 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
         this._lastX = e.pageX;
         this._lastY = e.pageY;
         if (!e.cancelBubble) {
+            if (Math.abs(this._downX - e.clientX) > 4 || Math.abs(this._downY - e.clientY) > 4) {
+                this._showOnUp = false;
+                PreviewCursor.Visible = false;
+            }
             if (!this._used && e.buttons === 1 && !e.altKey && !e.metaKey &&
                 (Math.abs(this._lastX - this._downX) > MarqueeView.DRAG_THRESHOLD || Math.abs(this._lastY - this._downY) > MarqueeView.DRAG_THRESHOLD)) {
                 this._visible = true;
@@ -76,11 +102,16 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
     onPointerUp = (e: PointerEvent): void => {
         this.cleanupInteractions(true);
         this._visible = false;
-        let mselect = this.marqueeSelect();
-        if (!e.shiftKey) {
-            SelectionManager.DeselectAll(mselect.length ? undefined : this.props.container.props.Document);
+        if (this._showOnUp) {
+            PreviewCursor.Show(this.hideCursor, this._downX, this._downY);
+            document.addEventListener("keypress", this.onKeyPress, false);
+        } else {
+            let mselect = this.marqueeSelect();
+            if (!e.shiftKey) {
+                SelectionManager.DeselectAll(mselect.length ? undefined : this.props.container.props.Document);
+            }
+            this.props.selectDocuments(mselect.length ? mselect : [this.props.container.props.Document]);
         }
-        this.props.selectDocuments(mselect.length ? mselect : [this.props.container.props.Document]);
     }
 
     intersectRect(r1: { left: number, top: number, width: number, height: number },
diff --git a/src/client/views/collections/collectionFreeForm/PreviewCursor.scss b/src/client/views/collections/collectionFreeForm/PreviewCursor.scss
deleted file mode 100644
index 7a67c29bf..000000000
--- a/src/client/views/collections/collectionFreeForm/PreviewCursor.scss
+++ /dev/null
@@ -1,27 +0,0 @@
-
-.previewCursor {
-    color: black;
-    position: absolute;
-    transform-origin: left top;
-    top: 0;
-    left:0;
-    pointer-events: none;
-}
-.previewCursorView {
-    top: 0;
-    left:0;
-    position: absolute;
-    width:100%;
-    height:100%;
-}
-
-//this is an animation for the blinking cursor!
-// @keyframes blink {
-// 	0% {opacity: 0}
-// 	49%{opacity: 0}
-// 	50% {opacity: 1}
-// }
-
-// #previewCursor {
-//      animation: blink 1s infinite;
-// }
\ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx b/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx
deleted file mode 100644
index 64da8ecc6..000000000
--- a/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx
+++ /dev/null
@@ -1,85 +0,0 @@
-import { action, observable, trace, computed, reaction } from "mobx";
-import { observer } from "mobx-react";
-import { Document } from "../../../../fields/Document";
-import { Documents } from "../../../documents/Documents";
-import { Transform } from "../../../util/Transform";
-import { CollectionFreeFormView } from "./CollectionFreeFormView";
-import "./PreviewCursor.scss";
-import React = require("react");
-import { Main, PreviewCursorPrompt } from "../../Main";
-
-
-export interface PreviewCursorProps {
-    getTransform: () => Transform;
-    container: CollectionFreeFormView;
-    addLiveTextDocument: (doc: Document) => void;
-}
-
-@observer
-export class PreviewCursor extends React.Component<PreviewCursorProps>  {
-    @observable _lastX: number = 0;
-    @observable _lastY: number = 0;
-    @observable public DownX: number = 0;
-    @observable public DownY: number = 0;
-    _showOnUp: boolean = false;
-
-    @action
-    cleanupInteractions = () => {
-        document.removeEventListener("pointerup", this.onPointerUp, true);
-        document.removeEventListener("pointermove", this.onPointerMove, true);
-    }
-
-    @action
-    onPointerDown = (e: React.PointerEvent) => {
-        if (e.button === 0 && this.props.container.props.active()) {
-            document.removeEventListener("keypress", this.onKeyPress, false);
-            this._showOnUp = true;
-            this.DownX = e.pageX;
-            this.DownY = e.pageY;
-            document.addEventListener("pointerup", this.onPointerUp, true);
-            document.addEventListener("pointermove", this.onPointerMove, true);
-        }
-    }
-    @action
-    onPointerMove = (e: PointerEvent): void => {
-        if (Math.abs(this.DownX - e.clientX) > 4 || Math.abs(this.DownY - e.clientY) > 4) {
-            this._showOnUp = false;
-            PreviewCursorPrompt.Visible = false;
-        }
-    }
-
-    onPointerUp = (e: PointerEvent): void => {
-        if (this._showOnUp) {
-            PreviewCursorPrompt.Show(this.hideCursor, this.DownX, this.DownY);
-            document.addEventListener("keypress", this.onKeyPress, false);
-        }
-        this.cleanupInteractions();
-    }
-
-    @action
-    onKeyPress = (e: KeyboardEvent) => {
-        // Mixing events between React and Native is finicky.  In FormattedTextBox, we set the
-        // DASHFormattedTextBoxHandled flag when a text box consumes a key press so that we can ignore
-        // the keyPress here.
-        //if not these keys, make a textbox if preview cursor is active!
-        if (!e.ctrlKey && !e.altKey && !e.defaultPrevented && !(e as any).DASHFormattedTextBoxHandled) {
-            //make textbox and add it to this collection
-            let [x, y] = this.props.getTransform().transformPoint(this.DownX, this.DownY);
-            let newBox = Documents.TextDocument({ width: 200, height: 100, x: x, y: y, title: "typed text" });
-            this.props.addLiveTextDocument(newBox);
-            PreviewCursorPrompt.Visible = false;
-            e.stopPropagation();
-        }
-    }
-
-    hideCursor = () => {
-        document.removeEventListener("keypress", this.onKeyPress, false);
-    }
-    render() {
-        return (
-            <div className="previewCursorView" onPointerDown={this.onPointerDown}>
-                {this.props.children}
-            </div>
-        );
-    }
-}
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2

