From 0c9d3637bde9825efe93c55afce8270b2a2e979c Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 12 Apr 2019 11:18:23 -0400
Subject: cleaned up and enabled linking to a top-level document

---
 src/client/views/Main.tsx | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

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

diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index c4c4a6bf9..60f7098fb 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -28,7 +28,7 @@ import '../northstar/model/ModelExtensions';
 import { HistogramOperation } from '../northstar/operations/HistogramOperation';
 import '../northstar/utils/Extensions';
 import { Server } from '../Server';
-import { setupDrag, DragManager } from '../util/DragManager';
+import { SetupDrag, DragManager } from '../util/DragManager';
 import { Transform } from '../util/Transform';
 import { UndoManager } from '../util/UndoManager';
 import { CollectionDockingView } from './collections/CollectionDockingView';
@@ -344,7 +344,7 @@ export class Main extends React.Component {
                 <ul id="add-options-list">
                     {btns.map(btn =>
                         <li key={btn[1]} ><div ref={btn[0]}>
-                            <button className="round-button add-button" title={btn[2]} onPointerDown={setupDrag(btn[0], btn[3])}>
+                            <button className="round-button add-button" title={btn[2]} onPointerDown={SetupDrag(btn[0], btn[3])}>
                                 <FontAwesomeIcon icon={btn[1]} size="sm" />
                             </button>
                         </div></li>)}
-- 
cgit v1.2.3-70-g09d2


From 0afa18bfc219c597ad55a52ffc5a2086c3d110d2 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 12 Apr 2019 14:15:05 -0400
Subject: changed signatures of focus functions.

---
 src/Utils.ts                                       |  3 +++
 src/client/views/DocumentDecorations.tsx           |  2 +-
 src/client/views/Main.tsx                          |  8 ++++----
 .../views/collections/CollectionDockingView.tsx    |  4 ++--
 .../views/collections/CollectionSchemaView.tsx     |  8 +++-----
 src/client/views/nodes/FieldView.tsx               |  4 ++--
 src/client/views/nodes/KeyValuePair.tsx            |  4 ++--
 src/client/views/nodes/LinkBox.tsx                 | 24 ++++++++--------------
 8 files changed, 25 insertions(+), 32 deletions(-)

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

diff --git a/src/Utils.ts b/src/Utils.ts
index b0e66787e..ae194bcc7 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -2,6 +2,7 @@ import v4 = require('uuid/v4');
 import v5 = require("uuid/v5");
 import { Socket } from 'socket.io';
 import { Message, Types } from './server/Message';
+import { Document } from './fields/Document';
 
 export class Utils {
 
@@ -96,4 +97,6 @@ export function returnFalse() {
 
 export function emptyFunction() { }
 
+export function emptyDocFunction(doc: Document) { console.log("focus " + doc.Title) }
+
 export type Without<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
\ No newline at end of file
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 15ac0a8fc..c172e870e 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -244,7 +244,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
     }
 
     onLinkButtonMoved = async (e: PointerEvent) => {
-        if (this._linkButton.current !== null) {
+        if (this._linkButton.current !== null && (e.movementX > 1 || e.movementY > 1)) {
             document.removeEventListener("pointermove", this.onLinkButtonMoved);
             document.removeEventListener("pointerup", this.onLinkButtonUp);
 
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 60f7098fb..419de6fc1 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -15,7 +15,7 @@ import { ListField } from '../../fields/ListField';
 import { WorkspacesMenu } from '../../server/authentication/controllers/WorkspacesMenu';
 import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils';
 import { MessageStore } from '../../server/Message';
-import { Utils, returnTrue, emptyFunction } from '../../Utils';
+import { Utils, returnTrue, emptyFunction, emptyDocFunction } from '../../Utils';
 import * as rp from 'request-promise';
 import { RouteStore } from '../../server/RouteStore';
 import { ServerUtils } from '../../server/ServerUtil';
@@ -202,7 +202,6 @@ export class Main extends React.Component {
 
     pwidthFunc = () => this.pwidth;
     pheightFunc = () => this.pheight;
-    focusDocument = (doc: Document) => { };
     noScaling = () => 1;
 
     @observable _textDoc?: Document = undefined;
@@ -280,7 +279,8 @@ export class Main extends React.Component {
             s[0] = Math.sqrt((s[0] - t[0]) * (s[0] - t[0]) + (s[1] - t[1]) * (s[1] - t[1]));
             return <div className="mainDiv-textInput" style={{ pointerEvents: "none", transform: `translate(${x}px, ${y}px) scale(${1 / s[0]},${1 / s[0]})`, width: "auto", height: "auto" }} >
                 <div className="mainDiv-textInput" onPointerDown={this.textBoxDown} ref={this._textProxyDiv} onScroll={this.textScroll} style={{ pointerEvents: "none", transform: `scale(${1}, ${1})`, width: `${w * s[0]}px`, height: `${h * s[0]}px` }}>
-                    <FormattedTextBox fieldKey={this._textFieldKey!} isOverlay={true} Document={this._textDoc} isSelected={returnTrue} select={emptyFunction} isTopMost={true} selectOnLoad={true} onActiveChanged={emptyFunction} active={returnTrue} ScreenToLocalTransform={() => this._textXf} focus={(doc) => { }} />
+                    <FormattedTextBox fieldKey={this._textFieldKey!} isOverlay={true} Document={this._textDoc} isSelected={returnTrue} select={emptyFunction} isTopMost={true}
+                        selectOnLoad={true} onActiveChanged={emptyFunction} active={returnTrue} ScreenToLocalTransform={() => this._textXf} focus={emptyDocFunction} />
                 </div>
             </ div>;
         }
@@ -299,7 +299,7 @@ export class Main extends React.Component {
                 PanelHeight={this.pheightFunc}
                 isTopMost={true}
                 selectOnLoad={false}
-                focus={this.focusDocument}
+                focus={emptyDocFunction}
                 parentActive={returnTrue}
                 onActiveChanged={emptyFunction}
                 ContainingCollectionView={undefined} />;
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index e54c25474..77ffb4157 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -8,7 +8,7 @@ import { Document } from "../../../fields/Document";
 import { KeyStore } from "../../../fields/KeyStore";
 import Measure from "react-measure";
 import { FieldId, Opt, Field, FieldWaiting } from "../../../fields/Field";
-import { Utils, returnTrue, emptyFunction } from "../../../Utils";
+import { Utils, returnTrue, emptyFunction, emptyDocFunction } from "../../../Utils";
 import { Server } from "../../Server";
 import { undoBatch } from "../../util/UndoManager";
 import { DocumentView } from "../nodes/DocumentView";
@@ -350,7 +350,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
                     selectOnLoad={false}
                     parentActive={returnTrue}
                     onActiveChanged={emptyFunction}
-                    focus={(doc: Document) => { }}
+                    focus={emptyDocFunction}
                     ContainingCollectionView={undefined} />
             </div>;
 
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index f53b2a76e..4cf187963 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -26,7 +26,7 @@ import { CollectionView } from "./CollectionView";
 import { CollectionSubView } from "./CollectionSubView";
 import { TextField } from "../../../fields/TextField";
 import * as globalCssVariables from "../../views/globalCssVariables.scss";
-import { emptyFunction, returnFalse } from "../../../Utils";
+import { emptyFunction, returnFalse, emptyDocFunction } from "../../../Utils";
 
 
 // bcz: need to add drag and drop of rows and columns.  This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657
@@ -82,7 +82,7 @@ export class CollectionSchemaView extends CollectionSubView {
             isTopMost: false,
             selectOnLoad: false,
             ScreenToLocalTransform: Transform.Identity,
-            focus: emptyFunction,
+            focus: emptyDocFunction,
             active: returnFalse,
             onActiveChanged: emptyFunction,
         };
@@ -253,8 +253,6 @@ export class CollectionSchemaView extends CollectionSubView {
     getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH - this._dividerX, - this.borderWidth).scale(1 / this._contentScaling);
     getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH - this._dividerX - this._tableWidth, - this.borderWidth).scale(1 / this._contentScaling);
 
-    focusDocument = (doc: Document) => { };
-
     onPointerDown = (e: React.PointerEvent): void => {
         if (e.button === 1 && this.props.isSelected() && !e.altKey && !e.ctrlKey && !e.metaKey) {
             e.stopPropagation();
@@ -317,7 +315,7 @@ export class CollectionSchemaView extends CollectionSubView {
                                 PanelWidth={this.getPanelWidth}
                                 PanelHeight={this.getPanelHeight}
                                 ContainingCollectionView={undefined}
-                                focus={this.focusDocument}
+                                focus={emptyDocFunction}
                                 parentActive={this.props.active}
                                 onActiveChanged={this.props.onActiveChanged} /> : null}
                         <input value={this.previewScript} onChange={this.onPreviewScriptChange}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 40b44aae5..0037d7b28 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -19,7 +19,7 @@ import { ListField } from "../../../fields/ListField";
 import { DocumentContentsView } from "./DocumentContentsView";
 import { Transform } from "../../util/Transform";
 import { KeyStore } from "../../../fields/KeyStore";
-import { returnFalse, emptyFunction } from "../../../Utils";
+import { returnFalse, emptyDocFunction } from "../../../Utils";
 
 
 //
@@ -85,7 +85,7 @@ export class FieldView extends React.Component<FieldViewProps> {
                     PanelHeight={() => 100}
                     isTopMost={true} //TODO Why is this top most?
                     selectOnLoad={false}
-                    focus={emptyFunction}
+                    focus={emptyDocFunction}
                     isSelected={returnFalse}
                     select={returnFalse}
                     layoutKey={KeyStore.Layout}
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index a1050dc6e..7f43d8fdf 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -12,7 +12,7 @@ import { Server } from "../../Server";
 import { EditableView } from "../EditableView";
 import { CompileScript, ToField } from "../../util/Scripting";
 import { Transform } from '../../util/Transform';
-import { returnFalse, emptyFunction } from '../../../Utils';
+import { returnFalse, emptyFunction, emptyDocFunction } from '../../../Utils';
 
 // Represents one row in a key value plane
 
@@ -54,7 +54,7 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
             active: returnFalse,
             onActiveChanged: emptyFunction,
             ScreenToLocalTransform: Transform.Identity,
-            focus: emptyFunction,
+            focus: emptyDocFunction,
         };
         let contents = (
             <FieldView {...props} />
diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx
index b016a3d48..1c0e316e8 100644
--- a/src/client/views/nodes/LinkBox.tsx
+++ b/src/client/views/nodes/LinkBox.tsx
@@ -1,24 +1,16 @@
-import { observable, computed, action } from "mobx";
-import React = require("react");
-import { SelectionManager } from "../../util/SelectionManager";
+import { library } from '@fortawesome/fontawesome-svg-core';
+import { faEdit, faEye, faTimes } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { observer } from "mobx-react";
-import './LinkBox.scss';
-import { KeyStore } from '../../../fields/KeyStore';
-import { props } from "bluebird";
-import { DocumentView } from "./DocumentView";
 import { Document } from "../../../fields/Document";
+import { KeyStore } from '../../../fields/KeyStore';
 import { ListField } from "../../../fields/ListField";
+import { NumberField } from "../../../fields/NumberField";
 import { DocumentManager } from "../../util/DocumentManager";
-import { LinkEditor } from "./LinkEditor";
-import { CollectionDockingView } from "../collections/CollectionDockingView";
-import { library } from '@fortawesome/fontawesome-svg-core';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { faEye } from '@fortawesome/free-solid-svg-icons';
-import { faEdit } from '@fortawesome/free-solid-svg-icons';
-import { faTimes } from '@fortawesome/free-solid-svg-icons';
 import { undoBatch } from "../../util/UndoManager";
-import { FieldWaiting } from "../../../fields/Field";
-import { NumberField } from "../../../fields/NumberField";
+import { CollectionDockingView } from "../collections/CollectionDockingView";
+import './LinkBox.scss';
+import React = require("react");
 
 
 library.add(faEye);
-- 
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/Main.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 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/Main.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 e3caa89d36c501c16acbc56900546d8a4522584a Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Fri, 12 Apr 2019 20:44:43 -0400
Subject: fixed lint warnings.

---
 src/Utils.ts                                           | 2 +-
 src/client/views/Main.tsx                              | 7 ++++---
 src/client/views/collections/CollectionDockingView.tsx | 3 ++-
 3 files changed, 7 insertions(+), 5 deletions(-)

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

diff --git a/src/Utils.ts b/src/Utils.ts
index ae194bcc7..ff55a2e4e 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -97,6 +97,6 @@ export function returnFalse() {
 
 export function emptyFunction() { }
 
-export function emptyDocFunction(doc: Document) { console.log("focus " + doc.Title) }
+export function emptyDocFunction(doc: Document) { console.log("focus " + doc.Title); }
 
 export type Without<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
\ No newline at end of file
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 3cf8f7c26..80e19c4f5 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -65,8 +65,9 @@ export class PreviewCursorPrompt extends React.Component<PromptProps> {
         setTimeout(action(() => this.Visible = true), (1));
     }
     render() {
-        if (!PreviewCursorPrompt.clickPoint)
+        if (!PreviewCursorPrompt.clickPoint) {
             return (null);
+        }
         if (PreviewCursorPrompt.Visible && this._prompt.current) {
             this._prompt.current.focus();
         }
@@ -469,8 +470,8 @@ export class Main extends React.Component {
                 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/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 77ffb4157..eb1cd1c09 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -276,8 +276,9 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
         }
         tab.closeElement.off('click') //unbind the current click handler
             .click(function () {
-                if (tab.reactionDisposer)
+                if (tab.reactionDisposer) {
                     tab.reactionDisposer();
+                }
                 tab.contentItem.remove();
             });
     }
-- 
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/Main.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

