From 5a4be44ac6b9fdc10a5464623a02891bc2cc4444 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sat, 20 Apr 2019 19:23:27 -0400
Subject: fixed input text scaling

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

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

diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index ae05c2dad..29ed2da13 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -115,7 +115,7 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
             );
         } else {
             this._proxyReactionDisposer = reaction(() => this.props.isSelected(),
-                () => this.props.isSelected() && MainOverlayTextBox.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform()));
+                () => this.props.isSelected() && MainOverlayTextBox.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform));
         }
 
 
@@ -186,7 +186,9 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
 
     onFocused = (e: React.FocusEvent): void => {
         if (!this.props.isOverlay) {
-            MainOverlayTextBox.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform());
+            if (MainOverlayTextBox.Instance.TextDoc != this.props.Document) {
+                MainOverlayTextBox.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform);
+            }
         } else {
             if (this._ref.current) {
                 this._ref.current.scrollTop = MainOverlayTextBox.Instance.TextScroll;
-- 
cgit v1.2.3-70-g09d2


From 27b514747188f12e0b0eeeb124576c556316923d Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Mon, 22 Apr 2019 22:57:18 -0400
Subject: Changes

---
 src/client/util/UndoManager.ts              |   4 +-
 src/client/views/nodes/AudioBox.tsx         |  27 +---
 src/client/views/nodes/DocumentView.tsx     | 190 ++++++++++++++--------------
 src/client/views/nodes/FormattedTextBox.tsx |  28 ++--
 src/new_fields/Doc.ts                       |  11 +-
 src/new_fields/Schema.ts                    |  13 +-
 src/new_fields/Types.ts                     |  12 +-
 7 files changed, 133 insertions(+), 152 deletions(-)

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

diff --git a/src/client/util/UndoManager.ts b/src/client/util/UndoManager.ts
index 27aed4bac..f91ca2e06 100644
--- a/src/client/util/UndoManager.ts
+++ b/src/client/util/UndoManager.ts
@@ -1,4 +1,4 @@
-import { observable, action } from "mobx";
+import { observable, action, runInAction } from "mobx";
 import 'source-map-support/register';
 import { Without } from "../../Utils";
 import { string } from "prop-types";
@@ -143,7 +143,7 @@ export namespace UndoManager {
     export function RunInBatch(fn: () => void, batchName: string) {
         let batch = StartBatch(batchName);
         try {
-            fn();
+            runInAction(fn);
         } finally {
             batch.end();
         }
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index 1493ff25b..be12dced3 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -1,36 +1,19 @@
 import React = require("react");
 import { FieldViewProps, FieldView } from './FieldView';
-import { FieldWaiting } from '../../../fields/Field';
 import { observer } from "mobx-react";
-import { ContextMenu } from "../../views/ContextMenu";
-import { observable, action } from 'mobx';
-import { KeyStore } from '../../../fields/KeyStore';
-import { AudioField } from "../../../fields/AudioField";
 import "./AudioBox.scss";
-import { NumberField } from "../../../fields/NumberField";
+import { Cast } from "../../../new_fields/Types";
+import { AudioField } from "../../../new_fields/URLField";
 
+const defaultField: AudioField = new AudioField(new URL("http://techslides.com/demos/samples/sample.mp3"));
 @observer
 export class AudioBox extends React.Component<FieldViewProps> {
 
     public static LayoutString() { return FieldView.LayoutString(AudioBox); }
 
-    constructor(props: FieldViewProps) {
-        super(props);
-    }
-
-
-
-    componentDidMount() {
-    }
-
-    componentWillUnmount() {
-    }
-
-
     render() {
-        let field = this.props.Document.Get(this.props.fieldKey);
-        let path = field === FieldWaiting ? "http://techslides.com/demos/samples/sample.mp3" :
-            field instanceof AudioField ? field.Data.href : "http://techslides.com/demos/samples/sample.mp3";
+        let field = Cast(this.props.Document[this.props.fieldKey], AudioField, defaultField);
+        let path = field.url.href;
 
         return (
             <div>
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index c0afc192e..e00f56d53 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -18,9 +18,20 @@ import "./DocumentView.scss";
 import React = require("react");
 import { Field, Opt, Doc, Id } from "../../../new_fields/Doc";
 import { DocComponent } from "../DocComponent";
-import { createSchema, makeInterface } from "../../../new_fields/Schema";
-import { FieldValue } from "../../../new_fields/Types";
+import { createSchema, makeInterface, listSpec } from "../../../new_fields/Schema";
+import { FieldValue, Cast, PromiseValue } from "../../../new_fields/Types";
+import { List } from "../../../new_fields/List";
+
+const linkSchema = createSchema({
+    title: "string",
+    linkDescription: "string",
+    linkTags: "string",
+    linkedTo: Doc,
+    linkedFrom: Doc
+});
 
+type LinkDoc = makeInterface<[typeof linkSchema]>;
+const LinkDoc = makeInterface(linkSchema);
 
 export interface DocumentViewProps {
     ContainingCollectionView: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
@@ -157,16 +168,14 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         e.stopPropagation();
         if (!SelectionManager.IsSelected(this) && e.button !== 2) {
             if (Math.abs(e.clientX - this._downX) < 4 && Math.abs(e.clientY - this._downY) < 4) {
-                if (this.props.Document.Get(KeyStore.MaximizedDoc) instanceof Document) {
-                    this.props.Document.GetAsync(KeyStore.MaximizedDoc, maxdoc => {
-                        if (maxdoc instanceof Document) {
-                            this.props.addDocument && this.props.addDocument(maxdoc, false);
-                            this.toggleMinimize(maxdoc, this.props.Document);
-                        }
-                    });
-                } else {
-                    SelectionManager.SelectDoc(this, e.ctrlKey);
-                }
+                PromiseValue(Cast(this.props.Document.maximizedDoc, Doc)).then(maxdoc => {
+                    if (maxdoc instanceof Doc) {
+                        this.props.addDocument && this.props.addDocument(maxdoc, false);
+                        this.toggleMinimize(maxdoc, this.props.Document);
+                    } else {
+                        SelectionManager.SelectDoc(this, e.ctrlKey);
+                    }
+                });
             }
         }
     }
@@ -184,7 +193,10 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         }
     }
     fullScreenClicked = (e: React.MouseEvent): void => {
-        CollectionDockingView.Instance.OpenFullScreen(Doc.MakeDelegate(this.Document.prototype));
+        const doc = Doc.MakeDelegate(FieldValue(this.Document.proto));
+        if (doc) {
+            CollectionDockingView.Instance.OpenFullScreen(doc);
+        }
         ContextMenu.Instance.clearItems();
         ContextMenu.Instance.addItem({ description: "Close Full Screen", event: this.closeFullScreenClicked });
         ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15);
@@ -197,39 +209,39 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15);
     }
 
-    @action createIcon = (layoutString: string): Document => {
-        let iconDoc = Documents.IconDocument(layoutString);
-        iconDoc.SetBoolean(KeyStore.IsMinimized, false);
-        iconDoc.SetNumber(KeyStore.NativeWidth, 0);
-        iconDoc.SetNumber(KeyStore.NativeHeight, 0);
-        iconDoc.Set(KeyStore.Prototype, this.props.Document);
-        iconDoc.Set(KeyStore.MaximizedDoc, this.props.Document);
-        this.props.Document.Set(KeyStore.MinimizedDoc, iconDoc);
+    @action createIcon = (layoutString: string): Doc => {
+        let iconDoc: Doc = Documents.IconDocument(layoutString);
+        iconDoc.isMinimized = false;
+        iconDoc.nativeWidth = 0;
+        iconDoc.nativeHeight = 0;
+        iconDoc.proto = this.props.Document;
+        iconDoc.maximizedDoc = this.props.Document;
+        this.Document.minimizedDoc = iconDoc;
         this.props.addDocument && this.props.addDocument(iconDoc, false);
         return iconDoc;
     }
 
-    animateTransition(icon: number[], targ: number[], width: number, height: number, stime: number, target: Document, maximizing: boolean) {
+    animateTransition(icon: number[], targ: number[], width: number, height: number, stime: number, target: Doc, maximizing: boolean) {
         setTimeout(() => {
             let now = Date.now();
             let progress = Math.min(1, (now - stime) / 200);
             let pval = maximizing ?
                 [icon[0] + (targ[0] - icon[0]) * progress, icon[1] + (targ[1] - icon[1]) * progress] :
                 [targ[0] + (icon[0] - targ[0]) * progress, targ[1] + (icon[1] - targ[1]) * progress];
-            target.SetNumber(KeyStore.Width, maximizing ? 25 + (width - 25) * progress : width + (25 - width) * progress);
-            target.SetNumber(KeyStore.Height, maximizing ? 25 + (height - 25) * progress : height + (25 - height) * progress);
-            target.SetNumber(KeyStore.X, pval[0]);
-            target.SetNumber(KeyStore.Y, pval[1]);
+            target.width = maximizing ? 25 + (width - 25) * progress : width + (25 - width) * progress;
+            target.height = maximizing ? 25 + (height - 25) * progress : height + (25 - height) * progress;
+            target.x = pval[0];
+            target.y = pval[1];
             if (now < stime + 200) {
                 this.animateTransition(icon, targ, width, height, stime, target, maximizing);
             }
             else {
                 if (!maximizing) {
-                    target.SetBoolean(KeyStore.IsMinimized, true);
-                    target.SetNumber(KeyStore.X, targ[0]);
-                    target.SetNumber(KeyStore.Y, targ[1]);
-                    target.SetNumber(KeyStore.Width, width);
-                    target.SetNumber(KeyStore.Height, height);
+                    target.isMinimized = true;
+                    target.x = targ[0];
+                    target.y = targ[1];
+                    target.width = width;
+                    target.height = height;
                 }
                 this._completed = true;
             }
@@ -240,83 +252,71 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     _completed = true;
 
     @action
-    public toggleMinimize = (maximized: Document, minim: Document): void => {
+    public toggleMinimize = (maximized: Doc, minim: Doc): void => {
         SelectionManager.DeselectAll();
-        if (maximized instanceof Document && this._completed) {
+        if (this._completed) {
             this._completed = false;
-            let minimized = maximized.GetBoolean(KeyStore.IsMinimized, false);
-            maximized.SetBoolean(KeyStore.IsMinimized, false);
+            let minimized = Cast(maximized.isMinimized, "boolean", false);
+            maximized.isMinimized = false;
             this.animateTransition(
-                [minim.GetNumber(KeyStore.X, 0), minim.GetNumber(KeyStore.Y, 0)],
-                [maximized.GetNumber(KeyStore.X, 0), maximized.GetNumber(KeyStore.Y, 0)],
-                maximized.GetNumber(KeyStore.Width, 0), maximized.GetNumber(KeyStore.Height, 0),
+                [Cast(minim.x, "number", 0), Cast(minim.y, "number", 0)],
+                [Cast(maximized.x, "number", 0), Cast(maximized.y, "number", 0)],
+                Cast(maximized.width, "number", 0), Cast(maximized.width, "number", 0),
                 Date.now(), maximized, minimized);
         }
     }
 
     @action
-    public minimize = (): void => {
-        this.props.Document.GetAsync(KeyStore.MinimizedDoc, mindoc => {
-            if (mindoc === undefined) {
-                this.props.Document.GetAsync(KeyStore.BackgroundLayout, field => {
-                    if (field instanceof TextField) {
-                        this.toggleMinimize(this.props.Document, this.createIcon(field.Data));
-                    }
-                    else this.props.Document.GetAsync(KeyStore.Layout, field => {
-                        if (field instanceof TextField) {
-                            this.createIcon(field.Data);
-                            this.toggleMinimize(this.props.Document, this.createIcon(field.Data));
-                        }
-                    });
-                });
-            }
-            else if (mindoc instanceof Document) {
-                this.props.addDocument && this.props.addDocument(mindoc, false);
-                this.toggleMinimize(this.props.Document, mindoc);
+    public minimize = async (): Promise<void> => {
+        const mindoc = await Cast(this.props.Document.minimizedDoc, Doc);
+        if (mindoc === undefined) {
+            const background = await Cast(this.props.Document.backgroundLayout, "string");
+            if (background === undefined) {
+                const layout = await Cast(this.props.Document.layout, "string");
+                if (layout) {
+                    this.createIcon(layout);
+                    this.toggleMinimize(this.props.Document, this.createIcon(layout));
+                }
+            } else {
+                this.toggleMinimize(this.props.Document, this.createIcon(background));
             }
-        });
+        } else {
+            this.props.addDocument && this.props.addDocument(mindoc, false);
+            this.toggleMinimize(this.props.Document, mindoc);
+        }
     }
 
     @undoBatch
     @action
-    drop = (e: Event, de: DragManager.DropEvent) => {
+    drop = async (e: Event, de: DragManager.DropEvent) => {
         if (de.data instanceof DragManager.LinkDragData) {
-            let sourceDoc: Document = de.data.linkSourceDocument;
-            let destDoc: Document = this.props.Document;
-            let linkDoc: Document = new Document();
-
-            destDoc.GetTAsync(KeyStore.Prototype, Document).then(protoDest =>
-                sourceDoc.GetTAsync(KeyStore.Prototype, Document).then(protoSrc =>
-                    runInAction(() => {
-                        let batch = UndoManager.StartBatch("document view drop");
-                        linkDoc.SetText(KeyStore.Title, "New Link");
-                        linkDoc.SetText(KeyStore.LinkDescription, "");
-                        linkDoc.SetText(KeyStore.LinkTags, "Default");
-
-                        let dstTarg = protoDest ? protoDest : destDoc;
-                        let srcTarg = protoSrc ? protoSrc : sourceDoc;
-                        linkDoc.Set(KeyStore.LinkedToDocs, dstTarg);
-                        linkDoc.Set(KeyStore.LinkedFromDocs, srcTarg);
-                        const prom1 = new Promise(resolve => dstTarg.GetOrCreateAsync(
-                            KeyStore.LinkedFromDocs,
-                            ListField,
-                            field => {
-                                (field as ListField<Document>).Data.push(linkDoc);
-                                resolve();
-                            }
-                        ));
-                        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());
-                    })
-                )
-            );
+            let sourceDoc: Doc = de.data.linkSourceDocument;
+            let destDoc: Doc = this.props.Document;
+            let linkDoc = LinkDoc();
+
+            const protoDest = await Cast(destDoc.proto, Doc);
+            const protoSrc = await Cast(sourceDoc.proto, Doc);
+            UndoManager.RunInBatch(() => {
+                linkDoc.title = "New Link";
+                linkDoc.linkDescription = "";
+                linkDoc.linkTags = "Default";
+
+                let dstTarg = protoDest ? protoDest : destDoc;
+                let srcTarg = protoSrc ? protoSrc : sourceDoc;
+                linkDoc.linkedTo = dstTarg;
+                linkDoc.linkedFrom = srcTarg;
+                let linkedFrom = Cast(dstTarg.linkedFrom, listSpec(Doc));
+                if (!linkedFrom) {
+                    dstTarg.linkedFrom = linkedFrom = new List<Doc>();
+                }
+                linkedFrom.push(linkDoc);
+
+                let linkedTo = Cast(srcTarg.linkedTo, listSpec(Doc));
+                if (!linkedTo) {
+                    srcTarg.linkedTo = linkedTo = new List<Doc>();
+                }
+                linkedTo.push(linkDoc);
+            }, "document view drop");
             e.stopPropagation();
         }
     }
@@ -361,7 +361,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
 
     @computed get nativeWidth() { return FieldValue(this.Document.nativeWidth) || 0; }
     @computed get nativeHeight() { return FieldValue(this.Document.nativeHeight) || 0; }
-    @computed get contents() { return (<DocumentContentsView {...this.props} isSelected={this.isSelected} select={this.select} layoutKey={KeyStore.Layout} />); }
+    @computed get contents() { return (<DocumentContentsView {...this.props} isSelected={this.isSelected} select={this.select} layoutKey={"layout"} />); }
 
 
     render() {
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 639dae30a..cb082dc69 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -4,11 +4,6 @@ import { history } from "prosemirror-history";
 import { keymap } from "prosemirror-keymap";
 import { EditorState, Plugin, Transaction } from "prosemirror-state";
 import { EditorView } from "prosemirror-view";
-import { FieldWaiting, Opt } from "../../../fields/Field";
-import { KeyStore } from "../../../fields/KeyStore";
-import { RichTextField } from "../../../fields/RichTextField";
-import { TextField } from "../../../fields/TextField";
-import { Document } from "../../../fields/Document";
 import buildKeymap from "../../util/ProsemirrorKeymap";
 import { inpRules } from "../../util/RichTextRules";
 import { schema } from "../../util/RichTextSchema";
@@ -20,6 +15,9 @@ import { FieldView, FieldViewProps } from "./FieldView";
 import "./FormattedTextBox.scss";
 import React = require("react");
 import { SelectionManager } from "../../util/SelectionManager";
+import { DocComponent } from "../DocComponent";
+import { createSchema, makeInterface } from "../../../new_fields/Schema";
+import { Opt, Doc } from "../../../new_fields/Doc";
 const { buildMenuItems } = require("prosemirror-example-setup");
 const { menuBar } = require("prosemirror-menu");
 
@@ -44,7 +42,14 @@ export interface FormattedTextBoxOverlay {
     isOverlay?: boolean;
 }
 
-export class FormattedTextBox extends React.Component<(FieldViewProps & FormattedTextBoxOverlay)> {
+const richTextSchema = createSchema({
+    documentText: "string"
+});
+
+type RichTextDocument = makeInterface<[typeof richTextSchema]>;
+const RichTextDocument = makeInterface(richTextSchema);
+
+export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTextBoxOverlay), RichTextDocument>(RichTextDocument) {
     public static LayoutString(fieldStr: string = "DataKey") {
         return FieldView.LayoutString(FormattedTextBox, fieldStr);
     }
@@ -59,7 +64,6 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
         super(props);
 
         this._ref = React.createRef();
-        this.onChange = this.onChange.bind(this);
     }
 
     _applyingChange: boolean = false;
@@ -74,7 +78,7 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
                 JSON.stringify(state.toJSON()),
                 RichTextField
             );
-            this.props.Document.SetDataOnPrototype(KeyStore.DocumentText, state.doc.textBetween(0, state.doc.content.size, "\n\n"), TextField);
+            Doc.SetOnPrototype(this.props.Document, "documentText", state.doc.textBetween(0, state.doc.content.size, "\n\n"));
             this._applyingChange = false;
             // doc.SetData(fieldKey, JSON.stringify(state.toJSON()), RichTextField);
         }
@@ -166,12 +170,6 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
         }
     }
 
-    @action
-    onChange(e: React.ChangeEvent<HTMLInputElement>) {
-        const { fieldKey, Document } = this.props;
-        Document.SetOnPrototype(fieldKey, new RichTextField(e.target.value));
-        // doc.SetData(fieldKey, e.target.value, RichTextField);
-    }
     onPointerDown = (e: React.PointerEvent): void => {
         if (e.button === 1 && this.props.isSelected() && !e.altKey && !e.ctrlKey && !e.metaKey) {
             console.log("first");
@@ -252,7 +250,7 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
     }
 
     onKeyPress(e: React.KeyboardEvent) {
-        if (e.key == "Escape") {
+        if (e.key === "Escape") {
             SelectionManager.DeselectAll();
         }
         e.stopPropagation();
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 60abccce6..5ae095e68 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -33,8 +33,8 @@ export class ObjectField {
 
 export type Field = number | string | boolean | ObjectField | RefField;
 export type Opt<T> = T | undefined;
-export type FieldWaiting<T extends Field = Field> = Promise<T | undefined>;
-export type FieldResult<T extends Field = Field> = Opt<T> | FieldWaiting<T>;
+export type FieldWaiting<T extends RefField = RefField> = T extends undefined ? never : Promise<T | undefined>;
+export type FieldResult<T extends Field = Field> = Opt<T> | FieldWaiting<Extract<T, RefField>>;
 
 export const Self = Symbol("Self");
 
@@ -58,7 +58,8 @@ export class Doc extends RefField {
 
     @serializable(alias("fields", map(autoObject())))
     @observable
-    private __fields: { [key: string]: Field | FieldWaiting | undefined } = {};
+    //{ [key: string]: Field | FieldWaiting | undefined }
+    private __fields: any = {};
 
     private [Update] = (diff: any) => {
         DocServer.UpdateField(this[Id], diff);
@@ -86,7 +87,7 @@ export namespace Doc {
         return Cast(Get(doc, key, ignoreProto), ctor) as T | null | undefined;
     }
     export async function SetOnPrototype(doc: Doc, key: string, value: Field) {
-        const proto = await Cast(doc.prototype, Doc);
+        const proto = await Cast(doc.proto, Doc);
         if (proto) {
             proto[key] = value;
         }
@@ -97,7 +98,7 @@ export namespace Doc {
         }
         const delegate = new Doc();
         //TODO Does this need to be doc[Self]?
-        delegate.prototype = doc;
+        delegate.proto = doc;
         return delegate;
     }
     export const Prototype = Symbol("Prototype");
diff --git a/src/new_fields/Schema.ts b/src/new_fields/Schema.ts
index 59c6db0bd..5081521c7 100644
--- a/src/new_fields/Schema.ts
+++ b/src/new_fields/Schema.ts
@@ -1,7 +1,5 @@
 import { Interface, ToInterface, Cast, ToConstructor, HasTail, Head, Tail, ListSpec, ToType } from "./Types";
-import { Doc, Field, ObjectField } from "./Doc";
-import { URLField } from "./URLField";
-import { List } from "./List";
+import { Doc, Field } from "./Doc";
 
 type AllToInterface<T extends Interface[]> = {
     1: ToInterface<Head<T>> & AllToInterface<Tail<T>>,
@@ -15,7 +13,7 @@ export type Document = makeInterface<[typeof emptySchema]>;
 export type makeInterface<T extends Interface[]> = Partial<AllToInterface<T>> & Doc;
 // export function makeInterface<T extends Interface[], U extends Doc>(schemas: T): (doc: U) => All<T, U>;
 // export function makeInterface<T extends Interface, U extends Doc>(schema: T): (doc: U) => makeInterface<T, U>; 
-export function makeInterface<T extends Interface[]>(...schemas: T): (doc: Doc) => makeInterface<T> {
+export function makeInterface<T extends Interface[]>(...schemas: T): (doc?: Doc) => makeInterface<T> {
     let schema: Interface = {};
     for (const s of schemas) {
         for (const key in s) {
@@ -35,7 +33,8 @@ export function makeInterface<T extends Interface[]>(...schemas: T): (doc: Doc)
             return true;
         }
     });
-    return function (doc: Doc) {
+    return function (doc?: Doc) {
+        doc = doc || new Doc;
         if (!(doc instanceof Doc)) {
             throw new Error("Currently wrapping a schema in another schema isn't supported");
         }
@@ -73,8 +72,8 @@ export function makeStrictInterface<T extends Interface>(schema: T): (doc: Doc)
     };
 }
 
-export function createSchema<T extends Interface>(schema: T): T & { prototype: ToConstructor<Doc> } {
-    schema.prototype = Doc;
+export function createSchema<T extends Interface>(schema: T): T & { proto: ToConstructor<Doc> } {
+    schema.proto = Doc;
     return schema as any;
 }
 
diff --git a/src/new_fields/Types.ts b/src/new_fields/Types.ts
index fbf002c84..246b0624e 100644
--- a/src/new_fields/Types.ts
+++ b/src/new_fields/Types.ts
@@ -1,4 +1,4 @@
-import { Field, Opt, FieldWaiting, FieldResult } from "./Doc";
+import { Field, Opt, FieldWaiting, FieldResult, RefField } from "./Doc";
 import { List } from "./List";
 
 export type ToType<T extends ToConstructor<Field> | ListSpec<Field>> =
@@ -18,7 +18,7 @@ export type ToConstructor<T extends Field> =
     new (...args: any[]) => T;
 
 export type ToInterface<T extends Interface> = {
-    [P in keyof T]: ToType<T[P]>;
+    [P in keyof T]: FieldResult<ToType<T[P]>>;
 };
 
 // type ListSpec<T extends Field[]> = { List: ToContructor<Head<T>> | ListSpec<Tail<T>> };
@@ -37,11 +37,11 @@ export interface Interface {
     // [key: string]: ToConstructor<Field> | ListSpec<Field[]>;
 }
 
-export function Cast<T extends ToConstructor<Field> | ListSpec<Field>>(field: Field | FieldWaiting | undefined, ctor: T): FieldResult<ToType<T>>;
-export function Cast<T extends ToConstructor<Field> | ListSpec<Field>>(field: Field | FieldWaiting | undefined, ctor: T, defaultVal: ToType<T>): ToType<T>;
-export function Cast<T extends ToConstructor<Field> | ListSpec<Field>>(field: Field | FieldWaiting | undefined, ctor: T, defaultVal?: ToType<T>): FieldResult<ToType<T>> | undefined {
+export function Cast<T extends ToConstructor<Field> | ListSpec<Field>>(field: FieldResult, ctor: T): FieldResult<ToType<T>>;
+export function Cast<T extends ToConstructor<Field> | ListSpec<Field>>(field: FieldResult, ctor: T, defaultVal: ToType<T>): ToType<T>;
+export function Cast<T extends ToConstructor<Field> | ListSpec<Field>>(field: FieldResult, ctor: T, defaultVal?: ToType<T>): FieldResult<ToType<T>> | undefined {
     if (field instanceof Promise) {
-        return defaultVal === undefined ? field.then(f => Cast(f, ctor) as any) : defaultVal;
+        return defaultVal === undefined ? field.then(f => Cast(f, ctor) as any) as any : defaultVal;
     }
     if (field !== undefined && !(field instanceof Promise)) {
         if (typeof ctor === "string") {
-- 
cgit v1.2.3-70-g09d2


From 1eaf7210492e3cc968f26d848c6db7b4e603a657 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 23 Apr 2019 15:24:10 -0400
Subject: maybe working events?

---
 src/client/util/SelectionManager.ts                      |  6 ++----
 src/client/views/collections/CollectionBaseView.tsx      |  7 +++++--
 .../views/collections/collectionFreeForm/MarqueeView.tsx | 16 +++++++++++-----
 .../views/nodes/CollectionFreeFormDocumentView.tsx       |  1 -
 src/client/views/nodes/DocumentView.tsx                  | 14 +++++++++-----
 src/client/views/nodes/FormattedTextBox.tsx              |  7 ++++++-
 6 files changed, 33 insertions(+), 18 deletions(-)

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

diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 92d78696e..0e7b374e9 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -1,9 +1,7 @@
-import { observable, action } from "mobx";
-import { DocumentView } from "../views/nodes/DocumentView";
+import { action, observable } from "mobx";
 import { Document } from "../../fields/Document";
-import { Main } from "../views/Main";
 import { MainOverlayTextBox } from "../views/MainOverlayTextBox";
-import { DragManager } from "./DragManager";
+import { DocumentView } from "../views/nodes/DocumentView";
 
 export namespace SelectionManager {
     class Manager {
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 962cb9b65..097236c1d 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -103,8 +103,11 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
                 this.props.Document.Set(this.props.fieldKey, new ListField([doc]));
             }
             // set the ZoomBasis only if hasn't already been set -- bcz: maybe set/resetting the ZoomBasis should be a parameter to addDocument?
-            doc.GetTAsync(KeyStore.ZoomBasis, NumberField, field => !field &&
-                doc.SetNumber(KeyStore.ZoomBasis, this.props.Document.GetNumber(KeyStore.Scale, 1)));
+            if (this.collectionViewType === CollectionViewType.Freeform || this.collectionViewType === CollectionViewType.Invalid) {
+                let zoom = this.props.Document.GetNumber(KeyStore.Scale, 1);
+                let screen = this.props.ScreenToLocalTransform().inverse().Scale / (this.props as any).ContentScaling() * zoom;
+                doc.SetNumber(KeyStore.ZoomBasis, screen);
+            }
         }
         return true;
         // bcz: What is this code trying to do?
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index a624c671f..48844f10c 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -79,6 +79,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             document.addEventListener("pointermove", this.onPointerMove, true);
             document.addEventListener("pointerup", this.onPointerUp, true);
             document.addEventListener("keydown", this.marqueeCommand, true);
+            e.stopPropagation();
         }
         if (e.altKey)
             e.preventDefault();
@@ -110,10 +111,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
     onPointerUp = (e: PointerEvent): void => {
         this.cleanupInteractions(true);
         this._visible = false;
-        if (this._showOnUp) {
-            PreviewCursor.Show(this.hideCursor, this._downX, this._downY);
-            document.addEventListener("keypress", this.onKeyPress, false);
-        } else if ((CollectionFreeFormView.RIGHT_BTN_DRAG && e.button === 0 && !e.altKey && !e.metaKey) ||
+        if (!this._showOnUp && (CollectionFreeFormView.RIGHT_BTN_DRAG && e.button === 0 && !e.altKey && !e.metaKey) ||
             (!CollectionFreeFormView.RIGHT_BTN_DRAG && ((e.button === 0 && e.altKey) || e.button === 2))) {
             let mselect = this.marqueeSelect();
             if (!e.shiftKey) {
@@ -125,6 +123,12 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             e.preventDefault();
     }
 
+    @action
+    onClick = (e: MouseEvent): void => {
+        PreviewCursor.Show(this.hideCursor, this._downX, this._downY);
+        document.addEventListener("keypress", this.onKeyPress, false);
+    }
+
     intersectRect(r1: { left: number, top: number, width: number, height: number },
         r2: { left: number, top: number, width: number, height: number }) {
         return !(r2.left > r1.left + r1.width || r2.left + r2.width < r1.left || r2.top > r1.top + r1.height || r2.top + r2.height < r1.top);
@@ -149,8 +153,10 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                 this.marqueeInkDelete(ink.Data);
             }
             this.cleanupInteractions();
+            e.stopPropagation();
         }
         if (e.key === "c") {
+            e.stopPropagation();
             let bounds = this.Bounds;
             let selected = this.marqueeSelect().map(d => {
                 this.props.removeDocument(d);
@@ -239,7 +245,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
     }
 
     render() {
-        return <div className="marqueeView" onPointerDown={this.onPointerDown}>
+        return <div className="marqueeView" onClick={this.onClick} onPointerDown={this.onPointerDown}>
             {this.props.children}
             {!this._visible ? (null) : this.marqueeDiv}
         </div>;
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 3a4425358..671bfbc04 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -134,7 +134,6 @@ export class CollectionFreeFormDocumentView extends React.Component<CollectionFr
         })
     }
     onPointerDown = (e: React.PointerEvent): void => {
-        e.stopPropagation();
         this._downX = e.clientX;
         this._downY = e.clientY;
         document.removeEventListener("pointerup", this.onPointerUp);
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 8922e4b81..efa291c0f 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -22,6 +22,7 @@ import { DocumentContentsView } from "./DocumentContentsView";
 import "./DocumentView.scss";
 import React = require("react");
 import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView";
+import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils";
 
 export interface DocumentViewProps {
     ContainingCollectionView: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
@@ -144,6 +145,13 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         }
     }
 
+    onClick = (e: React.MouseEvent): void => {
+        console.log("click = " + this.props.Document.Title);
+        if (CurrentUserUtils.MainDocId != this.props.Document.Id) {
+            SelectionManager.SelectDoc(this, e.ctrlKey);
+        }
+        e.stopPropagation();
+    }
     onPointerDown = (e: React.PointerEvent): void => {
         this._downX = e.clientX;
         this._downY = e.clientY;
@@ -180,10 +188,6 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     onPointerUp = (e: PointerEvent): void => {
         document.removeEventListener("pointermove", this.onPointerMove);
         document.removeEventListener("pointerup", this.onPointerUp);
-        if (!SelectionManager.IsSelected(this) && e.button !== 2 &&
-            Math.abs(e.clientX - this._downX) < 4 && Math.abs(e.clientY - this._downY) < 4) {
-            SelectionManager.SelectDoc(this, e.ctrlKey);
-        }
     }
 
     deleteClicked = (): void => {
@@ -304,7 +308,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
                     width: nativeWidth, height: nativeHeight,
                     transform: `scale(${scaling}, ${scaling})`
                 }}
-                onDrop={this.onDrop} onContextMenu={this.onContextMenu} onPointerDown={this.onPointerDown}
+                onDrop={this.onDrop} onContextMenu={this.onContextMenu} onPointerDown={this.onPointerDown} onClick={this.onClick}
             >
                 {this.contents}
             </div>
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 29ed2da13..56c21dbd3 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -229,6 +229,10 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
         }
     }
 
+    onClick = (e: React.MouseEvent): void => {
+        this._ref.current!.focus();
+    }
+
     tooltipTextMenuPlugin() {
         let myprops = this.props;
         return new Plugin({
@@ -255,7 +259,7 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
         if (e.keyCode === 9) e.preventDefault();
         // stop propagation doesn't seem to stop propagation of native keyboard events.
         // so we set a flag on the native event that marks that the event's been handled.
-        // (e.nativeEvent as any).DASHFormattedTextBoxHandled = true;
+        (e.nativeEvent as any).DASHFormattedTextBoxHandled = true;
     }
     render() {
         let style = this.props.isOverlay ? "scroll" : "hidden";
@@ -264,6 +268,7 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
                 onKeyDown={this.onKeyPress}
                 onKeyPress={this.onKeyPress}
                 onFocus={this.onFocused}
+                onClick={this.onClick}
                 onPointerUp={this.onPointerUp}
                 onPointerDown={this.onPointerDown}
                 onContextMenu={this.specificContextMenu}
-- 
cgit v1.2.3-70-g09d2


From 04b177406a98a52f4f8b3f94375f94db2f46a5df Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 24 Apr 2019 09:22:41 -0400
Subject: added simple text box titling

---
 src/client/views/DocumentDecorations.tsx                        | 2 +-
 src/client/views/collections/collectionFreeForm/MarqueeView.tsx | 2 +-
 src/client/views/nodes/FormattedTextBox.tsx                     | 9 ++++++++-
 3 files changed, 10 insertions(+), 3 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 95910c7be..539f19707 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -444,7 +444,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
     }
 
     getValue = (): string => {
-        if (this._title === "changed" && this._documents.length > 0) {
+        if (this._documents.length > 0) {
             let field = this._documents[0].props.Document.Get(this._fieldKey);
             if (field instanceof TextField) {
                 return (field).GetValue();
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 623643238..06e8a9fc6 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -49,7 +49,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
     onKeyPress = (e: KeyboardEvent) => {
         //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" });
+        let newBox = Documents.TextDocument({ width: 200, height: 100, x: x, y: y, title: "-typed text-" });
         this.props.addLiveTextDocument(newBox);
         e.stopPropagation();
     }
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 56c21dbd3..91b44962d 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -166,6 +166,7 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
         Document.SetOnPrototype(fieldKey, new RichTextField(e.target.value));
         // doc.SetData(fieldKey, e.target.value, RichTextField);
     }
+    @action
     onPointerDown = (e: React.PointerEvent): void => {
         if (e.button === 1 && this.props.isSelected() && !e.altKey && !e.ctrlKey && !e.metaKey) {
             console.log("first");
@@ -251,7 +252,8 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
         });
     }
 
-    onKeyPress(e: React.KeyboardEvent) {
+    @action
+    onKeyPress = (e: React.KeyboardEvent) => {
         if (e.key == "Escape") {
             SelectionManager.DeselectAll();
         }
@@ -260,6 +262,11 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
         // stop propagation doesn't seem to stop propagation of native keyboard events.
         // so we set a flag on the native event that marks that the event's been handled.
         (e.nativeEvent as any).DASHFormattedTextBoxHandled = true;
+        if (this.props.Document.Title.startsWith("-") && this._editorView) {
+            let str = this._editorView.state.doc.textContent;
+            let titlestr = str.substr(0, Math.min(40, str.length));
+            this.props.Document.SetText(KeyStore.Title, "-" + titlestr + (str.length > 40 ? "..." : ""));
+        };
     }
     render() {
         let style = this.props.isOverlay ? "scroll" : "hidden";
-- 
cgit v1.2.3-70-g09d2


From 20becbb5ca40350ed85e01f73f29621ba7783bb9 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 24 Apr 2019 12:20:38 -0400
Subject: playing with linking

---
 src/client/util/DragManager.ts                     |  6 ++--
 src/client/views/DocumentDecorations.tsx           |  3 +-
 src/client/views/PreviewCursor.tsx                 |  8 +++--
 .../collections/collectionFreeForm/MarqueeView.tsx | 33 ++++++++++++++++---
 .../views/nodes/CollectionFreeFormDocumentView.tsx | 16 ++++-----
 src/client/views/nodes/DocumentView.tsx            | 38 ++--------------------
 src/client/views/nodes/FormattedTextBox.tsx        |  2 ++
 src/fields/Document.ts                             | 31 ++++++++++++++++++
 8 files changed, 80 insertions(+), 57 deletions(-)

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

diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 91b3ce616..5aa7ad8e2 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -41,11 +41,11 @@ export function SetupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc:
 }
 
 export async function DragLinksAsDocuments(dragEle: HTMLElement, x: number, y: number, sourceDoc: Document) {
-    let srcTarg = sourceDoc.GetT(KeyStore.Prototype, Document);
-    let draggedDocs = (srcTarg && srcTarg !== FieldWaiting) ?
+    let srcTarg = sourceDoc.GetPrototype();
+    let draggedDocs = srcTarg ?
         srcTarg.GetList(KeyStore.LinkedToDocs, [] as Document[]).map(linkDoc =>
             (linkDoc.GetT(KeyStore.LinkedToDocs, Document)) as Document) : [];
-    let draggedFromDocs = (srcTarg && srcTarg !== FieldWaiting) ?
+    let draggedFromDocs = srcTarg ?
         srcTarg.GetList(KeyStore.LinkedFromDocs, [] as Document[]).map(linkDoc =>
             (linkDoc.GetT(KeyStore.LinkedFromDocs, Document)) as Document) : [];
     draggedDocs.push(...draggedFromDocs);
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 5c57a829a..9995c1c3f 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -6,7 +6,7 @@ import { ListField } from "../../fields/ListField";
 import { NumberField } from "../../fields/NumberField";
 import { TextField } from "../../fields/TextField";
 import { Document } from "../../fields/Document";
-import { emptyFunction } from "../../Utils";
+import { emptyFunction, Utils } from "../../Utils";
 import { DragLinksAsDocuments, DragManager } from "../util/DragManager";
 import { SelectionManager } from "../util/SelectionManager";
 import { undoBatch } from "../util/UndoManager";
@@ -19,7 +19,6 @@ import { CompileScript } from "../util/Scripting";
 import { IconBox } from "./nodes/IconBox";
 import { FieldValue, Field } from "../../fields/Field";
 import { Documents } from "../documents/Documents";
-import { Utils } from "../northstar/utils/Utils";
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx
index 39b6c6544..744ec0535 100644
--- a/src/client/views/PreviewCursor.tsx
+++ b/src/client/views/PreviewCursor.tsx
@@ -17,7 +17,7 @@ export class PreviewCursor extends React.Component<{}> {
 
     constructor(props: any) {
         super(props);
-        document.addEventListener("keypress", this.onKeyPress)
+        document.addEventListener("keydown", this.onKeyPress)
     }
 
     @action
@@ -28,8 +28,12 @@ export class PreviewCursor extends React.Component<{}> {
         //if not these keys, make a textbox if preview cursor is active!
         if (!e.ctrlKey && !e.altKey && !e.defaultPrevented && !(e as any).DASHFormattedTextBoxHandled) {
             PreviewCursor.Visible && PreviewCursor._onKeyPress && PreviewCursor._onKeyPress(e);
+            PreviewCursor.Visible = false;
+        } else if (e.ctrlKey) {
+            if (e.key == "v") {
+                PreviewCursor.Visible && PreviewCursor._onKeyPress && PreviewCursor._onKeyPress(e);
+            }
         }
-        PreviewCursor.Visible = false;
     }
     @action
     public static Show(x: number, y: number, onKeyPress: (e: KeyboardEvent) => void) {
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 39b42dac9..898fff019 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -14,6 +14,7 @@ import { CollectionFreeFormView } from "./CollectionFreeFormView";
 import "./MarqueeView.scss";
 import React = require("react");
 import { Utils } from "../../../../Utils";
+import { ListField } from "../../../../fields/ListField";
 
 interface MarqueeViewProps {
     getContainerTransform: () => Transform;
@@ -128,16 +129,16 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
     @undoBatch
     @action
     marqueeCommand = (e: KeyboardEvent) => {
-        if (e.key === "Backspace" || e.key === "Delete") {
+        if (e.key === "Backspace" || e.key === "Delete" || e.key == "d") {
             this.marqueeSelect().map(d => this.props.removeDocument(d));
             let ink = this.props.container.props.Document.GetT(KeyStore.Ink, InkField);
             if (ink && ink !== FieldWaiting) {
                 this.marqueeInkDelete(ink.Data);
             }
-            this.cleanupInteractions();
+            this.cleanupInteractions(true);
             e.stopPropagation();
         }
-        if (e.key === "c") {
+        if (e.key === "c" || e.key === "r") {
             e.stopPropagation();
             let bounds = this.Bounds;
             let selected = this.marqueeSelect().map(d => {
@@ -155,16 +156,38 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                 y: bounds.top,
                 panx: 0,
                 pany: 0,
+                backgroundColor: selected.length ? "white" : "",
                 scale: zoomBasis,
                 width: bounds.width * zoomBasis,
                 height: bounds.height * zoomBasis,
                 ink: inkData ? this.marqueeInkSelect(inkData) : undefined,
                 title: "a nested collection"
             });
-            this.props.addDocument(newCollection, false);
+
             this.marqueeInkDelete(inkData);
-            this.cleanupInteractions();
             SelectionManager.DeselectAll();
+            if (e.key === "r") {
+                let summary = Documents.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" });
+                summary.GetPrototype()!.CreateLink(newCollection.GetPrototype()!);
+                this.props.addLiveTextDocument(summary);
+                e.preventDefault();
+            }
+            else {
+                this.props.addDocument(newCollection, false);
+            }
+            this.cleanupInteractions(true);
+        }
+        if (e.key === "s") {
+            e.stopPropagation();
+            e.preventDefault();
+            let bounds = this.Bounds;
+            let selected = this.marqueeSelect();
+            SelectionManager.DeselectAll();
+            let summary = Documents.TextDocument({ x: bounds.left + bounds.width + 25, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" });
+            this.props.addLiveTextDocument(summary);
+            selected.map(select => summary.GetPrototype()!.CreateLink(select.GetPrototype()!));
+
+            this.cleanupInteractions(true);
         }
     }
     @action
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 671bfbc04..420324d40 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -7,7 +7,7 @@ import { Transform } from "../../util/Transform";
 import { DocumentView, DocumentViewProps } from "./DocumentView";
 import "./DocumentView.scss";
 import React = require("react");
-import { OmitKeys } from "../../../Utils";
+import { OmitKeys, Utils } from "../../../Utils";
 import { SelectionManager } from "../../util/SelectionManager";
 import { ListField } from "../../../fields/ListField";
 import { BooleanField } from "../../../fields/BooleanField";
@@ -102,9 +102,7 @@ export class CollectionFreeFormDocumentView extends React.Component<CollectionFr
     public toggleIcon = async (): Promise<void> => {
         SelectionManager.DeselectAll();
         let isMinimized: boolean | undefined;
-        let minDoc = await this.props.Document.GetTAsync(KeyStore.MinimizedDoc, Document);
-        if (!minDoc) return;
-        let minimizedDocSet = await minDoc.GetTAsync(KeyStore.LinkTags, ListField);
+        let minimizedDocSet = await this.props.Document.GetTAsync(KeyStore.LinkTags, ListField);
         if (!minimizedDocSet) return;
         minimizedDocSet.Data.map(async minimizedDoc => {
             if (minimizedDoc instanceof Document) {
@@ -136,16 +134,13 @@ export class CollectionFreeFormDocumentView extends React.Component<CollectionFr
     onPointerDown = (e: React.PointerEvent): void => {
         this._downX = e.clientX;
         this._downY = e.clientY;
-        document.removeEventListener("pointerup", this.onPointerUp);
-        document.addEventListener("pointerup", this.onPointerUp);
     }
-    onPointerUp = (e: PointerEvent): void => {
-        document.removeEventListener("pointerup", this.onPointerUp);
+    onClick = (e: React.MouseEvent): void => {
         e.stopPropagation();
-        if (Math.abs(e.clientX - this._downX) < 4 && Math.abs(e.clientY - this._downY) < 4) {
+        if (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD &&
+            Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD) {
             this.props.Document.GetTAsync(KeyStore.MaximizedDoc, Document).then(maxdoc => {
                 if (maxdoc instanceof Document) {   // bcz: need a better way to associate behaviors with click events on widget-documents
-                    SelectionManager.DeselectAll();
                     this.props.addDocument && this.props.addDocument(maxdoc, false);
                     this.toggleIcon();
                 }
@@ -170,6 +165,7 @@ export class CollectionFreeFormDocumentView extends React.Component<CollectionFr
         return (
             <div className="collectionFreeFormDocumentView-container" ref={this._mainCont}
                 onPointerDown={this.onPointerDown}
+                onClick={this.onClick}
                 style={{
                     opacity: zoomFade,
                     transformOrigin: "left top",
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 252f4d039..c19b0c342 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -152,7 +152,6 @@ export class DocumentView extends React.Component<DocumentViewProps> {
                 Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) {
             SelectionManager.SelectDoc(this, e.ctrlKey);
         }
-        e.stopPropagation();
     }
     onPointerDown = (e: React.PointerEvent): void => {
         this._downX = e.clientX;
@@ -217,43 +216,12 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     @action
     drop = (e: Event, de: DragManager.DropEvent) => {
         if (de.data instanceof DragManager.LinkDragData) {
-            let sourceDoc: Document = de.data.linkSourceDocument;
-            let destDoc: Document = this.props.Document;
-            let linkDoc: Document = new Document();
+            let sourceDoc = de.data.linkSourceDocument;
+            let destDoc = this.props.Document;
 
             destDoc.GetTAsync(KeyStore.Prototype, Document).then(protoDest =>
                 sourceDoc.GetTAsync(KeyStore.Prototype, Document).then(protoSrc =>
-                    runInAction(() => {
-                        let batch = UndoManager.StartBatch("document view drop");
-                        linkDoc.SetText(KeyStore.Title, "New Link");
-                        linkDoc.SetText(KeyStore.LinkDescription, "");
-                        linkDoc.SetText(KeyStore.LinkTags, "Default");
-
-                        let dstTarg = protoDest ? protoDest : destDoc;
-                        let srcTarg = protoSrc ? protoSrc : sourceDoc;
-                        if ((de.data as DragManager.LinkDragData).blacklist.indexOf(dstTarg) === -1) {
-                            linkDoc.Set(KeyStore.LinkedToDocs, dstTarg);
-                            linkDoc.Set(KeyStore.LinkedFromDocs, srcTarg);
-                            const prom1 = new Promise(resolve => dstTarg.GetOrCreateAsync(
-                                KeyStore.LinkedFromDocs,
-                                ListField,
-                                field => {
-                                    (field as ListField<Document>).Data.push(linkDoc);
-                                    resolve();
-                                }
-                            ));
-                            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());
-                        }
-                    })
-                )
+                    (protoSrc ? protoSrc : sourceDoc).CreateLink(protoDest ? protoDest : destDoc))
             );
             e.stopPropagation();
         }
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 91b44962d..9cd58c73a 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -270,8 +270,10 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
     }
     render() {
         let style = this.props.isOverlay ? "scroll" : "hidden";
+        let color = this.props.Document.GetText(KeyStore.BackgroundColor, "");
         return (
             <div className={`formattedTextBox-cont-${style}`}
+                style={{ background: color }}
                 onKeyDown={this.onKeyPress}
                 onKeyPress={this.onKeyPress}
                 onFocus={this.onFocused}
diff --git a/src/fields/Document.ts b/src/fields/Document.ts
index 7cf784f0e..7a7dbc3fe 100644
--- a/src/fields/Document.ts
+++ b/src/fields/Document.ts
@@ -371,6 +371,37 @@ export class Document extends Field {
         return alias;
     }
 
+    @action
+    CreateLink(dstTarg: Document) {
+        let batch = UndoManager.StartBatch("document view drop");
+        let linkDoc: Document = new Document();
+        linkDoc.SetText(KeyStore.Title, "New Link");
+        linkDoc.SetText(KeyStore.LinkDescription, "");
+        linkDoc.SetText(KeyStore.LinkTags, "Default");
+
+        let srcTarg = this;
+        linkDoc.Set(KeyStore.LinkedToDocs, dstTarg);
+        linkDoc.Set(KeyStore.LinkedFromDocs, srcTarg);
+        const prom1 = new Promise(resolve => dstTarg.GetOrCreateAsync(
+            KeyStore.LinkedFromDocs,
+            ListField,
+            field => {
+                (field as ListField<Document>).Data.push(linkDoc);
+                resolve();
+            }
+        ));
+        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());
+        return linkDoc;
+    }
+
     MakeDelegate(id?: string): Document {
         let delegate = new Document(id);
 
-- 
cgit v1.2.3-70-g09d2


From 575d8b339cdf74cdcb8d46dcd6e627aec2dda636 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 24 Apr 2019 23:17:44 -0400
Subject: added borderRadius and fixed a bunch of broken props along the way.

---
 src/client/documents/Documents.ts                          |  2 ++
 src/client/views/Main.scss                                 |  3 ++-
 src/client/views/Main.tsx                                  |  3 ++-
 src/client/views/MainOverlayTextBox.tsx                    |  4 ++--
 src/client/views/collections/CollectionBaseView.tsx        |  7 ++++---
 src/client/views/collections/CollectionDockingView.tsx     |  3 ++-
 src/client/views/collections/CollectionSchemaView.tsx      |  6 +++++-
 src/client/views/collections/CollectionSubView.tsx         |  1 +
 src/client/views/collections/CollectionTreeView.tsx        |  5 ++++-
 .../collectionFreeForm/CollectionFreeFormView.scss         |  1 +
 .../collectionFreeForm/CollectionFreeFormView.tsx          | 14 +++++++++++---
 .../views/collections/collectionFreeForm/MarqueeView.tsx   |  7 ++++---
 src/client/views/nodes/CollectionFreeFormDocumentView.tsx  | 11 +++++++++++
 src/client/views/nodes/DocumentView.tsx                    |  2 ++
 src/client/views/nodes/FieldView.tsx                       |  7 ++++++-
 src/client/views/nodes/FormattedTextBox.scss               |  3 +--
 src/client/views/nodes/FormattedTextBox.tsx                |  5 ++++-
 src/client/views/nodes/ImageBox.scss                       |  3 ---
 src/client/views/nodes/ImageBox.tsx                        |  2 +-
 src/fields/KeyStore.ts                                     |  3 ++-
 20 files changed, 67 insertions(+), 25 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 0e6661819..879b114b6 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -55,6 +55,7 @@ export interface DocumentOptions {
     backgroundColor?: string;
     copyDraggedItems?: boolean;
     documentText?: string;
+    borderRounding?: number;
 }
 
 export namespace Documents {
@@ -108,6 +109,7 @@ export namespace Documents {
         if (options.layout !== undefined) { doc.SetText(KeyStore.Layout, options.layout); }
         if (options.layoutKeys !== undefined) { doc.Set(KeyStore.LayoutKeys, new ListField(options.layoutKeys)); }
         if (options.copyDraggedItems !== undefined) { doc.SetBoolean(KeyStore.CopyDraggedItems, options.copyDraggedItems); }
+        if (options.borderRounding !== undefined) { doc.SetNumber(KeyStore.BorderRounding, options.borderRounding); }
         return doc;
     }
 
diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss
index 4373534b2..3edc79d39 100644
--- a/src/client/views/Main.scss
+++ b/src/client/views/Main.scss
@@ -42,7 +42,8 @@ h1 {
 }
 
 .jsx-parser {
-    width:100%
+    width:100%;
+    pointer-events: none;
 }
 
 p {
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 934616aca..057f68ed9 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -17,7 +17,7 @@ import { CurrentUserUtils } from '../../server/authentication/models/current_use
 import { MessageStore } from '../../server/Message';
 import { RouteStore } from '../../server/RouteStore';
 import { ServerUtils } from '../../server/ServerUtil';
-import { emptyDocFunction, emptyFunction, returnTrue, Utils, returnOne } from '../../Utils';
+import { emptyDocFunction, emptyFunction, returnTrue, Utils, returnOne, returnZero } from '../../Utils';
 import { Documents } from '../documents/Documents';
 import { ColumnAttributeModel } from '../northstar/core/attribute/AttributeModel';
 import { AttributeTransformationModel } from '../northstar/core/attribute/AttributeTransformationModel';
@@ -197,6 +197,7 @@ export class Main extends React.Component {
                             isTopMost={true}
                             selectOnLoad={false}
                             focus={emptyDocFunction}
+                            borderRounding={returnZero}
                             parentActive={returnTrue}
                             whenActiveChanged={emptyFunction}
                             ContainingCollectionView={undefined} />}
diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx
index 9aaaad084..f98f6e8a5 100644
--- a/src/client/views/MainOverlayTextBox.tsx
+++ b/src/client/views/MainOverlayTextBox.tsx
@@ -5,7 +5,7 @@ import * as React from 'react';
 import { Document } from '../../fields/Document';
 import { Key } from '../../fields/Key';
 import { KeyStore } from '../../fields/KeyStore';
-import { emptyDocFunction, emptyFunction, returnTrue } from '../../Utils';
+import { emptyDocFunction, emptyFunction, returnTrue, returnZero } from '../../Utils';
 import '../northstar/model/ModelExtensions';
 import '../northstar/utils/Extensions';
 import { DragManager } from '../util/DragManager';
@@ -97,7 +97,7 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
                     style={{ width: `${this.TextDoc.Width()}px`, height: `${this.TextDoc.Height()}px` }}>
                     <FormattedTextBox fieldKey={this._textFieldKey} isOverlay={true} Document={this.TextDoc} isSelected={returnTrue} select={emptyFunction} isTopMost={true}
                         selectOnLoad={true} ContainingCollectionView={undefined} whenActiveChanged={emptyFunction} active={returnTrue}
-                        ScreenToLocalTransform={this._textXf} focus={emptyDocFunction} />
+                        ScreenToLocalTransform={this._textXf} borderRounding={returnZero} PanelWidth={returnZero} PanelHeight={returnZero} focus={emptyDocFunction} />
                 </div>
             </ div>;
         }
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 097236c1d..e65770137 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -2,13 +2,12 @@ import { action, computed } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Document } from '../../../fields/Document';
-import { Field, FieldValue, FieldWaiting } from '../../../fields/Field';
+import { FieldValue, FieldWaiting } from '../../../fields/Field';
 import { KeyStore } from '../../../fields/KeyStore';
 import { ListField } from '../../../fields/ListField';
 import { NumberField } from '../../../fields/NumberField';
 import { ContextMenu } from '../ContextMenu';
 import { FieldViewProps } from '../nodes/FieldView';
-import { TextField } from '../../../fields/TextField';
 
 export enum CollectionViewType {
     Invalid,
@@ -190,7 +189,9 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         };
         const viewtype = this.collectionViewType;
         return (
-            <div className={this.props.className || "collectionView-cont"} onContextMenu={this.props.onContextMenu} ref={this.props.contentRef}>
+            <div className={this.props.className || "collectionView-cont"}
+                style={{ borderRadius: `${this.props.borderRounding()}px`, pointerEvents: "all" }}
+                onContextMenu={this.props.onContextMenu} ref={this.props.contentRef}>
                 {viewtype !== undefined ? this.props.children(viewtype, props) : (null)}
             </div>
         );
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 84159635a..eb94a4e6d 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, emptyDocFunction, returnOne } from "../../../Utils";
+import { Utils, returnTrue, emptyFunction, emptyDocFunction, returnOne, returnZero } from "../../../Utils";
 import { Server } from "../../Server";
 import { undoBatch } from "../../util/UndoManager";
 import { DocumentView } from "../nodes/DocumentView";
@@ -368,6 +368,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
                     parentActive={returnTrue}
                     whenActiveChanged={emptyFunction}
                     focus={emptyDocFunction}
+                    borderRounding={returnZero}
                     ContainingCollectionView={undefined} />
             </div>);
     }
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index cb7a67991..dc2910ede 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -12,7 +12,7 @@ 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 { emptyDocFunction, emptyFunction, returnFalse, returnZero } from "../../../Utils";
 import { Server } from "../../Server";
 import { SetupDrag } from "../../util/DragManager";
 import { CompileScript, ToField } from "../../util/Scripting";
@@ -77,6 +77,9 @@ export class CollectionSchemaView extends CollectionSubView {
             focus: emptyDocFunction,
             active: returnFalse,
             whenActiveChanged: emptyFunction,
+            borderRounding: this.props.borderRounding,
+            PanelHeight: returnZero,
+            PanelWidth: returnZero,
         };
         let contents = (
             <FieldView {...props} />
@@ -275,6 +278,7 @@ export class CollectionSchemaView extends CollectionSubView {
                         focus={emptyDocFunction}
                         parentActive={this.props.active}
                         whenActiveChanged={this.props.whenActiveChanged}
+                        borderRounding={this.props.borderRounding}
                     />
                 </div>
                 <input className="collectionSchemaView-input" value={this.previewScript} onChange={this.onPreviewScriptChange}
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index f9fc7be5a..bf59bec95 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -25,6 +25,7 @@ export interface CollectionViewProps extends FieldViewProps {
     moveDocument: (document: Document, targetCollection: Document, addDocument: (document: Document) => boolean) => boolean;
     PanelWidth: () => number;
     PanelHeight: () => number;
+    borderRounding: () => number;
 }
 
 export interface SubCollectionViewProps extends CollectionViewProps {
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index e0387f4b4..b9d1f0bd9 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -136,7 +136,10 @@ export class CollectionTreeView extends CollectionSubView {
             );
 
         return (
-            <div id="body" className="collectionTreeView-dropTarget" onWheel={(e: React.WheelEvent) => e.stopPropagation()} onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createDropTarget}>
+            <div id="body" className="collectionTreeView-dropTarget"
+                style={{ borderRadius: `${this.props.borderRounding()}px` }}
+                onWheel={(e: React.WheelEvent) => e.stopPropagation()}
+                onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createDropTarget}>
                 <div className="coll-title">
                     <EditableView
                         contents={this.props.Document.Title}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
index 57706b51e..67a0e532c 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
@@ -6,6 +6,7 @@
   width: 100%;
   height: 100%;
   transform-origin: left top;
+  pointer-events: none;
 }
 .collectionfreeformview-container {
   .collectionfreeformview > .jsx-parser {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 7492d8744..9e2c9bf9a 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -257,6 +257,7 @@ export class CollectionFreeFormView extends CollectionSubView {
             focus: this.focusDocument,
             parentActive: this.props.active,
             whenActiveChanged: this.props.active,
+            borderRounding: this.props.borderRounding,
         };
     }
 
@@ -288,11 +289,17 @@ export class CollectionFreeFormView extends CollectionSubView {
         const containerName = `collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`;
         return (
             <div className={containerName} ref={this.createDropTarget} onWheel={this.onPointerWheel}
+                style={{ borderRadius: `${this.props.borderRounding()}px` }}
                 onPointerDown={this.onPointerDown} onPointerMove={this.onCursorMove} onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} >
-                <MarqueeView container={this} activeDocuments={this.getActiveDocuments} selectDocuments={this.selectDocuments}
+                {/* <svg viewBox="0 0 180 18" style={{ top: "50%", opacity: 0.05, position: "absolute" }}>
+                    <text y="15" >
+                        {this.props.Document.Title}
+                    </text>
+                </svg> */}
+                <MarqueeView container={this} borderRadius={this.props.borderRounding} activeDocuments={this.getActiveDocuments} selectDocuments={this.selectDocuments}
                     addDocument={this.addDocument} removeDocument={this.props.removeDocument} addLiveTextDocument={this.addLiveTextBox}
                     getContainerTransform={this.getContainerTransform} getTransform={this.getTransform}>
-                    <CollectionFreeFormViewPannableContents centeringShiftX={this.centeringShiftX} centeringShiftY={this.centeringShiftY}
+                    <CollectionFreeFormViewPannableContents borderRadius={this.props.borderRounding} centeringShiftX={this.centeringShiftX} centeringShiftY={this.centeringShiftY}
                         zoomScaling={this.zoomScaling} panX={this.panX} panY={this.panY}>
                         <CollectionFreeFormLinksView {...this.props} key="freeformLinks">
                             <InkingCanvas getScreenTransform={this.getTransform} Document={this.props.Document} >
@@ -340,6 +347,7 @@ interface CollectionFreeFormViewPannableContentsProps {
     panX: () => number;
     panY: () => number;
     zoomScaling: () => number;
+    borderRadius: () => number;
 }
 
 @observer
@@ -350,7 +358,7 @@ class CollectionFreeFormViewPannableContents extends React.Component<CollectionF
         const panx = -this.props.panX();
         const pany = -this.props.panY();
         const zoom = this.props.zoomScaling();// needs to be a variable outside of the <Measure> otherwise, reactions won't fire
-        return <div className="collectionfreeformview" style={{ transform: `translate(${cenx}px, ${ceny}px) scale(${zoom}, ${zoom}) translate(${panx}px, ${pany}px)` }}>
+        return <div className="collectionfreeformview" style={{ borderRadius: `${this.props.borderRadius()}px`, transform: `translate(${cenx}px, ${ceny}px) scale(${zoom}, ${zoom}) translate(${panx}px, ${pany}px)` }}>
             {this.props.children}
         </div>;
     }
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 898fff019..e724ab47e 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -14,7 +14,6 @@ import { CollectionFreeFormView } from "./CollectionFreeFormView";
 import "./MarqueeView.scss";
 import React = require("react");
 import { Utils } from "../../../../Utils";
-import { ListField } from "../../../../fields/ListField";
 
 interface MarqueeViewProps {
     getContainerTransform: () => Transform;
@@ -25,6 +24,7 @@ interface MarqueeViewProps {
     selectDocuments: (docs: Document[]) => void;
     removeDocument: (doc: Document) => boolean;
     addLiveTextDocument: (doc: Document) => void;
+    borderRadius: () => number;
 }
 
 @observer
@@ -138,7 +138,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             this.cleanupInteractions(true);
             e.stopPropagation();
         }
-        if (e.key === "c" || e.key === "r") {
+        if (e.key === "c" || e.key === "r" || e.key === "e") {
             e.stopPropagation();
             let bounds = this.Bounds;
             let selected = this.marqueeSelect().map(d => {
@@ -156,6 +156,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                 y: bounds.top,
                 panx: 0,
                 pany: 0,
+                borderRounding: e.key === "e" ? -1 : undefined,
                 backgroundColor: selected.length ? "white" : "",
                 scale: zoomBasis,
                 width: bounds.width * zoomBasis,
@@ -250,7 +251,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
     }
 
     render() {
-        return <div className="marqueeView" onClick={this.onClick} onPointerDown={this.onPointerDown}>
+        return <div className="marqueeView" style={{ borderRadius: `${this.props.borderRadius()}px` }} onClick={this.onClick} onPointerDown={this.onPointerDown}>
             {this.props.children}
             {!this._visible ? (null) : this.marqueeDiv}
         </div>;
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 420324d40..8caf5ff31 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -65,6 +65,7 @@ export class CollectionFreeFormDocumentView extends React.Component<CollectionFr
             ScreenToLocalTransform={this.getTransform}
             PanelWidth={this.panelWidth}
             PanelHeight={this.panelHeight}
+            borderRounding={this.borderRounding}
         />;
     }
 
@@ -148,6 +149,15 @@ export class CollectionFreeFormDocumentView extends React.Component<CollectionFr
         }
     }
 
+    borderRounding = () => {
+        let br = this.props.Document.GetNumber(KeyStore.BorderRounding, 0);
+        return br >= 0 ? br :
+            this.props.Document.GetNumber(KeyStore.NativeWidth, 0) === 0 ?
+                Math.min(this.props.PanelWidth(), this.props.PanelHeight())
+                :
+                Math.min(this.props.Document.GetNumber(KeyStore.NativeWidth, 0), this.props.Document.GetNumber(KeyStore.NativeHeight, 0));
+    }
+
     render() {
         let maximizedDoc = this.props.Document.GetT(KeyStore.MaximizedDoc, Document);
         let zoomFade = 1;
@@ -168,6 +178,7 @@ export class CollectionFreeFormDocumentView extends React.Component<CollectionFr
                 onClick={this.onClick}
                 style={{
                     opacity: zoomFade,
+                    borderRadius: `${this.borderRounding()}px`,
                     transformOrigin: "left top",
                     transform: this.transform,
                     pointerEvents: (zoomFade < 0.09 ? "none" : "all"),
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index c19b0c342..ddf99c109 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -41,6 +41,7 @@ export interface DocumentViewProps {
     parentActive: () => boolean;
     whenActiveChanged: (isActive: boolean) => void;
     toggleMinimized: () => void;
+    borderRounding: () => number;
 }
 export interface JsxArgs extends DocumentViewProps {
     Keys: { [name: string]: Key };
@@ -277,6 +278,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
             <div className={`documentView-node${this.props.isTopMost ? "-topmost" : ""}`}
                 ref={this._mainCont}
                 style={{
+                    borderRadius: `${this.props.borderRounding()}px`,
                     background: this.props.Document.GetText(KeyStore.BackgroundColor, ""),
                     width: nativeWidth, height: nativeHeight,
                     transform: `scale(${scaling}, ${scaling})`
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 93e385821..8484194b0 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, emptyDocFunction, emptyFunction, returnOne } from "../../../Utils";
+import { returnFalse, emptyDocFunction, emptyFunction, returnOne, returnZero } from "../../../Utils";
 import { CollectionView } from "../collections/CollectionView";
 import { CollectionPDFView } from "../collections/CollectionPDFView";
 import { CollectionVideoView } from "../collections/CollectionVideoView";
@@ -47,6 +47,9 @@ export interface FieldViewProps {
     active: () => boolean;
     whenActiveChanged: (isActive: boolean) => void;
     focus: (doc: Document) => void;
+    PanelWidth: () => number;
+    PanelHeight: () => number;
+    borderRounding: () => number;
 }
 
 @observer
@@ -100,6 +103,8 @@ export class FieldView extends React.Component<FieldViewProps> {
                     layoutKey={KeyStore.Layout}
                     ContainingCollectionView={this.props.ContainingCollectionView}
                     parentActive={this.props.active}
+                    borderRounding={returnZero}
+                    toggleMinimized={emptyFunction}
                     whenActiveChanged={this.props.whenActiveChanged} />
             );
         }
diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss
index 5eb2bf7ce..59857bab3 100644
--- a/src/client/views/nodes/FormattedTextBox.scss
+++ b/src/client/views/nodes/FormattedTextBox.scss
@@ -22,11 +22,10 @@
   overflow-x: hidden;
   color: initial;
   height: 100%;
-  pointer-events: all;
+  pointer-events: none;
 }
 .formattedTextBox-cont-hidden {
     overflow: hidden;
-    pointer-events: none;
 }
 
 .menuicon {
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 9cd58c73a..4b2fdbaff 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -273,7 +273,10 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
         let color = this.props.Document.GetText(KeyStore.BackgroundColor, "");
         return (
             <div className={`formattedTextBox-cont-${style}`}
-                style={{ background: color }}
+                style={{
+                    borderRadius: `${this.props.borderRounding()}px`,
+                    background: color,
+                }}
                 onKeyDown={this.onKeyPress}
                 onKeyPress={this.onKeyPress}
                 onFocus={this.onFocused}
diff --git a/src/client/views/nodes/ImageBox.scss b/src/client/views/nodes/ImageBox.scss
index db9a08fba..96a724867 100644
--- a/src/client/views/nodes/ImageBox.scss
+++ b/src/client/views/nodes/ImageBox.scss
@@ -8,9 +8,6 @@
   max-height: 100%;
   pointer-events: none;
 }
-.imageBox-cont-interactive {
-    pointer-events: all;
-}
 
 .imageBox-dot {
     position:absolute;
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index a16fd5007..b22accb74 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -165,7 +165,7 @@ export class ImageBox extends React.Component<FieldViewProps> {
         let nativeWidth = this.props.Document.GetNumber(KeyStore.NativeWidth, 1);
         let interactive = InkingControl.Instance.selectedTool ? "" : "interactive"
         return (
-            <div className={`imageBox-cont-${interactive}`} onPointerDown={this.onPointerDown} onDrop={this.onDrop} ref={this.createDropTarget} onContextMenu={this.specificContextMenu}>
+            <div className="imageBox-cont" onPointerDown={this.onPointerDown} onDrop={this.onDrop} ref={this.createDropTarget} onContextMenu={this.specificContextMenu}>
                 <img src={paths[Math.min(paths.length, this._photoIndex)]} style={{ objectFit: (this._photoIndex === 0 ? undefined : "contain") }} width={nativeWidth} alt="Image not found" ref={this._imgRef} onLoad={this.onLoad} />
                 {paths.length > 1 ? this.dots(paths) : (null)}
                 {this.lightbox(paths)}
diff --git a/src/fields/KeyStore.ts b/src/fields/KeyStore.ts
index 0a96beb50..aa18a9f33 100644
--- a/src/fields/KeyStore.ts
+++ b/src/fields/KeyStore.ts
@@ -49,12 +49,13 @@ export namespace KeyStore {
     export const MinimizedDoc = new Key("MinimizedDoc");
     export const MaximizedDoc = new Key("MaximizedDoc");
     export const CopyDraggedItems = new Key("CopyDraggedItems");
+    export const BorderRounding = new Key("BorderRounding");
 
     export const KeyList: Key[] = [Prototype, X, Y, Page, Title, Author, PanX, PanY, Scale, NativeWidth, NativeHeight,
         Width, Height, ZIndex, ZoomBasis, Data, Annotations, ViewType, Layout, BackgroundColor, BackgroundLayout, OverlayLayout, LayoutKeys,
         LayoutFields, ColumnsKey, SchemaSplitPercentage, Caption, ActiveWorkspace, DocumentText, BrushingDocs, LinkedToDocs, LinkedFromDocs,
         LinkDescription, LinkTags, Thumbnail, ThumbnailPage, CurPage, AnnotationOn, NumPages, Ink, Cursors, OptionalRightCollection,
-        Archives, Workspaces, IsMinimized, MinimizedDoc, MaximizedDoc, CopyDraggedItems
+        Archives, Workspaces, IsMinimized, MinimizedDoc, MaximizedDoc, CopyDraggedItems, BorderRounding
     ];
     export function KeyLookup(keyid: string) {
         for (const key of KeyList) {
-- 
cgit v1.2.3-70-g09d2


From 6a62e0a16abc3bbadfb179750463e3d361f1c759 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Thu, 25 Apr 2019 09:15:22 -0400
Subject: silly me - borderRadius can be inherited

---
 src/client/views/Main.scss                                     |  1 +
 src/client/views/Main.tsx                                      |  1 -
 src/client/views/MainOverlayTextBox.tsx                        |  2 +-
 src/client/views/collections/CollectionBaseView.tsx            |  2 +-
 src/client/views/collections/CollectionDockingView.tsx         |  1 -
 src/client/views/collections/CollectionSchemaView.tsx          |  2 --
 src/client/views/collections/CollectionSubView.tsx             |  1 -
 src/client/views/collections/CollectionTreeView.tsx            |  2 +-
 .../collections/collectionFreeForm/CollectionFreeFormView.tsx  | 10 ++++------
 .../views/collections/collectionFreeForm/MarqueeView.tsx       |  3 +--
 src/client/views/nodes/CollectionFreeFormDocumentView.tsx      |  1 -
 src/client/views/nodes/DocumentView.tsx                        |  3 +--
 src/client/views/nodes/FieldView.tsx                           |  2 --
 src/client/views/nodes/FormattedTextBox.tsx                    |  2 +-
 14 files changed, 11 insertions(+), 22 deletions(-)

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

diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss
index 3edc79d39..2f899ff28 100644
--- a/src/client/views/Main.scss
+++ b/src/client/views/Main.scss
@@ -44,6 +44,7 @@ h1 {
 .jsx-parser {
     width:100%;
     pointer-events: none;
+    border-radius: inherit;
 }
 
 p {
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 057f68ed9..c6b3f06d8 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -197,7 +197,6 @@ export class Main extends React.Component {
                             isTopMost={true}
                             selectOnLoad={false}
                             focus={emptyDocFunction}
-                            borderRounding={returnZero}
                             parentActive={returnTrue}
                             whenActiveChanged={emptyFunction}
                             ContainingCollectionView={undefined} />}
diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx
index f98f6e8a5..be8d67925 100644
--- a/src/client/views/MainOverlayTextBox.tsx
+++ b/src/client/views/MainOverlayTextBox.tsx
@@ -97,7 +97,7 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
                     style={{ width: `${this.TextDoc.Width()}px`, height: `${this.TextDoc.Height()}px` }}>
                     <FormattedTextBox fieldKey={this._textFieldKey} isOverlay={true} Document={this.TextDoc} isSelected={returnTrue} select={emptyFunction} isTopMost={true}
                         selectOnLoad={true} ContainingCollectionView={undefined} whenActiveChanged={emptyFunction} active={returnTrue}
-                        ScreenToLocalTransform={this._textXf} borderRounding={returnZero} PanelWidth={returnZero} PanelHeight={returnZero} focus={emptyDocFunction} />
+                        ScreenToLocalTransform={this._textXf} PanelWidth={returnZero} PanelHeight={returnZero} focus={emptyDocFunction} />
                 </div>
             </ div>;
         }
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index e65770137..87b767c93 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -190,7 +190,7 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         const viewtype = this.collectionViewType;
         return (
             <div className={this.props.className || "collectionView-cont"}
-                style={{ borderRadius: `${this.props.borderRounding()}px`, pointerEvents: "all" }}
+                style={{ borderRadius: "inherit", pointerEvents: "all" }}
                 onContextMenu={this.props.onContextMenu} ref={this.props.contentRef}>
                 {viewtype !== undefined ? this.props.children(viewtype, props) : (null)}
             </div>
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index eb94a4e6d..3267f2455 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -368,7 +368,6 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
                     parentActive={returnTrue}
                     whenActiveChanged={emptyFunction}
                     focus={emptyDocFunction}
-                    borderRounding={returnZero}
                     ContainingCollectionView={undefined} />
             </div>);
     }
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index dc2910ede..b6d5f1bfa 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -77,7 +77,6 @@ export class CollectionSchemaView extends CollectionSubView {
             focus: emptyDocFunction,
             active: returnFalse,
             whenActiveChanged: emptyFunction,
-            borderRounding: this.props.borderRounding,
             PanelHeight: returnZero,
             PanelWidth: returnZero,
         };
@@ -278,7 +277,6 @@ export class CollectionSchemaView extends CollectionSubView {
                         focus={emptyDocFunction}
                         parentActive={this.props.active}
                         whenActiveChanged={this.props.whenActiveChanged}
-                        borderRounding={this.props.borderRounding}
                     />
                 </div>
                 <input className="collectionSchemaView-input" value={this.previewScript} onChange={this.onPreviewScriptChange}
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index bf59bec95..f9fc7be5a 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -25,7 +25,6 @@ export interface CollectionViewProps extends FieldViewProps {
     moveDocument: (document: Document, targetCollection: Document, addDocument: (document: Document) => boolean) => boolean;
     PanelWidth: () => number;
     PanelHeight: () => number;
-    borderRounding: () => number;
 }
 
 export interface SubCollectionViewProps extends CollectionViewProps {
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index b9d1f0bd9..905b48db7 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -137,7 +137,7 @@ export class CollectionTreeView extends CollectionSubView {
 
         return (
             <div id="body" className="collectionTreeView-dropTarget"
-                style={{ borderRadius: `${this.props.borderRounding()}px` }}
+                style={{ borderRadius: "inherit" }}
                 onWheel={(e: React.WheelEvent) => e.stopPropagation()}
                 onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createDropTarget}>
                 <div className="coll-title">
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 9e2c9bf9a..56342c84c 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -257,7 +257,6 @@ export class CollectionFreeFormView extends CollectionSubView {
             focus: this.focusDocument,
             parentActive: this.props.active,
             whenActiveChanged: this.props.active,
-            borderRounding: this.props.borderRounding,
         };
     }
 
@@ -289,17 +288,17 @@ export class CollectionFreeFormView extends CollectionSubView {
         const containerName = `collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`;
         return (
             <div className={containerName} ref={this.createDropTarget} onWheel={this.onPointerWheel}
-                style={{ borderRadius: `${this.props.borderRounding()}px` }}
+                style={{ borderRadius: "inherit" }}
                 onPointerDown={this.onPointerDown} onPointerMove={this.onCursorMove} onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} >
                 {/* <svg viewBox="0 0 180 18" style={{ top: "50%", opacity: 0.05, position: "absolute" }}>
                     <text y="15" >
                         {this.props.Document.Title}
                     </text>
                 </svg> */}
-                <MarqueeView container={this} borderRadius={this.props.borderRounding} activeDocuments={this.getActiveDocuments} selectDocuments={this.selectDocuments}
+                <MarqueeView container={this} activeDocuments={this.getActiveDocuments} selectDocuments={this.selectDocuments}
                     addDocument={this.addDocument} removeDocument={this.props.removeDocument} addLiveTextDocument={this.addLiveTextBox}
                     getContainerTransform={this.getContainerTransform} getTransform={this.getTransform}>
-                    <CollectionFreeFormViewPannableContents borderRadius={this.props.borderRounding} centeringShiftX={this.centeringShiftX} centeringShiftY={this.centeringShiftY}
+                    <CollectionFreeFormViewPannableContents centeringShiftX={this.centeringShiftX} centeringShiftY={this.centeringShiftY}
                         zoomScaling={this.zoomScaling} panX={this.panX} panY={this.panY}>
                         <CollectionFreeFormLinksView {...this.props} key="freeformLinks">
                             <InkingCanvas getScreenTransform={this.getTransform} Document={this.props.Document} >
@@ -347,7 +346,6 @@ interface CollectionFreeFormViewPannableContentsProps {
     panX: () => number;
     panY: () => number;
     zoomScaling: () => number;
-    borderRadius: () => number;
 }
 
 @observer
@@ -358,7 +356,7 @@ class CollectionFreeFormViewPannableContents extends React.Component<CollectionF
         const panx = -this.props.panX();
         const pany = -this.props.panY();
         const zoom = this.props.zoomScaling();// needs to be a variable outside of the <Measure> otherwise, reactions won't fire
-        return <div className="collectionfreeformview" style={{ borderRadius: `${this.props.borderRadius()}px`, transform: `translate(${cenx}px, ${ceny}px) scale(${zoom}, ${zoom}) translate(${panx}px, ${pany}px)` }}>
+        return <div className="collectionfreeformview" style={{ borderRadius: "inherit", transform: `translate(${cenx}px, ${ceny}px) scale(${zoom}, ${zoom}) translate(${panx}px, ${pany}px)` }}>
             {this.props.children}
         </div>;
     }
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index e724ab47e..b511a6e3d 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -24,7 +24,6 @@ interface MarqueeViewProps {
     selectDocuments: (docs: Document[]) => void;
     removeDocument: (doc: Document) => boolean;
     addLiveTextDocument: (doc: Document) => void;
-    borderRadius: () => number;
 }
 
 @observer
@@ -251,7 +250,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
     }
 
     render() {
-        return <div className="marqueeView" style={{ borderRadius: `${this.props.borderRadius()}px` }} onClick={this.onClick} onPointerDown={this.onPointerDown}>
+        return <div className="marqueeView" style={{ borderRadius: "inherit" }} onClick={this.onClick} onPointerDown={this.onPointerDown}>
             {this.props.children}
             {!this._visible ? (null) : this.marqueeDiv}
         </div>;
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 8caf5ff31..4537ce3eb 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -65,7 +65,6 @@ export class CollectionFreeFormDocumentView extends React.Component<CollectionFr
             ScreenToLocalTransform={this.getTransform}
             PanelWidth={this.panelWidth}
             PanelHeight={this.panelHeight}
-            borderRounding={this.borderRounding}
         />;
     }
 
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index ddf99c109..cec6e6468 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -41,7 +41,6 @@ export interface DocumentViewProps {
     parentActive: () => boolean;
     whenActiveChanged: (isActive: boolean) => void;
     toggleMinimized: () => void;
-    borderRounding: () => number;
 }
 export interface JsxArgs extends DocumentViewProps {
     Keys: { [name: string]: Key };
@@ -278,7 +277,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
             <div className={`documentView-node${this.props.isTopMost ? "-topmost" : ""}`}
                 ref={this._mainCont}
                 style={{
-                    borderRadius: `${this.props.borderRounding()}px`,
+                    borderRadius: "inherit",
                     background: this.props.Document.GetText(KeyStore.BackgroundColor, ""),
                     width: nativeWidth, height: nativeHeight,
                     transform: `scale(${scaling}, ${scaling})`
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 8484194b0..8f360754e 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -49,7 +49,6 @@ export interface FieldViewProps {
     focus: (doc: Document) => void;
     PanelWidth: () => number;
     PanelHeight: () => number;
-    borderRounding: () => number;
 }
 
 @observer
@@ -103,7 +102,6 @@ export class FieldView extends React.Component<FieldViewProps> {
                     layoutKey={KeyStore.Layout}
                     ContainingCollectionView={this.props.ContainingCollectionView}
                     parentActive={this.props.active}
-                    borderRounding={returnZero}
                     toggleMinimized={emptyFunction}
                     whenActiveChanged={this.props.whenActiveChanged} />
             );
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 4b2fdbaff..5b17763e7 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -274,7 +274,7 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
         return (
             <div className={`formattedTextBox-cont-${style}`}
                 style={{
-                    borderRadius: `${this.props.borderRounding()}px`,
+                    borderRadius: "inherit",
                     background: color,
                 }}
                 onKeyDown={this.onKeyPress}
-- 
cgit v1.2.3-70-g09d2


From 430dfa3afbfd38fe0db869b962da45903b888264 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Thu, 25 Apr 2019 11:55:59 -0400
Subject: more event fixing.  got rid of text box padding.

---
 src/client/views/collections/collectionFreeForm/MarqueeView.tsx | 1 -
 src/client/views/nodes/DocumentView.tsx                         | 2 +-
 src/client/views/nodes/FormattedTextBox.scss                    | 4 ++--
 src/client/views/nodes/FormattedTextBox.tsx                     | 4 +++-
 src/client/views/nodes/ImageBox.scss                            | 3 +++
 src/client/views/nodes/ImageBox.tsx                             | 4 ++--
 6 files changed, 11 insertions(+), 7 deletions(-)

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

diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index b511a6e3d..c6681e014 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -63,7 +63,6 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             document.addEventListener("pointermove", this.onPointerMove, true);
             document.addEventListener("pointerup", this.onPointerUp, true);
             document.addEventListener("keydown", this.marqueeCommand, true);
-            e.stopPropagation();
         }
         if (e.altKey)
             e.preventDefault();
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index cec6e6468..aaedd5b1c 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -179,7 +179,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
             if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) {
                 document.removeEventListener("pointermove", this.onPointerMove);
                 document.removeEventListener("pointerup", this.onPointerUp);
-                if (!e.altKey && (!this.topMost || e.buttons === 2)) {
+                if (!e.altKey && !this.topMost && (!CollectionFreeFormView.RIGHT_BTN_DRAG && e.buttons === 1) || (CollectionFreeFormView.RIGHT_BTN_DRAG && e.buttons === 2)) {
                     this.startDragging(this._downX, this._downY, e.ctrlKey || e.altKey);
                 }
             }
diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss
index 5eb2bf7ce..f4f37250f 100644
--- a/src/client/views/nodes/FormattedTextBox.scss
+++ b/src/client/views/nodes/FormattedTextBox.scss
@@ -12,9 +12,9 @@
 
 .formattedTextBox-cont-scroll, .formattedTextBox-cont-hidden {
   background: $light-color-secondary;
-  padding: 0.9em;
+  padding: 0;
   border-width: 0px;
-  border-radius: $border-radius;
+  border-radius: inherit;
   border-color: $intermediate-color;
   box-sizing: border-box;
   border-style: solid;
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 5b17763e7..4e841af98 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -21,6 +21,7 @@ import "./FormattedTextBox.scss";
 import React = require("react");
 import { SelectionManager } from "../../util/SelectionManager";
 import { observer } from "mobx-react";
+import { InkingControl } from "../InkingControl";
 const { buildMenuItems } = require("prosemirror-example-setup");
 const { menuBar } = require("prosemirror-menu");
 
@@ -271,10 +272,11 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
     render() {
         let style = this.props.isOverlay ? "scroll" : "hidden";
         let color = this.props.Document.GetText(KeyStore.BackgroundColor, "");
+        let interactive = InkingControl.Instance.selectedTool ? "" : "interactive";
         return (
             <div className={`formattedTextBox-cont-${style}`}
                 style={{
-                    borderRadius: "inherit",
+                    pointerEvents: interactive ? "all" : "none",
                     background: color,
                 }}
                 onKeyDown={this.onKeyPress}
diff --git a/src/client/views/nodes/ImageBox.scss b/src/client/views/nodes/ImageBox.scss
index 96a724867..9fe211df0 100644
--- a/src/client/views/nodes/ImageBox.scss
+++ b/src/client/views/nodes/ImageBox.scss
@@ -8,6 +8,9 @@
   max-height: 100%;
   pointer-events: none;
 }
+.imageBox-cont-interactive {
+  pointer-events: all;
+}
 
 .imageBox-dot {
     position:absolute;
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index b22accb74..2cbb0fa90 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -163,9 +163,9 @@ export class ImageBox extends React.Component<FieldViewProps> {
         else if (field instanceof ImageField) paths = [field.Data.href];
         else if (field instanceof ListField) paths = field.Data.filter(val => val as ImageField).map(p => (p as ImageField).Data.href);
         let nativeWidth = this.props.Document.GetNumber(KeyStore.NativeWidth, 1);
-        let interactive = InkingControl.Instance.selectedTool ? "" : "interactive"
+        let interactive = InkingControl.Instance.selectedTool ? "" : "-interactive";
         return (
-            <div className="imageBox-cont" onPointerDown={this.onPointerDown} onDrop={this.onDrop} ref={this.createDropTarget} onContextMenu={this.specificContextMenu}>
+            <div className={`imageBox-cont${interactive}`} onPointerDown={this.onPointerDown} onDrop={this.onDrop} ref={this.createDropTarget} onContextMenu={this.specificContextMenu}>
                 <img src={paths[Math.min(paths.length, this._photoIndex)]} style={{ objectFit: (this._photoIndex === 0 ? undefined : "contain") }} width={nativeWidth} alt="Image not found" ref={this._imgRef} onLoad={this.onLoad} />
                 {paths.length > 1 ? this.dots(paths) : (null)}
                 {this.lightbox(paths)}
-- 
cgit v1.2.3-70-g09d2


From 96b1e27da348e47a4d5c83b182a5f55e96e3218e Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Fri, 26 Apr 2019 08:41:53 -0400
Subject: fixed keyboard modifier to not create document.  cleaned up videobox
 render.

---
 src/client/views/PreviewCursor.tsx          |  9 ++++-----
 src/client/views/nodes/FormattedTextBox.tsx |  2 +-
 src/client/views/nodes/VideoBox.tsx         | 19 ++++++++++---------
 3 files changed, 15 insertions(+), 15 deletions(-)

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

diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx
index 744ec0535..2e63f751b 100644
--- a/src/client/views/PreviewCursor.tsx
+++ b/src/client/views/PreviewCursor.tsx
@@ -26,12 +26,11 @@ export class PreviewCursor extends React.Component<{}> {
         // 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) {
-            PreviewCursor.Visible && PreviewCursor._onKeyPress && PreviewCursor._onKeyPress(e);
-            PreviewCursor.Visible = false;
-        } else if (e.ctrlKey) {
-            if (e.key == "v") {
+        if (e.key.startsWith("F") && !e.key.endsWith("F")) {
+        } else if (e.key != "Alt" && e.key != "Shift" && e.key != "Meta" && e.key != "Control" && !e.defaultPrevented && !(e as any).DASHFormattedTextBoxHandled) {
+            if ((!e.ctrlKey && !e.metaKey) || e.key === "v") {
                 PreviewCursor.Visible && PreviewCursor._onKeyPress && PreviewCursor._onKeyPress(e);
+                PreviewCursor.Visible = false;
             }
         }
     }
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 4e841af98..8fb86f320 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -259,7 +259,7 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
             SelectionManager.DeselectAll();
         }
         e.stopPropagation();
-        if (e.keyCode === 9) e.preventDefault();
+        if (e.key === "Tab") e.preventDefault();
         // stop propagation doesn't seem to stop propagation of native keyboard events.
         // so we set a flag on the native event that marks that the event's been handled.
         (e.nativeEvent as any).DASHFormattedTextBoxHandled = true;
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 1e6bc58c9..019e5e489 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -53,25 +53,26 @@ export class VideoBox extends React.Component<FieldViewProps> {
             (vref as any).AHackBecauseSomethingResetsTheVideoToZero = this.curPage;
         }
     }
+    videoContent(path: string) {
+        return <video className="videobox-cont" ref={this.setVideoRef}>
+            <source src={path} type="video/mp4" />
+            Not supported.
+    </video>;
+    }
 
     render() {
         let field = this.props.Document.GetT(this.props.fieldKey, VideoField);
         if (!field || field === FieldWaiting) {
             return <div>Loading</div>;
         }
-        let path = field.Data.href;
-        trace();
-        return (
+        return (this.props.Document.GetNumber(KeyStore.NativeHeight, 0)) ?
+            this.videoContent(field.data.href) :
             <Measure onResize={this.setScaling}>
                 {({ measureRef }) =>
                     <div style={{ width: "100%", height: "auto" }} ref={measureRef}>
-                        <video className="videobox-cont" ref={this.setVideoRef}>
-                            <source src={path} type="video/mp4" />
-                            Not supported.
-                        </video>
+                        {this.videoContent(field.data.href)}
                     </div>
                 }
-            </Measure>
-        );
+            </Measure>;
     }
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From b2d9133f2fdb6dd2af3b74c4dd9de49145611b1b Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Fri, 26 Apr 2019 22:08:20 -0400
Subject: fixed previewcursor appearing on select. adjusted rounded border
 text.

---
 src/client/views/PreviewCursor.tsx                            |  2 +-
 .../collections/collectionFreeForm/CollectionFreeFormView.tsx |  2 +-
 .../views/collections/collectionFreeForm/MarqueeView.tsx      |  6 +++++-
 src/client/views/nodes/DocumentView.tsx                       |  1 +
 src/client/views/nodes/FormattedTextBox.scss                  | 11 ++++++++++-
 src/client/views/nodes/FormattedTextBox.tsx                   | 11 +++++++----
 6 files changed, 25 insertions(+), 8 deletions(-)

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

diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx
index 2e63f751b..4359ba093 100644
--- a/src/client/views/PreviewCursor.tsx
+++ b/src/client/views/PreviewCursor.tsx
@@ -27,7 +27,7 @@ export class PreviewCursor extends React.Component<{}> {
         // the keyPress here.
         //if not these keys, make a textbox if preview cursor is active!
         if (e.key.startsWith("F") && !e.key.endsWith("F")) {
-        } else if (e.key != "Alt" && e.key != "Shift" && e.key != "Meta" && e.key != "Control" && !e.defaultPrevented && !(e as any).DASHFormattedTextBoxHandled) {
+        } else if (e.key != "Escape" && e.key != "Alt" && e.key != "Shift" && e.key != "Meta" && e.key != "Control" && !e.defaultPrevented && !(e as any).DASHFormattedTextBoxHandled) {
             if ((!e.ctrlKey && !e.metaKey) || e.key === "v") {
                 PreviewCursor.Visible && PreviewCursor._onKeyPress && PreviewCursor._onKeyPress(e);
                 PreviewCursor.Visible = false;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 405594eb1..1a953006a 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -295,7 +295,7 @@ export class CollectionFreeFormView extends CollectionSubView {
                         {this.props.Document.Title}
                     </text>
                 </svg> */}
-                <MarqueeView container={this} activeDocuments={this.getActiveDocuments} selectDocuments={this.selectDocuments}
+                <MarqueeView container={this} activeDocuments={this.getActiveDocuments} selectDocuments={this.selectDocuments} isSelected={this.props.isSelected}
                     addDocument={this.addDocument} removeDocument={this.props.removeDocument} addLiveTextDocument={this.addLiveTextBox}
                     getContainerTransform={this.getContainerTransform} getTransform={this.getTransform}>
                     <CollectionFreeFormViewPannableContents centeringShiftX={this.centeringShiftX} centeringShiftY={this.centeringShiftY}
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index c6681e014..0e2ac0a80 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -24,6 +24,7 @@ interface MarqueeViewProps {
     selectDocuments: (docs: Document[]) => void;
     removeDocument: (doc: Document) => boolean;
     addLiveTextDocument: (doc: Document) => void;
+    isSelected: () => boolean;
 }
 
 @observer
@@ -102,7 +103,9 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
     onClick = (e: React.MouseEvent): void => {
         if (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD &&
             Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD) {
-            PreviewCursor.Show(e.clientX, e.clientY, this.onKeyPress);
+            if (this.props.isSelected()) {
+                PreviewCursor.Show(e.clientX, e.clientY, this.onKeyPress);
+            }
             // let the DocumentView stopPropagation of this event when it selects this document
         } else {  // why do we get a click event when the cursor have moved a big distance?
             // let's cut it off here so no one else has to deal with it.
@@ -137,6 +140,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             e.stopPropagation();
         }
         if (e.key === "c" || e.key === "r" || e.key === "e") {
+            console.log("DO MARQUEE");
             e.stopPropagation();
             let bounds = this.Bounds;
             let selected = this.marqueeSelect().map(d => {
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index aaedd5b1c..3d6e0c4d8 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -172,6 +172,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
             document.removeEventListener("pointerup", this.onPointerUp);
             document.addEventListener("pointerup", this.onPointerUp);
             e.preventDefault();
+            e.stopPropagation();
         }
     }
     onPointerMove = (e: PointerEvent): void => {
diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss
index f4f37250f..727d3c0b2 100644
--- a/src/client/views/nodes/FormattedTextBox.scss
+++ b/src/client/views/nodes/FormattedTextBox.scss
@@ -10,7 +10,7 @@
   outline: none !important;
 }
 
-.formattedTextBox-cont-scroll, .formattedTextBox-cont-hidden {
+.formattedTextBox-cont-scroll, .formattedTextBox-cont-hidden  {
   background: $light-color-secondary;
   padding: 0;
   border-width: 0px;
@@ -24,10 +24,19 @@
   height: 100%;
   pointer-events: all;
 }
+
 .formattedTextBox-cont-hidden {
     overflow: hidden;
     pointer-events: none;
 }
+.formattedTextBox-inner-rounded {
+    height: calc(100% - 40px);
+    width: calc(100% - 40px);
+    position: absolute;
+    overflow: scroll;
+    top: 20;
+    left: 20;
+}
 
 .menuicon {
   display: inline-block;
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 8fb86f320..02d98de6b 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -270,11 +270,12 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
         };
     }
     render() {
-        let style = this.props.isOverlay ? "scroll" : "hidden";
+        let style = this.props.isOverlay ? "-scroll" : "-hidden";
+        let rounded = this.props.Document.GetNumber(KeyStore.BorderRounding, 0) < 0 ? "-rounded" : "";
         let color = this.props.Document.GetText(KeyStore.BackgroundColor, "");
-        let interactive = InkingControl.Instance.selectedTool ? "" : "interactive";
+        let interactive = InkingControl.Instance.selectedTool ? "" : "-interactive";
         return (
-            <div className={`formattedTextBox-cont-${style}`}
+            <div className={`formattedTextBox-cont${style}`}
                 style={{
                     pointerEvents: interactive ? "all" : "none",
                     background: color,
@@ -288,7 +289,9 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
                 onContextMenu={this.specificContextMenu}
                 // tfs: do we need this event handler
                 onWheel={this.onPointerWheel}
-                ref={this._ref} />
+            >
+                <div className={`formattedTextBox-inner${rounded}`} ref={this._ref} />
+            </div>
         );
     }
 }
-- 
cgit v1.2.3-70-g09d2


From 7a820b3b175ea52712927e75ce16e32f0ed3a131 Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Sat, 27 Apr 2019 19:51:58 -0400
Subject: Compiling

---
 src/client/util/DragManager.ts                     |  8 +++----
 src/client/views/MainOverlayTextBox.tsx            | 17 +++++++-------
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  2 +-
 src/client/views/nodes/FormattedTextBox.tsx        | 17 ++++++--------
 src/fields/RichTextField.ts                        | 26 ----------------------
 src/new_fields/RichTextField.ts                    | 12 ++++++++++
 src/new_fields/Types.ts                            | 14 ++++++------
 7 files changed, 39 insertions(+), 57 deletions(-)
 delete mode 100644 src/fields/RichTextField.ts
 create mode 100644 src/new_fields/RichTextField.ts

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

diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 0174b2f54..e65f2b9ed 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -158,13 +158,13 @@ export namespace DragManager {
     }
 
     export class LinkDragData {
-        constructor(linkSourceDoc: Document, blacklist: Document[] = []) {
+        constructor(linkSourceDoc: Doc, blacklist: Doc[] = []) {
             this.linkSourceDocument = linkSourceDoc;
             this.blacklist = blacklist;
         }
-        droppedDocuments: Document[] = [];
-        linkSourceDocument: Document;
-        blacklist: Document[];
+        droppedDocuments: Doc[] = [];
+        linkSourceDocument: Doc;
+        blacklist: Doc[];
         [id: string]: any;
     }
 
diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx
index be8d67925..a7ced36bf 100644
--- a/src/client/views/MainOverlayTextBox.tsx
+++ b/src/client/views/MainOverlayTextBox.tsx
@@ -2,16 +2,15 @@ import { action, observable, trace } from 'mobx';
 import { observer } from 'mobx-react';
 import "normalize.css";
 import * as React from 'react';
-import { Document } from '../../fields/Document';
-import { Key } from '../../fields/Key';
-import { KeyStore } from '../../fields/KeyStore';
-import { emptyDocFunction, emptyFunction, returnTrue, returnZero } from '../../Utils';
+import { emptyFunction, returnTrue, returnZero } from '../../Utils';
 import '../northstar/model/ModelExtensions';
 import '../northstar/utils/Extensions';
 import { DragManager } from '../util/DragManager';
 import { Transform } from '../util/Transform';
 import "./MainOverlayTextBox.scss";
 import { FormattedTextBox } from './nodes/FormattedTextBox';
+import { Doc } from '../../new_fields/Doc';
+import { NumCast } from '../../new_fields/Types';
 
 interface MainOverlayTextBoxProps {
 }
@@ -19,11 +18,11 @@ interface MainOverlayTextBoxProps {
 @observer
 export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps> {
     public static Instance: MainOverlayTextBox;
-    @observable public TextDoc?: Document = undefined;
+    @observable public TextDoc?: Doc = undefined;
     public TextScroll: number = 0;
     @observable _textRect: any;
     @observable _textXf: () => Transform = () => Transform.Identity();
-    private _textFieldKey: Key = KeyStore.Data;
+    private _textFieldKey: string = "data";
     private _textColor: string | null = null;
     private _textTargetDiv: HTMLDivElement | undefined;
     private _textProxyDiv: React.RefObject<HTMLDivElement>;
@@ -35,7 +34,7 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
     }
 
     @action
-    SetTextDoc(textDoc?: Document, textFieldKey?: Key, div?: HTMLDivElement, tx?: () => Transform) {
+    SetTextDoc(textDoc?: Doc, textFieldKey?: string, div?: HTMLDivElement, tx?: () => Transform) {
         if (this._textTargetDiv) {
             this._textTargetDiv.style.color = this._textColor;
         }
@@ -94,10 +93,10 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
             let s = 1 / this._textXf().Scale;
             return <div className="mainOverlayTextBox-textInput" style={{ transform: `translate(${pt[0]}px, ${pt[1]}px) scale(${s},${s})`, width: "auto", height: "auto" }} >
                 <div className="mainOverlayTextBox-textInput" onPointerDown={this.textBoxDown} ref={this._textProxyDiv} onScroll={this.textScroll}
-                    style={{ width: `${this.TextDoc.Width()}px`, height: `${this.TextDoc.Height()}px` }}>
+                    style={{ width: `${NumCast(this.TextDoc.width)}px`, height: `${NumCast(this.TextDoc.height)}px` }}>
                     <FormattedTextBox fieldKey={this._textFieldKey} isOverlay={true} Document={this.TextDoc} isSelected={returnTrue} select={emptyFunction} isTopMost={true}
                         selectOnLoad={true} ContainingCollectionView={undefined} whenActiveChanged={emptyFunction} active={returnTrue}
-                        ScreenToLocalTransform={this._textXf} PanelWidth={returnZero} PanelHeight={returnZero} focus={emptyDocFunction} />
+                        ScreenToLocalTransform={this._textXf} PanelWidth={returnZero} PanelHeight={returnZero} focus={emptyFunction} />
                 </div>
             </ div>;
         }
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 80900c450..047fbad18 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -97,7 +97,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
                     if (!NumCast(d.height)) {
                         let nw = NumCast(d.nativeWidth);
                         let nh = NumCast(d.nativeHeight);
-                        d.height = nw && nh ? nh / nw * d.Width() : 300;
+                        d.height = nw && nh ? nh / nw * NumCast(d.Width) : 300;
                     }
                     this.bringToFront(d);
                 });
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index c65b1ac89..7a85c9dd3 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -20,7 +20,8 @@ import { createSchema, makeInterface } from "../../../new_fields/Schema";
 import { Opt, Doc } from "../../../new_fields/Doc";
 import { observer } from "mobx-react";
 import { InkingControl } from "../InkingControl";
-import { StrCast } from "../../../new_fields/Types";
+import { StrCast, Cast } from "../../../new_fields/Types";
+import { RichTextField } from "../../../new_fields/RichTextField";
 const { buildMenuItems } = require("prosemirror-example-setup");
 const { menuBar } = require("prosemirror-menu");
 
@@ -77,11 +78,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
             const state = this._editorView.state.apply(tx);
             this._editorView.updateState(state);
             this._applyingChange = true;
-            this.props.Document.SetDataOnPrototype(
-                this.props.fieldKey,
-                JSON.stringify(state.toJSON()),
-                RichTextField
-            );
+            Doc.SetOnPrototype(this.props.Document, this.props.fieldKey, new RichTextField(JSON.stringify(state.toJSON())));
             Doc.SetOnPrototype(this.props.Document, "documentText", state.doc.textBetween(0, state.doc.content.size, "\n\n"));
             this._applyingChange = false;
             // doc.SetData(fieldKey, JSON.stringify(state.toJSON()), RichTextField);
@@ -127,8 +124,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
 
         this._reactionDisposer = reaction(
             () => {
-                const field = this.props.Document ? this.props.Document.GetT(this.props.fieldKey, RichTextField) : undefined;
-                return field && field !== FieldWaiting ? field.Data : undefined;
+                const field = this.props.Document ? Cast(this.props.Document[this.props.fieldKey], RichTextField) : undefined;
+                return field ? field.Data : undefined;
             },
             field => field && this._editorView && !this._applyingChange &&
                 this._editorView.updateState(EditorState.fromJSON(config, JSON.parse(field)))
@@ -136,8 +133,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
         this.setupEditor(config, this.props.Document);
     }
 
-    private setupEditor(config: any, doc?: Document) {
-        let field = doc ? doc.GetT(this.props.fieldKey, RichTextField) : undefined;
+    private setupEditor(config: any, doc?: Doc) {
+        let field = doc ? Cast(doc[this.props.fieldKey], RichTextField) : undefined;
         if (this._ref.current) {
             this._editorView = new EditorView(this._ref.current, {
                 state: field && field.Data ? EditorState.fromJSON(config, JSON.parse(field.Data)) : EditorState.create(config),
diff --git a/src/fields/RichTextField.ts b/src/fields/RichTextField.ts
deleted file mode 100644
index f53f48ca6..000000000
--- a/src/fields/RichTextField.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { BasicField } from "./BasicField";
-import { Types } from "../server/Message";
-import { FieldId } from "./Field";
-
-export class RichTextField extends BasicField<string> {
-    constructor(data: string = "", id?: FieldId, save: boolean = true) {
-        super(data, save, id);
-    }
-
-    ToScriptString(): string {
-        return `new RichTextField(${this.Data})`;
-    }
-
-    Copy() {
-        return new RichTextField(this.Data);
-    }
-
-    ToJson() {
-        return {
-            type: Types.RichText,
-            data: this.Data,
-            id: this.Id
-        };
-    }
-
-}
\ No newline at end of file
diff --git a/src/new_fields/RichTextField.ts b/src/new_fields/RichTextField.ts
new file mode 100644
index 000000000..156e4efd9
--- /dev/null
+++ b/src/new_fields/RichTextField.ts
@@ -0,0 +1,12 @@
+import { ObjectField } from "./Doc";
+import { serializable } from "serializr";
+
+export class RichTextField extends ObjectField {
+    @serializable(true)
+    readonly Data: string;
+
+    constructor(data: string) {
+        super();
+        this.Data = data;
+    }
+}
\ No newline at end of file
diff --git a/src/new_fields/Types.ts b/src/new_fields/Types.ts
index 4808d6e46..7fa18673f 100644
--- a/src/new_fields/Types.ts
+++ b/src/new_fields/Types.ts
@@ -38,10 +38,10 @@ export interface Interface {
 }
 
 export function Cast<T extends ToConstructor<Field> | ListSpec<Field>>(field: FieldResult, ctor: T): FieldResult<ToType<T>>;
-export function Cast<T extends ToConstructor<Field> | ListSpec<Field>>(field: FieldResult, ctor: T, defaultVal: WithoutList<ToType<T>>): WithoutList<ToType<T>>;
-export function Cast<T extends ToConstructor<Field> | ListSpec<Field>>(field: FieldResult, ctor: T, defaultVal?: ToType<T>): FieldResult<ToType<T>> | undefined {
+export function Cast<T extends ToConstructor<Field> | ListSpec<Field>>(field: FieldResult, ctor: T, defaultVal: WithoutList<ToType<T>> | null): WithoutList<ToType<T>>;
+export function Cast<T extends ToConstructor<Field> | ListSpec<Field>>(field: FieldResult, ctor: T, defaultVal?: ToType<T> | null): FieldResult<ToType<T>> | undefined {
     if (field instanceof Promise) {
-        return defaultVal === undefined ? field.then(f => Cast(f, ctor) as any) as any : defaultVal;
+        return defaultVal === undefined ? field.then(f => Cast(f, ctor) as any) as any : defaultVal === null ? undefined : defaultVal;
     }
     if (field !== undefined && !(field instanceof Promise)) {
         if (typeof ctor === "string") {
@@ -56,18 +56,18 @@ export function Cast<T extends ToConstructor<Field> | ListSpec<Field>>(field: Fi
             return field as ToType<T>;
         }
     }
-    return defaultVal;
+    return defaultVal === null ? undefined : defaultVal;
 }
 
-export function NumCast(field: FieldResult, defaultVal: Opt<number> = 0) {
+export function NumCast(field: FieldResult, defaultVal: number | null = 0) {
     return Cast(field, "number", defaultVal);
 }
 
-export function StrCast(field: FieldResult, defaultVal: Opt<string> = "") {
+export function StrCast(field: FieldResult, defaultVal: string | null = "") {
     return Cast(field, "string", defaultVal);
 }
 
-export function BoolCast(field: FieldResult, defaultVal: Opt<boolean> = undefined) {
+export function BoolCast(field: FieldResult, defaultVal: boolean | null = null) {
     return Cast(field, "boolean", defaultVal);
 }
 
-- 
cgit v1.2.3-70-g09d2


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

---
 src/client/util/DragManager.ts              |  32 ++++----
 src/client/views/DocumentDecorations.tsx    | 116 ++++++++++++++--------------
 src/client/views/nodes/FormattedTextBox.tsx |   4 +-
 3 files changed, 77 insertions(+), 75 deletions(-)

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

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


From 506af03831bf3cc002f93ad8708eafb909c0a194 Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Sat, 27 Apr 2019 22:27:26 -0400
Subject: Various fixes

---
 src/client/DocServer.ts                            | 24 ++++++++++++++++++----
 src/client/documents/Documents.ts                  |  2 +-
 src/client/northstar/dash-nodes/HistogramBox.tsx   |  2 +-
 src/client/views/collections/CollectionPDFView.tsx |  2 +-
 src/client/views/collections/CollectionSubView.tsx |  1 +
 .../views/collections/CollectionVideoView.tsx      |  2 +-
 src/client/views/collections/CollectionView.tsx    |  2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  2 +-
 src/client/views/nodes/FieldView.tsx               |  4 ++--
 src/client/views/nodes/FormattedTextBox.tsx        |  2 +-
 src/client/views/nodes/KeyValueBox.tsx             |  2 +-
 src/new_fields/util.ts                             |  5 +++--
 src/server/database.ts                             | 21 +++++++++++++------
 src/server/index.ts                                | 10 +++++----
 14 files changed, 55 insertions(+), 26 deletions(-)

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

diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts
index c7cbfce37..07997f072 100644
--- a/src/client/DocServer.ts
+++ b/src/client/DocServer.ts
@@ -55,12 +55,28 @@ export namespace DocServer {
                 map[id] = cached;
             }
         }
-        const prom = Utils.EmitCallback(_socket, MessageStore.GetFields, requestedIds);
-        requestedIds.map((id, index) => _cache[id] = prom.then((fields: RefField[]) => fields[index]));
+        const prom = Utils.EmitCallback(_socket, MessageStore.GetRefFields, requestedIds).then(fields => {
+            for (const key in fields) {
+                const field = fields[key];
+                if (field) {
+                    fields[key] = SerializationHelper.Deserialize(field);
+                }
+            }
+            return fields;
+        });
+        requestedIds.forEach((id, index) => _cache[id] = prom.then((fields: RefField[]) => fields[index]));
         const fields = await prom;
-        requestedIds.map((id, index) => map[id] = fields[index]);
+        requestedIds.forEach((id, index) => {
+            const field = fields[index];
+            if (field) {
+                _cache[id] = field;
+            } else {
+                delete _cache[id];
+            }
+            map[id] = field;
+        });
         const otherFields = await Promise.all(promises);
-        waitingIds.map((id, index) => map[id] = otherFields[index]);
+        waitingIds.forEach((id, index) => map[id] = otherFields[index]);
         return map;
     }
 
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index c30fb21d5..2a9687bda 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -138,7 +138,7 @@ export namespace Docs {
         return webProto;
     }
     function CreateCollectionPrototype(): Doc {
-        let collProto = setupPrototypeOptions(collProtoId, "COLLECTION_PROTO", CollectionView.LayoutString("DataKey"),
+        let collProto = setupPrototypeOptions(collProtoId, "COLLECTION_PROTO", CollectionView.LayoutString("data"),
             { panX: 0, panY: 0, scale: 1, width: 500, height: 500 });
         return collProto;
     }
diff --git a/src/client/northstar/dash-nodes/HistogramBox.tsx b/src/client/northstar/dash-nodes/HistogramBox.tsx
index a9c68ccba..19d108676 100644
--- a/src/client/northstar/dash-nodes/HistogramBox.tsx
+++ b/src/client/northstar/dash-nodes/HistogramBox.tsx
@@ -26,7 +26,7 @@ import { Id } from "../../../new_fields/RefField";
 
 @observer
 export class HistogramBox extends React.Component<FieldViewProps> {
-    public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(HistogramBox, fieldStr); }
+    public static LayoutString(fieldStr: string = "data") { return FieldView.LayoutString(HistogramBox, fieldStr); }
     private _dropXRef = React.createRef<HTMLDivElement>();
     private _dropYRef = React.createRef<HTMLDivElement>();
     private _dropXDisposer?: DragManager.DragDropDisposer;
diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx
index e73b7b4a6..99438b4e8 100644
--- a/src/client/views/collections/CollectionPDFView.tsx
+++ b/src/client/views/collections/CollectionPDFView.tsx
@@ -13,7 +13,7 @@ import { NumCast } from "../../../new_fields/Types";
 @observer
 export class CollectionPDFView extends React.Component<FieldViewProps> {
 
-    public static LayoutString(fieldKey: string = "DataKey") {
+    public static LayoutString(fieldKey: string = "data") {
         return FieldView.LayoutString(CollectionPDFView, fieldKey);
     }
 
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 4d090b680..2c2d74302 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -53,6 +53,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
 
         @action
         protected async setCursorPosition(position: [number, number]) {
+            return;
             let ind;
             let doc = this.props.Document;
             let id = CurrentUserUtils.id;
diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index d314e3fc0..d45be228a 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -18,7 +18,7 @@ export class CollectionVideoView extends React.Component<FieldViewProps> {
     @observable _currentTimecode: number = 0;
     @observable _isPlaying: boolean = false;
 
-    public static LayoutString(fieldKey: string = "DataKey") {
+    public static LayoutString(fieldKey: string = "data") {
         return FieldView.LayoutString(CollectionVideoView, fieldKey);
     }
     private get uIButtons() {
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index e7bf1e121..b72065bca 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -13,7 +13,7 @@ import { trace } from 'mobx';
 
 @observer
 export class CollectionView extends React.Component<FieldViewProps> {
-    public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(CollectionView, fieldStr); }
+    public static LayoutString(fieldStr: string = "data") { return FieldView.LayoutString(CollectionView, fieldStr); }
 
     private SubView = (type: CollectionViewType, renderProps: CollectionRenderProps) => {
         let props = { ...this.props, ...renderProps };
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 18107e98a..dfacca204 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -314,7 +314,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
                                 {this.childViews}
                             </InkingCanvas>
                         </CollectionFreeFormLinksView>
-                        <CollectionFreeFormRemoteCursors {...this.props} key="remoteCursors" />
+                        {/* <CollectionFreeFormRemoteCursors {...this.props} key="remoteCursors" /> */}
                     </CollectionFreeFormViewPannableContents>
                     <CollectionFreeFormOverlayView {...this.getDocumentViewProps(this.props.Document)} />
                 </MarqueeView>
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index dc36c5914..df76f7cea 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -45,8 +45,8 @@ export interface FieldViewProps {
 
 @observer
 export class FieldView extends React.Component<FieldViewProps> {
-    public static LayoutString(fieldType: { name: string }, fieldStr: string = "DataKey") {
-        return `<${fieldType.name} {...props} fieldKey={${fieldStr}} />`;
+    public static LayoutString(fieldType: { name: string }, fieldStr: string = "data") {
+        return `<${fieldType.name} {...props} fieldKey={"${fieldStr}"} />`;
     }
 
     @computed
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 7a85c9dd3..96512718f 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -55,7 +55,7 @@ const RichTextDocument = makeInterface(richTextSchema);
 
 @observer
 export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTextBoxOverlay), RichTextDocument>(RichTextDocument) {
-    public static LayoutString(fieldStr: string = "DataKey") {
+    public static LayoutString(fieldStr: string = "data") {
         return FieldView.LayoutString(FormattedTextBox, fieldStr);
     }
     private _ref: React.RefObject<HTMLDivElement>;
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index ae39ebe2d..876a3c173 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -14,7 +14,7 @@ import { Doc, IsField } from "../../../new_fields/Doc";
 export class KeyValueBox extends React.Component<FieldViewProps> {
     private _mainCont = React.createRef<HTMLDivElement>();
 
-    public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(KeyValueBox, fieldStr); }
+    public static LayoutString(fieldStr: string = "data") { return FieldView.LayoutString(KeyValueBox, fieldStr); }
     @observable private _keyInput: string = "";
     @observable private _valueInput: string = "";
     @computed get splitPercentage() { return NumCast(this.props.Document.schemaSplitPercentage, 50); }
diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts
index 011e8c8d9..b2299f34a 100644
--- a/src/new_fields/util.ts
+++ b/src/new_fields/util.ts
@@ -5,8 +5,9 @@ import { ProxyField } from "./Proxy";
 import { FieldValue } from "./Types";
 import { RefField, Id } from "./RefField";
 import { ObjectField, Parent, OnUpdate } from "./ObjectField";
+import { action } from "mobx";
 
-export function setter(target: any, prop: string | symbol | number, value: any, receiver: any): boolean {
+export const setter = action(function (target: any, prop: string | symbol | number, value: any, receiver: any): boolean {
     if (SerializationHelper.IsSerializing()) {
         target[prop] = value;
         return true;
@@ -46,7 +47,7 @@ export function setter(target: any, prop: string | symbol | number, value: any,
         undo: () => receiver[prop] = curValue
     });
     return true;
-}
+});
 
 export function getter(target: any, prop: string | symbol | number, receiver: any): any {
     if (typeof prop === "symbol") {
diff --git a/src/server/database.ts b/src/server/database.ts
index 6b3b6797f..4775c0eeb 100644
--- a/src/server/database.ts
+++ b/src/server/database.ts
@@ -60,19 +60,28 @@ export class Database {
     }
 
     public getDocument(id: string, fn: (result?: Transferable) => void, collectionName = Database.DocumentsCollection) {
-        console.log("getDocument");
-        this.db && this.db.collection(collectionName).findOne({ id: id }, (err, result) =>
-            fn(result ? ({ id: result._id, type: result.type, data: result.data }) : undefined));
+        this.db && this.db.collection(collectionName).findOne({ _id: id }, (err, result) => {
+            if (result) {
+                result.id = result._id;
+                delete result._id;
+                fn(result);
+            } else {
+                fn(undefined);
+            }
+        });
     }
 
     public getDocuments(ids: string[], fn: (result: Transferable[]) => void, collectionName = Database.DocumentsCollection) {
-        console.log("getDocuments");
-        this.db && this.db.collection(collectionName).find({ id: { "$in": ids } }).toArray((err, docs) => {
+        this.db && this.db.collection(collectionName).find({ _id: { "$in": ids } }).toArray((err, docs) => {
             if (err) {
                 console.log(err.message);
                 console.log(err.errmsg);
             }
-            fn(docs.map(doc => ({ id: doc._id, type: doc.type, data: doc.data })));
+            fn(docs.map(doc => {
+                doc.id = doc._id;
+                delete doc._id;
+                return doc;
+            }));
         });
     }
 
diff --git a/src/server/index.ts b/src/server/index.ts
index 10158eb96..6801b3132 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -234,16 +234,18 @@ server.on("connection", function (socket: Socket) {
 
     Utils.AddServerHandler(socket, MessageStore.CreateField, CreateField);
     Utils.AddServerHandler(socket, MessageStore.UpdateField, diff => UpdateField(socket, diff));
-    Utils.AddServerHandler(socket, MessageStore.GetRefField, GetRefField);
-    Utils.AddServerHandler(socket, MessageStore.GetRefFields, GetRefFields);
+    Utils.AddServerHandlerCallback(socket, MessageStore.GetRefField, GetRefField);
+    Utils.AddServerHandlerCallback(socket, MessageStore.GetRefFields, GetRefFields);
 });
 
-function deleteFields() {
-    return Database.Instance.deleteAll();
+async function deleteFields() {
+    await Database.Instance.deleteAll();
+    await Database.Instance.deleteAll('newDocuments');
 }
 
 async function deleteAll() {
     await Database.Instance.deleteAll();
+    await Database.Instance.deleteAll('newDocuments');
     await Database.Instance.deleteAll('sessions');
     await Database.Instance.deleteAll('users');
 }
-- 
cgit v1.2.3-70-g09d2


From a2751d16babb38cde2b86b1cb8fc5d74c15762d7 Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Sun, 28 Apr 2019 00:23:18 -0400
Subject: Decent amount of stuff is working

---
 src/client/views/Main.tsx                                             | 2 +-
 src/client/views/collections/CollectionBaseView.tsx                   | 2 +-
 src/client/views/collections/CollectionPDFView.tsx                    | 3 ++-
 src/client/views/collections/CollectionVideoView.tsx                  | 3 ++-
 src/client/views/collections/CollectionView.tsx                       | 3 ++-
 .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx   | 2 +-
 src/client/views/nodes/CollectionFreeFormDocumentView.tsx             | 1 +
 src/client/views/nodes/DocumentView.tsx                               | 4 ++--
 src/client/views/nodes/FormattedTextBox.tsx                           | 3 ++-
 src/client/views/nodes/PDFBox.tsx                                     | 2 +-
 src/new_fields/RichTextField.ts                                       | 2 ++
 src/new_fields/Types.ts                                               | 2 +-
 12 files changed, 18 insertions(+), 11 deletions(-)

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

diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 4a68d1c68..98c5a5306 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -165,7 +165,7 @@ export class Main extends React.Component {
     @action
     openWorkspace = async (doc: Doc, fromHistory = false) => {
         this.mainContainer = doc;
-        fromHistory || window.history.pushState(null, StrCast(doc.title), "/doc/" + doc.Id);
+        fromHistory || window.history.pushState(null, StrCast(doc.title), "/doc/" + doc[Id]);
         const col = await Cast(CurrentUserUtils.UserDocument.optionalRightCollection, Doc);
         // if there is a pending doc, and it has new data, show it (syip: we use a timeout to prevent collection docking view from being uninitialized)
         setTimeout(async () => {
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index b2fba1415..ed761d3f3 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -95,7 +95,7 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
             //TODO This won't create the field if it doesn't already exist
             const value = Cast(props.Document[props.fieldKey], listSpec(Doc));
             if (value !== undefined) {
-                if (allowDuplicates || !value.some(v => v.Id === doc.Id)) {
+                if (allowDuplicates || !value.some(v => v[Id] === doc[Id])) {
                     value.push(doc);
                 }
             } else {
diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx
index 99438b4e8..5a1af354a 100644
--- a/src/client/views/collections/CollectionPDFView.tsx
+++ b/src/client/views/collections/CollectionPDFView.tsx
@@ -8,6 +8,7 @@ import { FieldView, FieldViewProps } from "../nodes/FieldView";
 import { CollectionRenderProps, CollectionBaseView, CollectionViewType } from "./CollectionBaseView";
 import { emptyFunction } from "../../../Utils";
 import { NumCast } from "../../../new_fields/Types";
+import { Id } from "../../../new_fields/RefField";
 
 
 @observer
@@ -33,7 +34,7 @@ export class CollectionPDFView extends React.Component<FieldViewProps> {
     }
 
     onContextMenu = (e: React.MouseEvent): void => {
-        if (!e.isPropagationStopped() && this.props.Document.Id !== "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
+        if (!e.isPropagationStopped() && this.props.Document[Id] !== "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
             ContextMenu.Instance.addItem({ description: "PDFOptions", event: emptyFunction });
         }
     }
diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index d45be228a..7232ecea2 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -8,6 +8,7 @@ import { CollectionFreeFormView } from "./collectionFreeForm/CollectionFreeFormV
 import { FieldView, FieldViewProps } from "../nodes/FieldView";
 import { emptyFunction } from "../../../Utils";
 import { NumCast } from "../../../new_fields/Types";
+import { Id } from "../../../new_fields/RefField";
 
 
 @observer
@@ -107,7 +108,7 @@ export class CollectionVideoView extends React.Component<FieldViewProps> {
     }
 
     onContextMenu = (e: React.MouseEvent): void => {
-        if (!e.isPropagationStopped() && this.props.Document.Id !== "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
+        if (!e.isPropagationStopped() && this.props.Document[Id] !== "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
             ContextMenu.Instance.addItem({ description: "VideoOptions", event: emptyFunction });
         }
     }
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index b72065bca..c2049a09a 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -10,6 +10,7 @@ import { CurrentUserUtils } from '../../../server/authentication/models/current_
 import { observer } from 'mobx-react';
 import { undoBatch } from '../../util/UndoManager';
 import { trace } from 'mobx';
+import { Id } from '../../../new_fields/RefField';
 
 @observer
 export class CollectionView extends React.Component<FieldViewProps> {
@@ -31,7 +32,7 @@ export class CollectionView extends React.Component<FieldViewProps> {
     get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldKey === "annotations"; } // bcz: ? Why do we need to compare Id's?
 
     onContextMenu = (e: React.MouseEvent): void => {
-        if (!this.isAnnotationOverlay && !e.isPropagationStopped() && this.props.Document.Id !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
+        if (!this.isAnnotationOverlay && !e.isPropagationStopped() && this.props.Document[Id] !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
             ContextMenu.Instance.addItem({ description: "Freeform", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Freeform) });
             ContextMenu.Instance.addItem({ description: "Schema", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Schema) });
             ContextMenu.Instance.addItem({ description: "Treeview", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Tree) });
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index dfacca204..dcded7648 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -257,7 +257,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             moveDocument: this.props.moveDocument,
             ScreenToLocalTransform: this.getTransform,
             isTopMost: false,
-            selectOnLoad: document.Id === this._selectOnLoaded,
+            selectOnLoad: document[Id] === this._selectOnLoaded,
             PanelWidth: () => Cast(document.width, "number", 0),//TODO Types These are inline functions
             PanelHeight: () => Cast(document.height, "number", 0),
             ContentScaling: returnOne,
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 376af0b36..8766eb7ea 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -20,6 +20,7 @@ const schema = createSchema({
     zIndex: "number"
 });
 
+//TODO Types: The import order is wrong, so positionSchema is undefined
 type FreeformDocument = makeInterface<[typeof schema, typeof positionSchema]>;
 const FreeformDocument = makeInterface(schema, positionSchema);
 
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index c304b6a35..3814eeb9c 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -139,7 +139,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     }
 
     onClick = (e: React.MouseEvent): void => {
-        if (CurrentUserUtils.MainDocId !== this.props.Document.Id &&
+        if (CurrentUserUtils.MainDocId !== this.props.Document[Id] &&
             (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD &&
                 Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) {
             SelectionManager.SelectDoc(this, e.ctrlKey);
@@ -247,7 +247,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         ContextMenu.Instance.addItem({ description: "Fields", event: this.fieldsClicked });
         ContextMenu.Instance.addItem({ description: "Center", event: () => this.props.focus(this.props.Document) });
         ContextMenu.Instance.addItem({ description: "Open Right", event: () => CollectionDockingView.Instance.AddRightSplit(this.props.Document) });
-        ContextMenu.Instance.addItem({ description: "Copy URL", event: () => Utils.CopyText(DocServer.prepend("/doc/" + this.props.Document.Id)) });
+        ContextMenu.Instance.addItem({ description: "Copy URL", event: () => Utils.CopyText(DocServer.prepend("/doc/" + this.props.Document[Id])) });
         ContextMenu.Instance.addItem({ description: "Copy ID", event: () => Utils.CopyText(this.props.Document[Id]) });
         //ContextMenu.Instance.addItem({ description: "Docking", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Docking) })
         ContextMenu.Instance.addItem({ description: "Delete", event: this.deleteClicked });
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 96512718f..c4c720ca9 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -22,6 +22,7 @@ import { observer } from "mobx-react";
 import { InkingControl } from "../InkingControl";
 import { StrCast, Cast } from "../../../new_fields/Types";
 import { RichTextField } from "../../../new_fields/RichTextField";
+import { Id } from "../../../new_fields/RefField";
 const { buildMenuItems } = require("prosemirror-example-setup");
 const { menuBar } = require("prosemirror-menu");
 
@@ -108,7 +109,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
         };
 
         if (this.props.isOverlay) {
-            this._inputReactionDisposer = reaction(() => MainOverlayTextBox.Instance.TextDoc && MainOverlayTextBox.Instance.TextDoc.Id,
+            this._inputReactionDisposer = reaction(() => MainOverlayTextBox.Instance.TextDoc && MainOverlayTextBox.Instance.TextDoc[Id],
                 () => {
                     if (this._editorView) {
                         this._editorView.destroy();
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 7fbfed1c0..9f0849492 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -447,7 +447,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
         let pdfUrl = Cast(this.props.Document[this.props.fieldKey], PdfField);
         let xf = FieldValue(this.Document.nativeHeight, 0) / renderHeight;
         return <div className="pdfBox-contentContainer" key="container" style={{ transform: `scale(${xf}, ${xf})` }}>
-            <Document file={window.origin + RouteStore.corsProxy + `/${pdfUrl}`} renderMode={this._renderAsSvg ? "svg" : ""}>
+            <Document file={window.origin + RouteStore.corsProxy + `/${pdfUrl!.url.href}`} renderMode={this._renderAsSvg ? "svg" : ""}>
                 <Measure onResize={this.setScaling}>
                     {({ measureRef }) =>
                         <div className="pdfBox-page" ref={measureRef}>
diff --git a/src/new_fields/RichTextField.ts b/src/new_fields/RichTextField.ts
index 0fa3cf73c..f2033d5a7 100644
--- a/src/new_fields/RichTextField.ts
+++ b/src/new_fields/RichTextField.ts
@@ -1,6 +1,8 @@
 import { ObjectField } from "./ObjectField";
 import { serializable } from "serializr";
+import { Deserializable } from "../client/util/SerializationHelper";
 
+@Deserializable("RichTextField")
 export class RichTextField extends ObjectField {
     @serializable(true)
     readonly Data: string;
diff --git a/src/new_fields/Types.ts b/src/new_fields/Types.ts
index 3f8eabd45..e179c2602 100644
--- a/src/new_fields/Types.ts
+++ b/src/new_fields/Types.ts
@@ -76,7 +76,7 @@ type WithoutList<T extends Field> = T extends List<infer R> ? R[] : T;
 export function FieldValue<T extends Field, U extends WithoutList<T>>(field: FieldResult<T>, defaultValue: U): WithoutList<T>;
 export function FieldValue<T extends Field>(field: FieldResult<T>): Opt<T>;
 export function FieldValue<T extends Field>(field: FieldResult<T>, defaultValue?: T): Opt<T> {
-    return field instanceof Promise ? defaultValue : field;
+    return (field instanceof Promise || field === undefined) ? defaultValue : field;
 }
 
 export interface PromiseLike<T> {
-- 
cgit v1.2.3-70-g09d2


From a5ab5caa244da261814bc10f0ae88b302da93951 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sun, 28 Apr 2019 22:00:32 -0400
Subject: fixed webbox interactions.  got rid of pdf annotation.  fixed
 formatted text menu appearing

---
 src/client/util/TooltipTextMenu.tsx         |  2 +-
 src/client/views/nodes/FormattedTextBox.tsx | 20 ++++++++++++--------
 src/client/views/nodes/PDFBox.tsx           |  4 ++--
 src/client/views/nodes/WebBox.scss          | 17 +++++++++++++++--
 src/client/views/nodes/WebBox.tsx           |  6 ++++--
 5 files changed, 34 insertions(+), 15 deletions(-)

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

diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index 4f0eb7d63..38267f4f9 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -24,7 +24,7 @@ const SVG = "http://www.w3.org/2000/svg";
 //appears above a selection of text in a RichTextBox to give user options such as Bold, Italics, etc.
 export class TooltipTextMenu {
 
-    private tooltip: HTMLElement;
+    public tooltip: HTMLElement;
     private num_icons = 0;
     private view: EditorView;
     private fontStyles: MarkType[];
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index d8cd28b6c..fc8d757f6 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -1,4 +1,4 @@
-import { action, IReactionDisposer, reaction, trace, computed } from "mobx";
+import { action, IReactionDisposer, reaction, trace, computed, _allowStateChangesInsideComputed } from "mobx";
 import { baseKeymap } from "prosemirror-commands";
 import { history } from "prosemirror-history";
 import { keymap } from "prosemirror-keymap";
@@ -22,8 +22,6 @@ import React = require("react");
 import { SelectionManager } from "../../util/SelectionManager";
 import { observer } from "mobx-react";
 import { InkingControl } from "../InkingControl";
-const { buildMenuItems } = require("prosemirror-example-setup");
-const { menuBar } = require("prosemirror-menu");
 
 // FormattedTextBox: Displays an editable plain text node that maps to a specified Key of a Document
 //
@@ -67,9 +65,10 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
 
     _applyingChange: boolean = false;
 
+    _lastState: any = undefined;
     dispatchTransaction = (tx: Transaction) => {
         if (this._editorView) {
-            const state = this._editorView.state.apply(tx);
+            const state = this._lastState = this._editorView.state.apply(tx);
             this._editorView.updateState(state);
             this._applyingChange = true;
             this.props.Document.SetDataOnPrototype(
@@ -88,10 +87,10 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
             schema,
             inpRules, //these currently don't do anything, but could eventually be helpful
             plugins: this.props.isOverlay ? [
+                this.tooltipTextMenuPlugin(),
                 history(),
                 keymap(buildKeymap(schema)),
                 keymap(baseKeymap),
-                this.tooltipTextMenuPlugin(),
                 // this.tooltipLinkingMenuPlugin(),
                 new Plugin({
                     props: {
@@ -169,8 +168,10 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
     }
     @action
     onPointerDown = (e: React.PointerEvent): void => {
-        if (e.button === 1 && this.props.isSelected() && !e.altKey && !e.ctrlKey && !e.metaKey) {
+        if (e.button === 0 && this.props.isSelected() && !e.altKey && !e.ctrlKey && !e.metaKey) {
             e.stopPropagation();
+            if (this._toolTipTextMenu && this._toolTipTextMenu.tooltip)
+                this._toolTipTextMenu.tooltip.style.opacity = "0";
         }
         if (e.button === 2 || (e.button === 0 && e.ctrlKey)) {
             this._gotDown = true;
@@ -178,7 +179,8 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
         }
     }
     onPointerUp = (e: React.PointerEvent): void => {
-        console.log("pointer up");
+        if (this._toolTipTextMenu && this._toolTipTextMenu.tooltip)
+            this._toolTipTextMenu.tooltip.style.opacity = "1";
         if (e.buttons === 1 && this.props.isSelected() && !e.altKey) {
             e.stopPropagation();
         }
@@ -235,13 +237,15 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
 
     tooltipTextMenuPlugin() {
         let myprops = this.props;
+        let self = this;
         return new Plugin({
             view(_editorView) {
-                return new TooltipTextMenu(_editorView, myprops);
+                return self._toolTipTextMenu = new TooltipTextMenu(_editorView, myprops);
             }
         });
     }
 
+    _toolTipTextMenu: TooltipTextMenu | undefined = undefined;
     tooltipLinkingMenuPlugin() {
         let myprops = this.props;
         return new Plugin({
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 3d13c6f23..226dfba11 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -115,7 +115,7 @@ export class PDFBox extends React.Component<FieldViewProps> {
                                 child.id = "highlighted";
                                 //@ts-ignore
                                 obj.spans.push(child);
-                                child.addEventListener("mouseover", this.onEnter); //adds mouseover annotation handler
+                                // child.addEventListener("mouseover", this.onEnter); //adds mouseover annotation handler
                             }
                         });
                     }
@@ -138,7 +138,7 @@ export class PDFBox extends React.Component<FieldViewProps> {
                     child.id = "highlighted";
                     //@ts-ignore
                     temp.spans.push(child);
-                    child.addEventListener("mouseover", this.onEnter); //adds mouseover annotation handler
+                    // child.addEventListener("mouseover", this.onEnter); //adds mouseover annotation handler
                 }
             });
 
diff --git a/src/client/views/nodes/WebBox.scss b/src/client/views/nodes/WebBox.scss
index 2ad1129a4..eb09b0693 100644
--- a/src/client/views/nodes/WebBox.scss
+++ b/src/client/views/nodes/WebBox.scss
@@ -1,12 +1,19 @@
 
-.webBox-cont {
+.webBox-cont, .webBox-cont-interactive{
     padding: 0vw;
     position: absolute;
     top: 0;
     left:0;
     width: 100%;
     height: 100%;
-    overflow: scroll;
+    overflow: auto;
+    pointer-events: none ;
+}
+.webBox-cont-interactive {
+    pointer-events: all;
+    span {
+        user-select: text !important;
+    }
 }
 
 #webBox-htmlSpan {
@@ -15,6 +22,12 @@
     left:0;
 }
 
+.webBox-overlay {
+    width: 100%;
+    height: 100%;
+    position: absolute;
+}
+
 .webBox-button {
     padding : 0vw;
     border: none;
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index f7f5e31e6..a7c6fda8b 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -7,6 +7,7 @@ import { observer } from "mobx-react";
 import { computed, reaction, IReactionDisposer } from 'mobx';
 import { KeyStore } from '../../../fields/KeyStore';
 import { DocumentDecorations } from "../DocumentDecorations";
+import { InkingControl } from "../InkingControl";
 
 @observer
 export class WebBox extends React.Component<FieldViewProps> {
@@ -45,12 +46,13 @@ export class WebBox extends React.Component<FieldViewProps> {
 
         let frozen = !this.props.isSelected() || DocumentDecorations.Instance.Interacting;
 
+        let classname = "webBox-cont" + (this.props.isSelected() && !InkingControl.Instance.selectedTool && !DocumentDecorations.Instance.Interacting ? "-interactive" : "");
         return (
             <>
-                <div className="webBox-cont"  >
+                <div className={classname}  >
                     {content}
                 </div>
-                {!frozen ? (null) : <div onWheel={this.onPreWheel} onPointerDown={this.onPrePointer} onPointerMove={this.onPrePointer} onPointerUp={this.onPrePointer} style={{ width: "100%", height: "100%", position: "absolute" }} />}
+                {!frozen ? (null) : <div className="webBox-overlay" onWheel={this.onPreWheel} onPointerDown={this.onPrePointer} onPointerMove={this.onPrePointer} onPointerUp={this.onPrePointer} />}
             </>);
     }
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From a98672afa22eeb5f4c24edd3207c1b043cd012e7 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Mon, 29 Apr 2019 01:01:59 -0400
Subject: fixed templates

---
 src/client/views/MainOverlayTextBox.tsx         |  8 +++-----
 src/client/views/Templates.tsx                  |  6 +++---
 src/client/views/nodes/DocumentContentsView.tsx |  4 +++-
 src/client/views/nodes/DocumentView.tsx         | 23 +++++++++++++----------
 src/client/views/nodes/FormattedTextBox.tsx     | 12 ++++++------
 5 files changed, 28 insertions(+), 25 deletions(-)

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

diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx
index be8d67925..209b1202c 100644
--- a/src/client/views/MainOverlayTextBox.tsx
+++ b/src/client/views/MainOverlayTextBox.tsx
@@ -89,12 +89,10 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
 
     render() {
         if (this.TextDoc) {
-            let toScreenXf = this._textXf().inverse();
-            let pt = toScreenXf.transformPoint(0, 0);
-            let s = 1 / this._textXf().Scale;
-            return <div className="mainOverlayTextBox-textInput" style={{ transform: `translate(${pt[0]}px, ${pt[1]}px) scale(${s},${s})`, width: "auto", height: "auto" }} >
+            let s = this._textXf().Scale;
+            return <div className="mainOverlayTextBox-textInput" style={{ transform: `translate(${this._textRect.x}px, ${this._textRect.y}px) scale(${1 / s},${1 / s})`, width: "auto", height: "auto" }} >
                 <div className="mainOverlayTextBox-textInput" onPointerDown={this.textBoxDown} ref={this._textProxyDiv} onScroll={this.textScroll}
-                    style={{ width: `${this.TextDoc.Width()}px`, height: `${this.TextDoc.Height()}px` }}>
+                    style={{ width: `${this._textRect.width * s}px`, height: `${this._textRect.height * s}px` }}>
                     <FormattedTextBox fieldKey={this._textFieldKey} isOverlay={true} Document={this.TextDoc} isSelected={returnTrue} select={emptyFunction} isTopMost={true}
                         selectOnLoad={true} ContainingCollectionView={undefined} whenActiveChanged={emptyFunction} active={returnTrue}
                         ScreenToLocalTransform={this._textXf} PanelWidth={returnZero} PanelHeight={returnZero} focus={emptyDocFunction} />
diff --git a/src/client/views/Templates.tsx b/src/client/views/Templates.tsx
index 52021861f..a0f9fe7e5 100644
--- a/src/client/views/Templates.tsx
+++ b/src/client/views/Templates.tsx
@@ -39,15 +39,15 @@ export namespace Templates {
     // export const BasicLayout = new Template("Basic layout", "{layout}");
 
     export const OuterCaption = new Template("Outer caption", TemplatePosition.OutterBottom,
-        `<div><div style="margin:auto; height:calc(100%); width:100%;">{layout}</div><div style="height:(100% + 50px); width:100%; position:absolute"><FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={CaptionKey} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} isTopMost={isTopMost}/></div></div>`
+        `<div><div style="margin:auto; height:calc(100%); width:100%;">{layout}</div><div style="height:(100% + 50px); width:100%; position:absolute"><FormattedTextBox {...props} fieldKey={CaptionKey} /></div></div>`
     );
 
     export const InnerCaption = new Template("Inner caption", TemplatePosition.InnerBottom,
-        `<div><div style="margin:auto; height:calc(100% - 50px); width:100%;">{layout}</div><div style="height:50px; width:100%; position:absolute"><FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={CaptionKey} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} isTopMost={isTopMost}/></div></div>`
+        `<div><div style="margin:auto; height:calc(100% - 50px); width:100%;">{layout}</div><div style="height:50px; width:100%; position:absolute"><FormattedTextBox {...props} fieldKey={CaptionKey}/></div></div>`
     );
 
     export const SideCaption = new Template("Side caption", TemplatePosition.OutterRight,
-        `<div><div style="margin:auto; height:100%; width:100%;">{layout}</div><div style="height:100%; width:300px; position:absolute; top: 0; right: -300px;"><FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={CaptionKey} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} isTopMost={isTopMost}/></div> </div>`
+        `<div><div style="margin:auto; height:100%; width:100%;">{layout}</div><div style="height:100%; width:300px; position:absolute; top: 0; right: -300px;"><FormattedTextBox {...props} fieldKey={CaptionKey}/></div> </div>`
     );
 
     export const Title = new Template("Title", TemplatePosition.InnerTop,
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 07599c345..e9c46aa9d 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -47,7 +47,9 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
     CreateBindings(): JsxBindings {
         let bindings: JsxBindings = { props: OmitKeys(this.props, ['parentActive'], (obj: any) => obj.active = this.props.parentActive) };
 
-        for (const key of this.layoutKeys) {
+        let keys: Key[] = [];
+        keys.push(...this.layoutKeys, KeyStore.Caption) // bcz: hack to get templates to work
+        for (const key of keys) {
             bindings[key.Name + "Key"] = key; // this maps string values of the form <keyname>Key to an actual key Kestore.keyname  e.g,   "DataKey" => KeyStore.Data
         }
         for (const key of this.layoutFields) {
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index bae14193e..6dddab600 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -26,6 +26,7 @@ import React = require("react");
 import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView";
 import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils";
 import { MarqueeView } from "../collections/collectionFreeForm/MarqueeView";
+import { TextField } from "../../../fields/TextField";
 
 export interface DocumentViewProps {
     ContainingCollectionView: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
@@ -88,7 +89,6 @@ export function FakeJsxArgs(keys: string[], fields: string[] = []): JsxArgs {
 export class DocumentView extends React.Component<DocumentViewProps> {
     private _downX: number = 0;
     private _downY: number = 0;
-    @computed get base(): string { return this.props.Document.GetText(KeyStore.BaseLayout, "<p>Error loading base layout data</p>"); }
     private _mainCont = React.createRef<HTMLDivElement>();
     private _dropDisposer?: DragManager.DragDropDisposer;
 
@@ -249,17 +249,20 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         }
     }
 
-    updateLayout = (): void => {
-        let base = this.base;
-        let layout = this.base;
+    updateLayout = async () => {
+        const baseLayout = await this.props.Document.GetTAsync(KeyStore.BaseLayout, TextField);
+        if (baseLayout) {
+            let base = baseLayout.Data;
+            let layout = baseLayout.Data;
 
-        this.templates.forEach(template => {
-            let temp = template.Layout;
-            layout = temp.replace("{layout}", base);
-            base = layout;
-        });
+            this.templates.forEach(template => {
+                let temp = template.Layout;
+                layout = temp.replace("{layout}", base);
+                base = layout;
+            });
 
-        this.props.Document.SetText(KeyStore.Layout, layout);
+            this.props.Document.SetText(KeyStore.Layout, layout);
+        }
     }
 
     @action
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index fc8d757f6..92957ed19 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -50,6 +50,7 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
         return FieldView.LayoutString(FormattedTextBox, fieldStr);
     }
     private _ref: React.RefObject<HTMLDivElement>;
+    private _proseRef: React.RefObject<HTMLDivElement>;
     private _editorView: Opt<EditorView>;
     private _gotDown: boolean = false;
     private _reactionDisposer: Opt<IReactionDisposer>;
@@ -60,6 +61,7 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
         super(props);
 
         this._ref = React.createRef();
+        this._proseRef = React.createRef();
         this.onChange = this.onChange.bind(this);
     }
 
@@ -188,9 +190,7 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
 
     onFocused = (e: React.FocusEvent): void => {
         if (!this.props.isOverlay) {
-            if (MainOverlayTextBox.Instance.TextDoc != this.props.Document) {
-                MainOverlayTextBox.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform);
-            }
+            MainOverlayTextBox.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform);
         } else {
             if (this._ref.current) {
                 this._ref.current.scrollTop = MainOverlayTextBox.Instance.TextScroll;
@@ -232,7 +232,7 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
     }
 
     onClick = (e: React.MouseEvent): void => {
-        this._ref.current!.focus();
+        this._proseRef.current!.focus();
     }
 
     tooltipTextMenuPlugin() {
@@ -277,7 +277,7 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
         let color = this.props.Document.GetText(KeyStore.BackgroundColor, "");
         let interactive = InkingControl.Instance.selectedTool ? "" : "-interactive";
         return (
-            <div className={`formattedTextBox-cont${style}`}
+            <div className={`formattedTextBox-cont${style}`} ref={this._ref}
                 style={{
                     pointerEvents: interactive ? "all" : "none",
                     background: color,
@@ -292,7 +292,7 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
                 // tfs: do we need this event handler
                 onWheel={this.onPointerWheel}
             >
-                <div className={`formattedTextBox-inner${rounded}`} ref={this._ref} />
+                <div className={`formattedTextBox-inner${rounded}`} ref={this._proseRef} />
             </div>
         );
     }
-- 
cgit v1.2.3-70-g09d2


From a180574f56447d6f24b4e77f87efba3a1287da9c Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Mon, 29 Apr 2019 09:43:10 -0400
Subject: fixed title template and overlay text positioning

---
 src/client/views/MainOverlayTextBox.tsx     |  9 ++++-----
 src/client/views/Templates.tsx              |  2 +-
 src/client/views/nodes/FormattedTextBox.tsx | 11 +++++------
 3 files changed, 10 insertions(+), 12 deletions(-)

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

diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx
index 209b1202c..13e661b46 100644
--- a/src/client/views/MainOverlayTextBox.tsx
+++ b/src/client/views/MainOverlayTextBox.tsx
@@ -21,7 +21,6 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
     public static Instance: MainOverlayTextBox;
     @observable public TextDoc?: Document = undefined;
     public TextScroll: number = 0;
-    @observable _textRect: any;
     @observable _textXf: () => Transform = () => Transform.Identity();
     private _textFieldKey: Key = KeyStore.Data;
     private _textColor: string | null = null;
@@ -47,7 +46,6 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
         if (div) {
             this._textColor = div.style.color;
             div.style.color = "transparent";
-            this._textRect = div.getBoundingClientRect();
             this.TextScroll = div.scrollTop;
         }
     }
@@ -88,11 +86,12 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
     }
 
     render() {
-        if (this.TextDoc) {
+        if (this.TextDoc && this._textTargetDiv) {
+            let textRect = this._textTargetDiv.getBoundingClientRect();
             let s = this._textXf().Scale;
-            return <div className="mainOverlayTextBox-textInput" style={{ transform: `translate(${this._textRect.x}px, ${this._textRect.y}px) scale(${1 / s},${1 / s})`, width: "auto", height: "auto" }} >
+            return <div className="mainOverlayTextBox-textInput" style={{ transform: `translate(${textRect.x}px, ${textRect.y}px) scale(${1 / s},${1 / s})`, width: "auto", height: "auto" }} >
                 <div className="mainOverlayTextBox-textInput" onPointerDown={this.textBoxDown} ref={this._textProxyDiv} onScroll={this.textScroll}
-                    style={{ width: `${this._textRect.width * s}px`, height: `${this._textRect.height * s}px` }}>
+                    style={{ width: `${textRect.width * s}px`, height: `${textRect.height * s}px` }}>
                     <FormattedTextBox fieldKey={this._textFieldKey} isOverlay={true} Document={this.TextDoc} isSelected={returnTrue} select={emptyFunction} isTopMost={true}
                         selectOnLoad={true} ContainingCollectionView={undefined} whenActiveChanged={emptyFunction} active={returnTrue}
                         ScreenToLocalTransform={this._textXf} PanelWidth={returnZero} PanelHeight={returnZero} focus={emptyDocFunction} />
diff --git a/src/client/views/Templates.tsx b/src/client/views/Templates.tsx
index a0f9fe7e5..fef69392d 100644
--- a/src/client/views/Templates.tsx
+++ b/src/client/views/Templates.tsx
@@ -51,7 +51,7 @@ export namespace Templates {
     );
 
     export const Title = new Template("Title", TemplatePosition.InnerTop,
-        `<div><div style="height:100%; width:100%;position:absolute;">{layout}</div><div style="height:25px; width:100%; position:absolute; top: 0; background-color: rgba(0, 0, 0, .4); color: white; padding:12px">{Title}</div></div>`
+        `<div><div style="height:100%; width:100%;position:absolute;">{layout}</div><div style="height:25px; width:100%; position:absolute; top: 0; background-color: rgba(0, 0, 0, .4); color: white; padding:2px 10px">{Title}</div></div>`
     );
 
     export const TemplateList: Template[] = [Title, OuterCaption, InnerCaption, SideCaption];
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 92957ed19..41ee24498 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -80,7 +80,11 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
             );
             this.props.Document.SetDataOnPrototype(KeyStore.DocumentText, state.doc.textBetween(0, state.doc.content.size, "\n\n"), TextField);
             this._applyingChange = false;
-            // doc.SetData(fieldKey, JSON.stringify(state.toJSON()), RichTextField);
+            if (this.props.Document.Title.startsWith("-") && this._editorView) {
+                let str = this._editorView.state.doc.textContent;
+                let titlestr = str.substr(0, Math.min(40, str.length));
+                this.props.Document.SetText(KeyStore.Title, "-" + titlestr + (str.length > 40 ? "..." : ""));
+            };
         }
     }
 
@@ -265,11 +269,6 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
         // stop propagation doesn't seem to stop propagation of native keyboard events.
         // so we set a flag on the native event that marks that the event's been handled.
         (e.nativeEvent as any).DASHFormattedTextBoxHandled = true;
-        if (this.props.Document.Title.startsWith("-") && this._editorView) {
-            let str = this._editorView.state.doc.textContent;
-            let titlestr = str.substr(0, Math.min(40, str.length));
-            this.props.Document.SetText(KeyStore.Title, "-" + titlestr + (str.length > 40 ? "..." : ""));
-        };
     }
     render() {
         let style = this.props.isOverlay ? "-scroll" : "-hidden";
-- 
cgit v1.2.3-70-g09d2


From 7d4a4b25459b66568880528cd3776b6ff9cbcf9f Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Tue, 30 Apr 2019 19:17:20 -0400
Subject: Fixed rich text background

---
 src/client/views/nodes/FormattedTextBox.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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

diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 455672472..9c6f95fc4 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -279,7 +279,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
         let color = StrCast(this.props.Document.backgroundColor);
         let interactive = InkingControl.Instance.selectedTool ? "" : "interactive";
         return (
-            <div className={`formattedTextBox-cont${style}`} ref={this._ref}
+            <div className={`formattedTextBox-cont-${style}`} ref={this._ref}
                 style={{
                     pointerEvents: interactive ? "all" : "none",
                     background: color,
-- 
cgit v1.2.3-70-g09d2


From 35105279d9cc55ccf331ec06de78077250b4cb5b Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Tue, 30 Apr 2019 19:30:17 -0400
Subject: Fixed various keys that hadn't been properly converted, which fixes
 zooming out on images/videos, etc.

---
 src/client/documents/Documents.ts           | 20 ++++++++++----------
 src/client/views/Templates.tsx              |  8 ++++----
 src/client/views/nodes/FormattedTextBox.tsx |  2 +-
 3 files changed, 15 insertions(+), 15 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 964faa8db..d9ee7a736 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -112,13 +112,13 @@ export namespace Docs {
     }
 
     function CreateImagePrototype(): Doc {
-        let imageProto = setupPrototypeOptions(imageProtoId, "IMAGE_PROTO", CollectionView.LayoutString("AnnotationsKey"),
+        let imageProto = setupPrototypeOptions(imageProtoId, "IMAGE_PROTO", CollectionView.LayoutString("annotations"),
             { x: 0, y: 0, nativeWidth: 600, width: 300, backgroundLayout: ImageBox.LayoutString(), curPage: 0 });
         return imageProto;
     }
 
     function CreateHistogramPrototype(): Doc {
-        let histoProto = setupPrototypeOptions(histoProtoId, "HISTO PROTO", CollectionView.LayoutString("AnnotationsKey"),
+        let histoProto = setupPrototypeOptions(histoProtoId, "HISTO PROTO", CollectionView.LayoutString("annotations"),
             { x: 0, y: 0, width: 300, height: 300, backgroundColor: "black", backgroundLayout: HistogramBox.LayoutString() });
         return histoProto;
     }
@@ -134,7 +134,7 @@ export namespace Docs {
         return textProto;
     }
     function CreatePdfPrototype(): Doc {
-        let pdfProto = setupPrototypeOptions(pdfProtoId, "PDF_PROTO", CollectionPDFView.LayoutString("AnnotationsKey"),
+        let pdfProto = setupPrototypeOptions(pdfProtoId, "PDF_PROTO", CollectionPDFView.LayoutString("annotations"),
             { x: 0, y: 0, nativeWidth: 1200, width: 300, backgroundLayout: PDFBox.LayoutString(), curPage: 1 });
         return pdfProto;
     }
@@ -155,7 +155,7 @@ export namespace Docs {
         return kvpProto;
     }
     function CreateVideoPrototype(): Doc {
-        let videoProto = setupPrototypeOptions(videoProtoId, "VIDEO_PROTO", CollectionVideoView.LayoutString("AnnotationsKey"),
+        let videoProto = setupPrototypeOptions(videoProtoId, "VIDEO_PROTO", CollectionVideoView.LayoutString("annotations"),
             { x: 0, y: 0, nativeWidth: 600, width: 300, backgroundLayout: VideoBox.LayoutString(), curPage: 0 });
         return videoProto;
     }
@@ -267,14 +267,14 @@ export namespace Docs {
             + ImageBox.LayoutString() +
             `</div>
             <div style="position:relative; height:15%; text-align:center; ">`
-            + FormattedTextBox.LayoutString("CaptionKey") +
+            + FormattedTextBox.LayoutString("caption") +
             `</div> 
         </div>`;
     }
-    export function FixedCaption(fieldName: string = "Caption") {
+    export function FixedCaption(fieldName: string = "caption") {
         return `<div style="position:absolute; height:30px; bottom:0; width:100%">
             <div style="position:absolute; width:100%; height:100%; text-align:center;bottom:0;">`
-            + FormattedTextBox.LayoutString(fieldName + "Key") +
+            + FormattedTextBox.LayoutString(fieldName) +
             `</div> 
         </div>`;
     }
@@ -286,7 +286,7 @@ export namespace Docs {
         {layout}
     </div>
     <div style="height:(100% + 25px); width:100%; position:absolute">
-        <FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={"CaptionKey"} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} isTopMost={isTopMost}/>
+        <FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={"caption"} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} isTopMost={isTopMost}/>
     </div>
 </div>       
         `);
@@ -298,7 +298,7 @@ export namespace Docs {
             {layout}
         </div>
         <div style="height:25px; width:100%; position:absolute">
-            <FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={"CaptionKey"} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} isTopMost={isTopMost}/>
+            <FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={"caption"} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} isTopMost={isTopMost}/>
         </div>
     </div>       
             `);
@@ -321,7 +321,7 @@ export namespace Docs {
             {layout}
         </div>
         <div style="height:15%; width:100%; position:absolute">
-            <FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={"CaptionKey"} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} isTopMost={isTopMost}/>
+            <FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={"caption"} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} isTopMost={isTopMost}/>
         </div>
     </div>       
             `);
diff --git a/src/client/views/Templates.tsx b/src/client/views/Templates.tsx
index fef69392d..5b7e8da63 100644
--- a/src/client/views/Templates.tsx
+++ b/src/client/views/Templates.tsx
@@ -39,19 +39,19 @@ export namespace Templates {
     // export const BasicLayout = new Template("Basic layout", "{layout}");
 
     export const OuterCaption = new Template("Outer caption", TemplatePosition.OutterBottom,
-        `<div><div style="margin:auto; height:calc(100%); width:100%;">{layout}</div><div style="height:(100% + 50px); width:100%; position:absolute"><FormattedTextBox {...props} fieldKey={CaptionKey} /></div></div>`
+        `<div><div style="margin:auto; height:calc(100%); width:100%;">{layout}</div><div style="height:(100% + 50px); width:100%; position:absolute"><FormattedTextBox {...props} fieldKey={"caption"} /></div></div>`
     );
 
     export const InnerCaption = new Template("Inner caption", TemplatePosition.InnerBottom,
-        `<div><div style="margin:auto; height:calc(100% - 50px); width:100%;">{layout}</div><div style="height:50px; width:100%; position:absolute"><FormattedTextBox {...props} fieldKey={CaptionKey}/></div></div>`
+        `<div><div style="margin:auto; height:calc(100% - 50px); width:100%;">{layout}</div><div style="height:50px; width:100%; position:absolute"><FormattedTextBox {...props} fieldKey={"caption"}/></div></div>`
     );
 
     export const SideCaption = new Template("Side caption", TemplatePosition.OutterRight,
-        `<div><div style="margin:auto; height:100%; width:100%;">{layout}</div><div style="height:100%; width:300px; position:absolute; top: 0; right: -300px;"><FormattedTextBox {...props} fieldKey={CaptionKey}/></div> </div>`
+        `<div><div style="margin:auto; height:100%; width:100%;">{layout}</div><div style="height:100%; width:300px; position:absolute; top: 0; right: -300px;"><FormattedTextBox {...props} fieldKey={"caption"}/></div> </div>`
     );
 
     export const Title = new Template("Title", TemplatePosition.InnerTop,
-        `<div><div style="height:100%; width:100%;position:absolute;">{layout}</div><div style="height:25px; width:100%; position:absolute; top: 0; background-color: rgba(0, 0, 0, .4); color: white; padding:2px 10px">{Title}</div></div>`
+        `<div><div style="height:100%; width:100%;position:absolute;">{layout}</div><div style="height:25px; width:100%; position:absolute; top: 0; background-color: rgba(0, 0, 0, .4); color: white; padding:2px 10px">{Document.title}</div></div>`
     );
 
     export const TemplateList: Template[] = [Title, OuterCaption, InnerCaption, SideCaption];
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 9c6f95fc4..b95d327d2 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -28,7 +28,7 @@ const { menuBar } = require("prosemirror-menu");
 
 // FormattedTextBox: Displays an editable plain text node that maps to a specified Key of a Document
 //
-//  HTML Markup:  <FormattedTextBox Doc={Document's ID} FieldKey={Key's name + "Key"}
+//  HTML Markup:  <FormattedTextBox Doc={Document's ID} FieldKey={Key's name}
 //
 //  In Code, the node's HTML is specified in the document's parameterized structure as:
 //        document.SetField(KeyStore.Layout,  "<FormattedTextBox doc={doc} fieldKey={<KEYNAME>Key} />");
-- 
cgit v1.2.3-70-g09d2


From 3ed9fbefe1428c1493027122791ccbbe1b2fe1d1 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 30 Apr 2019 19:48:36 -0400
Subject: fixed link document

---
 src/client/views/nodes/FormattedTextBox.scss | 6 +++---
 src/client/views/nodes/FormattedTextBox.tsx  | 8 ++++----
 src/new_fields/Doc.ts                        | 8 ++++----
 3 files changed, 11 insertions(+), 11 deletions(-)

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

diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss
index 727d3c0b2..d43aa4e02 100644
--- a/src/client/views/nodes/FormattedTextBox.scss
+++ b/src/client/views/nodes/FormattedTextBox.scss
@@ -30,11 +30,11 @@
     pointer-events: none;
 }
 .formattedTextBox-inner-rounded {
-    height: calc(100% - 40px);
+    height: calc(100% - 25px);
     width: calc(100% - 40px);
     position: absolute;
-    overflow: scroll;
-    top: 20;
+    overflow: auto;
+    top: 15;
     left: 20;
 }
 
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 9c6f95fc4..fe9696062 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -144,8 +144,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
 
     private setupEditor(config: any, doc?: Doc) {
         let field = doc ? Cast(doc[this.props.fieldKey], RichTextField) : undefined;
-        if (this._ref.current) {
-            this._editorView = new EditorView(this._ref.current, {
+        if (this._proseRef.current) {
+            this._editorView = new EditorView(this._proseRef.current, {
                 state: field && field.Data ? EditorState.fromJSON(config, JSON.parse(field.Data)) : EditorState.create(config),
                 dispatchTransaction: this.dispatchTransaction
             });
@@ -195,8 +195,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
         if (!this.props.isOverlay) {
             MainOverlayTextBox.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform);
         } else {
-            if (this._ref.current) {
-                this._ref.current.scrollTop = MainOverlayTextBox.Instance.TextScroll;
+            if (this._proseRef.current) {
+                this._proseRef.current.scrollTop = MainOverlayTextBox.Instance.TextScroll;
             }
         }
     }
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 64cc6d270..c4ad5ae95 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -1,7 +1,6 @@
 import { observable, action } from "mobx";
 import { serializable, primitive, map, alias, list } from "serializr";
 import { autoObject, SerializationHelper, Deserializable } from "../client/util/SerializationHelper";
-import { Utils } from "../Utils";
 import { DocServer } from "../client/DocServer";
 import { setter, getter, getField, updateFunction, deleteProperty } from "./util";
 import { Cast, ToConstructor, PromiseValue, FieldValue, NumCast } from "./Types";
@@ -10,6 +9,7 @@ import { listSpec } from "./Schema";
 import { List } from "./List";
 import { ObjectField, Parent, OnUpdate } from "./ObjectField";
 import { RefField, FieldId, Id } from "./RefField";
+import { Docs } from "../client/documents/Documents";
 
 export function IsField(field: any): field is Field {
     return (typeof field === "string")
@@ -163,9 +163,9 @@ export namespace Doc {
         return copy;
     }
 
-    export function MakeLink(source: Doc, target: Doc): Doc {
-        return UndoManager.RunInBatch(() => {
-            let linkDoc = new Doc;
+    export function MakeLink(source: Doc, target: Doc) {
+        UndoManager.RunInBatch(() => {
+            let linkDoc = Docs.TextDocument({ width: 100, height: 30, borderRounding: -1 });
             linkDoc.title = "New Link";
             linkDoc.linkDescription = "";
             linkDoc.linkTags = "Default";
-- 
cgit v1.2.3-70-g09d2


From 8f9baace2a0fd25e8a1cbdbb153cee1f286ad8e3 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 1 May 2019 09:03:17 -0400
Subject: fixed transition to GoldenLayout with Shift after drag starts

---
 src/client/views/nodes/DocumentView.tsx     | 1 -
 src/client/views/nodes/FormattedTextBox.tsx | 6 ++++++
 2 files changed, 6 insertions(+), 1 deletion(-)

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

diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index eab068355..cda9f9473 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -171,7 +171,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             document.addEventListener("pointermove", this.onPointerMove);
             document.removeEventListener("pointerup", this.onPointerUp);
             document.addEventListener("pointerup", this.onPointerUp);
-            e.preventDefault();
         }
     }
     onPointerMove = (e: PointerEvent): void => {
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 45e5901eb..12b7b5abf 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -237,6 +237,11 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
     onClick = (e: React.MouseEvent): void => {
         this._proseRef.current!.focus();
     }
+    onMouseDown = (e: React.MouseEvent): void => {
+        if (!this.props.isSelected() && this.props.active()) { // preventing default allows the onClick to be generated instead of being swallowed by the text box itself
+            e.preventDefault(); // bcz: this would normally be in OnPointerDown - however, if done there, no mouse move events will be generated which makes transititioning to GoldenLayout's drag interactions impossible
+        }
+    }
 
     tooltipTextMenuPlugin() {
         let myprops = this.props;
@@ -290,6 +295,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
                 onClick={this.onClick}
                 onPointerUp={this.onPointerUp}
                 onPointerDown={this.onPointerDown}
+                onMouseDown={this.onMouseDown}
                 onContextMenu={this.specificContextMenu}
                 // tfs: do we need this event handler
                 onWheel={this.onPointerWheel}
-- 
cgit v1.2.3-70-g09d2


From d6ecb1cabeb34b5e55bc107f308f63071e4c40f7 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 1 May 2019 11:02:53 -0400
Subject: fixed nested textbox selection

---
 src/client/views/nodes/FormattedTextBox.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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

diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 12b7b5abf..7f269a505 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -238,7 +238,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
         this._proseRef.current!.focus();
     }
     onMouseDown = (e: React.MouseEvent): void => {
-        if (!this.props.isSelected() && this.props.active()) { // preventing default allows the onClick to be generated instead of being swallowed by the text box itself
+        if (!this.props.isSelected()) { // preventing default allows the onClick to be generated instead of being swallowed by the text box itself
             e.preventDefault(); // bcz: this would normally be in OnPointerDown - however, if done there, no mouse move events will be generated which makes transititioning to GoldenLayout's drag interactions impossible
         }
     }
-- 
cgit v1.2.3-70-g09d2


From 1ece3904b6b3fbf4ddde29e93e31a30f3898e720 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Thu, 2 May 2019 13:20:27 -0400
Subject: cleaned up drag code - userDropAction takes precedence over
 dropAction. default is alias

---
 src/client/documents/Documents.ts                  |  3 ++-
 src/client/util/DragManager.ts                     | 19 ++++++++++------
 src/client/views/DocumentDecorations.tsx           |  1 -
 src/client/views/EditableView.tsx                  |  2 +-
 src/client/views/Main.tsx                          | 14 +++++-------
 src/client/views/collections/CollectionSubView.tsx |  6 ++---
 .../views/collections/CollectionTreeView.scss      |  3 ++-
 .../views/collections/CollectionTreeView.tsx       | 26 +++++++++++-----------
 src/client/views/nodes/DocumentView.tsx            | 12 +++++-----
 src/client/views/nodes/FormattedTextBox.tsx        |  6 +++--
 10 files changed, 49 insertions(+), 43 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 2de389a3c..8706359e4 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -32,6 +32,7 @@ import { IconField } from "../../new_fields/IconField";
 import { listSpec } from "../../new_fields/Schema";
 import { DocServer } from "../DocServer";
 import { StrokeData, InkField } from "../../new_fields/InkField";
+import { dropActionType } from "../util/DragManager";
 
 export interface DocumentOptions {
     x?: number;
@@ -51,7 +52,7 @@ export interface DocumentOptions {
     templates?: List<string>;
     viewType?: number;
     backgroundColor?: string;
-    copyDraggedItems?: boolean;
+    dropAction?: dropActionType;
     backgroundLayout?: string;
     curPage?: number;
     documentText?: string;
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 4acf609f4..a3dbe6e43 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -1,14 +1,14 @@
 import { action } from "mobx";
 import { emptyFunction } from "../../Utils";
 import { CollectionDockingView } from "../views/collections/CollectionDockingView";
-import { DocumentDecorations } from "../views/DocumentDecorations";
 import * as globalCssVariables from "../views/globalCssVariables.scss";
 import { MainOverlayTextBox } from "../views/MainOverlayTextBox";
 import { Doc } from "../../new_fields/Doc";
 import { Cast } from "../../new_fields/Types";
 import { listSpec } from "../../new_fields/Schema";
 
-export function SetupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc: () => Doc, moveFunc?: DragManager.MoveFunction, copyOnDrop: boolean = false) {
+export type dropActionType = "alias" | "copy" | undefined;
+export function SetupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc: () => Doc, moveFunc?: DragManager.MoveFunction, dropAction?: dropActionType) {
     let onRowMove = action((e: PointerEvent): void => {
         e.stopPropagation();
         e.preventDefault();
@@ -16,7 +16,7 @@ export function SetupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc:
         document.removeEventListener("pointermove", onRowMove);
         document.removeEventListener('pointerup', onRowUp);
         var dragData = new DragManager.DocumentDragData([docFunc()]);
-        dragData.copyOnDrop = copyOnDrop;
+        dragData.dropAction = dropAction;
         dragData.moveDocument = moveFunc;
         DragManager.StartDocumentDrag([_reference.current!], dragData, e.x, e.y);
     });
@@ -146,15 +146,20 @@ export namespace DragManager {
         droppedDocuments: Doc[];
         xOffset: number;
         yOffset: number;
-        aliasOnDrop?: boolean;
-        copyOnDrop?: boolean;
+        dropAction: dropActionType;
+        userDropAction: dropActionType;
         moveDocument?: MoveFunction;
         [id: string]: any;
     }
 
     export function StartDocumentDrag(eles: HTMLElement[], dragData: DocumentDragData, downX: number, downY: number, options?: DragOptions) {
         StartDrag(eles, dragData, downX, downY, options,
-            (dropData: { [id: string]: any }) => (dropData.droppedDocuments = dragData.aliasOnDrop ? dragData.draggedDocuments.map(d => Doc.MakeAlias(d)) : dragData.copyOnDrop ? dragData.draggedDocuments.map(d => Doc.MakeCopy(d, true)) : dragData.draggedDocuments));
+            (dropData: { [id: string]: any }) =>
+                (dropData.droppedDocuments = dragData.userDropAction == "alias" || (!dragData.userDropAction && dragData.dropAction == "alias") ?
+                    dragData.draggedDocuments.map(d => Doc.MakeAlias(d)) :
+                    dragData.userDropAction == "copy" || (!dragData.userDropAction && dragData.dropAction == "copy") ?
+                        dragData.draggedDocuments.map(d => Doc.MakeCopy(d, true)) :
+                        dragData.draggedDocuments));
     }
 
     export class LinkDragData {
@@ -252,7 +257,7 @@ export namespace DragManager {
             e.stopPropagation();
             e.preventDefault();
             if (dragData instanceof DocumentDragData) {
-                dragData.aliasOnDrop = e.ctrlKey || e.altKey;
+                dragData.userDropAction = e.ctrlKey || e.altKey ? "alias" : undefined;
             }
             if (e.shiftKey) {
                 AbortDrag();
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 7dcd71495..d07adcb71 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -144,7 +144,6 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         let dragData = new DragManager.DocumentDragData(SelectionManager.SelectedDocuments().map(dv => dv.props.Document));
         dragData.xOffset = xoff;
         dragData.yOffset = yoff;
-        dragData.aliasOnDrop = false;
         dragData.moveDocument = SelectionManager.SelectedDocuments()[0].props.moveDocument;
         this.Interacting = true;
         this._hidden = true;
diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index 2f17c6c51..73467eb9d 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -60,7 +60,7 @@ export class EditableView extends React.Component<EditableProps> {
             return (
                 <div className="editableView-container-editing" style={{ display: this.props.display, height: "auto", maxHeight: `${this.props.height}` }}
                     onClick={action(() => this.editing = true)} >
-                    {this.props.contents}
+                    <span>{this.props.contents}</span>
                 </div>
             );
         }
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index b2ca4a196..a07a2d5b1 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -8,9 +8,7 @@ import * as React from 'react';
 import * as ReactDOM from 'react-dom';
 import Measure from 'react-measure';
 import * as request from 'request';
-import { WorkspacesMenu } from '../../server/authentication/controllers/WorkspacesMenu';
 import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils';
-import { MessageStore } from '../../server/Message';
 import { RouteStore } from '../../server/RouteStore';
 import { emptyFunction, returnTrue, Utils, returnOne, returnZero } from '../../Utils';
 import { Docs } from '../documents/Documents';
@@ -86,11 +84,11 @@ export class Main extends React.Component {
         this.initEventListeners();
         this.initAuthenticationRouters();
 
-        try {
-            this.initializeNorthstar();
-        } catch (e) {
+        // try {
+        //     this.initializeNorthstar();
+        // } catch (e) {
 
-        }
+        // }
     }
 
     componentDidMount() { window.onpopstate = this.onHistory; }
@@ -219,8 +217,8 @@ export class Main extends React.Component {
         let addTextNode = action(() => Docs.TextDocument({ borderRounding: -1, width: 200, height: 200, title: "a text note" }));
         let addColNode = action(() => Docs.FreeformDocument([], { width: 200, height: 200, title: "a freeform collection" }));
         let addSchemaNode = action(() => Docs.SchemaDocument([], { width: 200, height: 200, title: "a schema collection" }));
-        let addTreeNode = action(() => Docs.TreeDocument([CurrentUserUtils.UserDocument], { width: 250, height: 400, title: "Library:" + CurrentUserUtils.email, copyDraggedItems: true }));
-        // let addTreeNode = action(() => Docs.TreeDocument(this._northstarSchemas, { width: 250, height: 400, title: "northstar schemas", copyDraggedItems: true }));
+        let addTreeNode = action(() => Docs.TreeDocument([CurrentUserUtils.UserDocument], { width: 250, height: 400, title: "Library:" + CurrentUserUtils.email, dropAction: "alias" }));
+        // let addTreeNode = action(() => Docs.TreeDocument(this._northstarSchemas, { width: 250, height: 400, title: "northstar schemas", dropAction: "copy"  }));
         let addVideoNode = action(() => Docs.VideoDocument(videourl, { width: 200, title: "video node" }));
         let addPDFNode = action(() => Docs.PdfDocument(pdfurl, { width: 200, height: 200, title: "a pdf doc" }));
         let addImageNode = action(() => Docs.ImageDocument(imgurl, { width: 200, title: "an image of a cat" }));
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index bcbde24f0..a59bc196e 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -83,13 +83,13 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
         @action
         protected drop(e: Event, de: DragManager.DropEvent): boolean {
             if (de.data instanceof DragManager.DocumentDragData) {
-                if (de.data.aliasOnDrop || de.data.copyOnDrop) {
+                if (de.data.dropAction || de.data.userDropAction) {
                     ["width", "height", "curPage"].map(key =>
                         de.data.draggedDocuments.map((draggedDocument: Doc, i: number) =>
                             PromiseValue(Cast(draggedDocument[key], "number")).then(f => f && (de.data.droppedDocuments[i][key] = f))));
                 }
                 let added = false;
-                if (de.data.aliasOnDrop || de.data.copyOnDrop) {
+                if (de.data.dropAction || de.data.userDropAction) {
                     added = de.data.droppedDocuments.reduce((added: boolean, d) => {
                         let moved = this.props.addDocument(d);
                         return moved || added;
@@ -129,7 +129,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
             }
             if (type.indexOf("excel") !== -1) {
                 ctor = Docs.DBDocument;
-                options.copyDraggedItems = true;
+                options.dropAction = "copy";
             }
             if (type.indexOf("html") !== -1) {
                 if (path.includes('localhost')) {
diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss
index ecb5f78bb..d00785879 100644
--- a/src/client/views/collections/CollectionTreeView.scss
+++ b/src/client/views/collections/CollectionTreeView.scss
@@ -45,7 +45,8 @@
 
     .docContainer {
         margin-left: 10px;
-        display: inline-table;
+        display: block;
+        width: max-content;
     }
 
     .docContainer:hover {
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 0520e0f88..037703c46 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -3,7 +3,7 @@ import { faCaretDown, faCaretRight, faTrashAlt } from '@fortawesome/free-solid-s
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, observable } from "mobx";
 import { observer } from "mobx-react";
-import { DragManager, SetupDrag } from "../../util/DragManager";
+import { DragManager, SetupDrag, dropActionType } from "../../util/DragManager";
 import { EditableView } from "../EditableView";
 import { CollectionSubView } from "./CollectionSubView";
 import "./CollectionTreeView.scss";
@@ -12,8 +12,6 @@ import { Document, listSpec } from '../../../new_fields/Schema';
 import { Cast, StrCast, BoolCast, FieldValue } from '../../../new_fields/Types';
 import { Doc } from '../../../new_fields/Doc';
 import { Id } from '../../../new_fields/RefField';
-import { Utils } from '../../../Utils';
-import { JSXElement } from 'babel-types';
 import { ContextMenu } from '../ContextMenu';
 import { undoBatch } from '../../util/UndoManager';
 import { Main } from '../Main';
@@ -24,7 +22,7 @@ export interface TreeViewProps {
     document: Doc;
     deleteDoc: (doc: Doc) => void;
     moveDocument: DragManager.MoveFunction;
-    copyOnDrag: boolean;
+    dropAction: "alias" | "copy" | undefined;
 }
 
 export enum BulletType {
@@ -83,7 +81,7 @@ class TreeView extends React.Component<TreeViewProps> {
      */
     renderTitle() {
         let reference = React.createRef<HTMLDivElement>();
-        let onItemDown = SetupDrag(reference, () => this.props.document, this.props.moveDocument, this.props.copyOnDrag);
+        let onItemDown = SetupDrag(reference, () => this.props.document, this.props.moveDocument, this.props.dropAction);
         let editableView = (titleString: string) =>
             (<EditableView
                 display={"inline"}
@@ -91,14 +89,15 @@ class TreeView extends React.Component<TreeViewProps> {
                 height={36}
                 GetValue={() => StrCast(this.props.document.title)}
                 SetValue={(value: string) => {
-                    this.props.document.title = value;
+                    let target = this.props.document.proto ? this.props.document.proto : this.props.document;
+                    target.title = value;
                     return true;
                 }}
             />);
         return (
             <div className="docContainer" ref={reference} onPointerDown={onItemDown}>
                 {editableView(StrCast(this.props.document.title))}
-                <div className="delete-button" onClick={this.delete}><FontAwesomeIcon icon="trash-alt" size="xs" /></div>
+                {/* <div className="delete-button" onClick={this.delete}><FontAwesomeIcon icon="trash-alt" size="xs" /></div> */}
             </div >);
     }
 
@@ -117,7 +116,7 @@ class TreeView extends React.Component<TreeViewProps> {
             if (!this._collapsed) {
                 bulletType = BulletType.Collapsible;
                 contentElement = <ul>
-                    {TreeView.GetChildElements(children, this.remove, this.move, this.props.copyOnDrag)}
+                    {TreeView.GetChildElements(children, this.remove, this.move, this.props.dropAction)}
                 </ul >;
             }
             else bulletType = BulletType.Collapsed;
@@ -130,9 +129,9 @@ class TreeView extends React.Component<TreeViewProps> {
             </li>
         </div>;
     }
-    public static GetChildElements(docs: Doc[], remove: ((doc: Doc) => void), move: DragManager.MoveFunction, copyOnDrag: boolean) {
+    public static GetChildElements(docs: Doc[], remove: ((doc: Doc) => void), move: DragManager.MoveFunction, dropAction: dropActionType) {
         return docs.filter(child => !child.excludeFromLibrary).map(child =>
-            <TreeView document={child} key={child[Id]} deleteDoc={remove} moveDocument={move} copyOnDrag={copyOnDrag} />);
+            <TreeView document={child} key={child[Id]} deleteDoc={remove} moveDocument={move} dropAction={dropAction} />);
     }
 }
 
@@ -154,13 +153,13 @@ export class CollectionTreeView extends CollectionSubView(Document) {
     }
     render() {
         const children = this.children;
-        let copyOnDrag = BoolCast(this.props.Document.copyDraggedItems, false);
+        let dropAction = StrCast(this.props.Document.dropAction, "alias") as dropActionType;
         if (!children) {
             return (null);
         }
         let testForLibrary = children && children.length === 1 && children[0] === CurrentUserUtils.UserDocument;
         var subchildren = testForLibrary ? Cast(children[0].data, listSpec(Doc), children) : children;
-        let childElements = TreeView.GetChildElements(subchildren, this.remove, this.props.moveDocument, copyOnDrag);
+        let childElements = TreeView.GetChildElements(subchildren, this.remove, this.props.moveDocument, dropAction);
 
         return (
             <div id="body" className="collectionTreeView-dropTarget"
@@ -175,7 +174,8 @@ export class CollectionTreeView extends CollectionSubView(Document) {
                         height={72}
                         GetValue={() => StrCast(this.props.Document.title)}
                         SetValue={(value: string) => {
-                            this.props.Document.title = value;
+                            let target = this.props.Document.proto ? this.props.Document.proto : this.props.Document;
+                            target.title = value;
                             return true;
                         }} />
                 </div>
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 86d34725d..b151657e1 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -3,7 +3,7 @@ import { observer } from "mobx-react";
 import { emptyFunction, Utils } from "../../../Utils";
 import { Docs } from "../../documents/Documents";
 import { DocumentManager } from "../../util/DocumentManager";
-import { DragManager } from "../../util/DragManager";
+import { DragManager, dropActionType } from "../../util/DragManager";
 import { SelectionManager } from "../../util/SelectionManager";
 import { Transform } from "../../util/Transform";
 import { undoBatch, UndoManager } from "../../util/UndoManager";
@@ -129,12 +129,12 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         e.stopPropagation();
     }
 
-    startDragging(x: number, y: number, dropAliasOfDraggedDoc: boolean) {
+    startDragging(x: number, y: number, dropAction: dropActionType) {
         if (this._mainCont.current) {
             const [left, top] = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).inverse().transformPoint(0, 0);
             let dragData = new DragManager.DocumentDragData([this.props.Document]);
             const [xoff, yoff] = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).transformDirection(x - left, y - top);
-            dragData.aliasOnDrop = dropAliasOfDraggedDoc;
+            dragData.dropAction = dropAction;
             dragData.xOffset = xoff;
             dragData.yOffset = yoff;
             dragData.moveDocument = this.props.moveDocument;
@@ -142,7 +142,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 handlers: {
                     dragComplete: action(emptyFunction)
                 },
-                hideSource: !dropAliasOfDraggedDoc
+                hideSource: !dropAction
             });
         }
     }
@@ -162,7 +162,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         }
         if (e.shiftKey && e.buttons === 1) {
             if (this.props.isTopMost) {
-                this.startDragging(e.pageX, e.pageY, e.altKey || e.ctrlKey);
+                this.startDragging(e.pageX, e.pageY, e.altKey || e.ctrlKey ? "alias" : undefined);
             } else {
                 CollectionDockingView.Instance.StartOtherDrag([this.props.Document], e);
             }
@@ -180,7 +180,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 document.removeEventListener("pointermove", this.onPointerMove);
                 document.removeEventListener("pointerup", this.onPointerUp);
                 if (!e.altKey && !this.topMost && (!CollectionFreeFormView.RIGHT_BTN_DRAG && e.buttons === 1) || (CollectionFreeFormView.RIGHT_BTN_DRAG && e.buttons === 2)) {
-                    this.startDragging(this._downX, this._downY, e.ctrlKey || e.altKey);
+                    this.startDragging(this._downX, this._downY, e.ctrlKey || e.altKey ? "alias" : undefined);
                 }
             }
             e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document'  however it does mark the event as cancelBubble=true which we test for in the move event handlers
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 7f269a505..1d362bdaa 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -89,7 +89,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
             if (title && title.startsWith("-") && this._editorView) {
                 let str = this._editorView.state.doc.textContent;
                 let titlestr = str.substr(0, Math.min(40, str.length));
-                this.props.Document.title = "-" + titlestr + (str.length > 40 ? "..." : "");
+                let target = this.props.Document.proto ? this.props.Document.proto : this.props.Document;
+                target.title = "-" + titlestr + (str.length > 40 ? "..." : "");
             };
         }
     }
@@ -275,7 +276,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
         if (StrCast(this.props.Document.title).startsWith("-") && this._editorView) {
             let str = this._editorView.state.doc.textContent;
             let titlestr = str.substr(0, Math.min(40, str.length));
-            this.props.Document.title = "-" + titlestr + (str.length > 40 ? "..." : "");
+            let target = this.props.Document.proto ? this.props.Document.proto : this.props.Document;
+            target.title = "-" + titlestr + (str.length > 40 ? "..." : "");
         }
     }
     render() {
-- 
cgit v1.2.3-70-g09d2


From 9b33ac1cb790e88558edb3e4626f5a7b759ea3db Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 3 May 2019 14:46:31 -0400
Subject: added make button option.  summarize to text notes that can be frozen
 to resize.

---
 src/client/views/DocumentDecorations.tsx             |  1 +
 .../collections/collectionFreeForm/MarqueeView.tsx   | 20 +++++++++++++++-----
 .../views/nodes/CollectionFreeFormDocumentView.tsx   | 16 +++++++++-------
 src/client/views/nodes/DocumentView.tsx              | 10 +++++++++-
 src/client/views/nodes/FormattedTextBox.tsx          | 20 ++++++++++++++------
 5 files changed, 48 insertions(+), 19 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 2299f4c32..693d6ec55 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -255,6 +255,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
     @action createIcon = (selected: DocumentView[], layoutString: string): Doc => {
         let doc = selected[0].props.Document;
         let iconDoc = Docs.IconDocument(layoutString);
+        iconDoc.isButton = true;
         iconDoc.title = selected.length > 1 ? "ICONset" : "ICON" + StrCast(doc.title);
         iconDoc.labelField = this._fieldKey;
         iconDoc[this._fieldKey] = selected.length > 1 ? "collection" : undefined;
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 82027a6f2..8c81f6990 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -154,7 +154,8 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             e.stopPropagation();
             let bounds = this.Bounds;
             let selected = this.marqueeSelect().map(d => {
-                this.props.removeDocument(d);
+                if (e.key !== "r")
+                    this.props.removeDocument(d);
                 d.x = NumCast(d.x) - bounds.left - bounds.width / 2;
                 d.y = NumCast(d.y) - bounds.top - bounds.height / 2;
                 d.page = -1;
@@ -180,12 +181,21 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             // SelectionManager.DeselectAll();
             if (e.key === "r") {
                 let summary = Docs.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" });
-                summary.doc1 = selected[0];
-                if (selected.length > 1)
-                    summary.doc2 = selected[1];
-                summary.templates = new List<string>([Templates.Summary.Layout]);
+                summary.maximizedDocs = new List<Doc>(selected);
+                // summary.doc1 = selected[0];
+                // if (selected.length > 1)
+                //     summary.doc2 = selected[1];
+                // summary.templates = new List<string>([Templates.Summary.Layout]);
                 this.props.addLiveTextDocument(summary);
                 e.preventDefault();
+                let scrpt = this.props.getTransform().inverse().transformPoint(bounds.left, bounds.top);
+                selected.map(maximizedDoc => {
+                    let maxx = NumCast(maximizedDoc.x, undefined);
+                    let maxy = NumCast(maximizedDoc.y, undefined);
+                    let maxw = NumCast(maximizedDoc.width, undefined);
+                    let maxh = NumCast(maximizedDoc.height, undefined);
+                    maximizedDoc.isIconAnimating = new List<number>([scrpt[0], scrpt[1], maxx, maxy, maxw, maxh, Date.now(), 0])
+                });
             }
             else {
                 this.props.addDocument(newCollection, false);
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 741af82fd..2ba0458f5 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -138,8 +138,8 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
                     if (isMinimized === undefined) {
                         isMinimized = BoolCast(maximizedDoc.isMinimized, false);
                     }
-                    let minx = NumCast(minimizedTarget.x, undefined);
-                    let miny = NumCast(minimizedTarget.y, undefined);
+                    let minx = NumCast(minimizedTarget.x, undefined) + NumCast(minimizedTarget.width, undefined) / 2;
+                    let miny = NumCast(minimizedTarget.y, undefined) + NumCast(minimizedTarget.height, undefined) / 2;
                     let maxx = NumCast(maximizedDoc.x, undefined);
                     let maxy = NumCast(maximizedDoc.y, undefined);
                     let maxw = NumCast(maximizedDoc.width, undefined);
@@ -164,11 +164,13 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
         let ctrlKey = e.ctrlKey;
         if (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD &&
             Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD) {
-            let maximizedDocs = await Cast(this.props.Document.maximizedDocs, listSpec(Doc));
-            if (maximizedDocs) {   // bcz: need a better way to associate behaviors with click events on widget-documents
-                if (ctrlKey)
-                    this.props.addDocument && maximizedDocs.filter(d => d instanceof Doc).map(maxDoc => this.props.addDocument!(maxDoc, false));
-                this.toggleIcon();
+            if (await BoolCast(this.props.Document.isButton, false)) {
+                let maximizedDocs = await Cast(this.props.Document.maximizedDocs, listSpec(Doc));
+                if (maximizedDocs) {   // bcz: need a better way to associate behaviors with click events on widget-documents
+                    if (ctrlKey)
+                        this.props.addDocument && maximizedDocs.filter(d => d instanceof Doc).map(maxDoc => this.props.addDocument!(maxDoc, false));
+                    this.toggleIcon();
+                }
             }
         }
     }
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 892850a69..c08e322c0 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -16,7 +16,7 @@ import { Template, Templates } from "./../Templates";
 import { DocumentContentsView } from "./DocumentContentsView";
 import "./DocumentView.scss";
 import React = require("react");
-import { Opt, Doc } from "../../../new_fields/Doc";
+import { Opt, Doc, WidthSym, HeightSym } from "../../../new_fields/Doc";
 import { DocComponent } from "../DocComponent";
 import { createSchema, makeInterface } from "../../../new_fields/Schema";
 import { FieldValue, StrCast, BoolCast } from "../../../new_fields/Types";
@@ -200,6 +200,13 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         let kvp = Docs.KVPDocument(this.props.Document, { width: 300, height: 300 });
         CollectionDockingView.Instance.AddRightSplit(kvp);
     }
+    makeButton = (e: React.MouseEvent): void => {
+        this.props.Document.isButton = !BoolCast(this.props.Document.isButton, false);
+        if (this.props.Document.isButton && !this.props.Document.nativeWidth) {
+            this.props.Document.nativeWidth = this.props.Document[WidthSym]();
+            this.props.Document.nativeHeight = this.props.Document[HeightSym]();
+        }
+    }
     fullScreenClicked = (e: React.MouseEvent): void => {
         const doc = Doc.MakeDelegate(FieldValue(this.Document.proto));
         if (doc) {
@@ -263,6 +270,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         e.preventDefault();
 
         ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked });
+        ContextMenu.Instance.addItem({ description: this.props.Document.isButton ? "Remove Button" : "Make Button", event: this.makeButton });
         ContextMenu.Instance.addItem({ description: "Fields", event: this.fieldsClicked });
         ContextMenu.Instance.addItem({ description: "Center", event: () => this.props.focus(this.props.Document) });
         ContextMenu.Instance.addItem({ description: "Open Right", event: () => CollectionDockingView.Instance.AddRightSplit(this.props.Document) });
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 1d362bdaa..eeb60cb3d 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -17,10 +17,10 @@ import React = require("react");
 import { SelectionManager } from "../../util/SelectionManager";
 import { DocComponent } from "../DocComponent";
 import { createSchema, makeInterface } from "../../../new_fields/Schema";
-import { Opt, Doc } from "../../../new_fields/Doc";
+import { Opt, Doc, WidthSym, HeightSym } from "../../../new_fields/Doc";
 import { observer } from "mobx-react";
 import { InkingControl } from "../InkingControl";
-import { StrCast, Cast, NumCast } from "../../../new_fields/Types";
+import { StrCast, Cast, NumCast, BoolCast } from "../../../new_fields/Types";
 import { RichTextField } from "../../../new_fields/RichTextField";
 import { Id } from "../../../new_fields/RefField";
 const { buildMenuItems } = require("prosemirror-example-setup");
@@ -128,7 +128,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
             );
         } else {
             this._proxyReactionDisposer = reaction(() => this.props.isSelected(),
-                () => this.props.isSelected() && MainOverlayTextBox.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform));
+                () => this.props.isSelected() && !BoolCast(this.props.Document.isButton, false) && MainOverlayTextBox.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform));
         }
 
 
@@ -203,15 +203,23 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
     }
 
     //REPLACE THIS WITH CAPABILITIES SPECIFIC TO THIS TYPE OF NODE
-    textCapability = (e: React.MouseEvent): void => { };
+    textCapability = (e: React.MouseEvent): void => {
+        if (NumCast(this.props.Document.nativeWidth)) {
+            this.props.Document.nativeWidth = undefined;
+            this.props.Document.nativeHeight = undefined;
 
+        } else {
+            this.props.Document.nativeWidth = this.props.Document[WidthSym]();
+            this.props.Document.nativeHeight = this.props.Document[HeightSym]();
+        }
+    }
     specificContextMenu = (e: React.MouseEvent): void => {
         if (!this._gotDown) {
             e.preventDefault();
             return;
         }
         ContextMenu.Instance.addItem({
-            description: "Text Capability",
+            description: NumCast(this.props.Document.nativeWidth) ? "Unfreeze" : "Freeze",
             event: this.textCapability
         });
 
@@ -302,7 +310,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
                 // tfs: do we need this event handler
                 onWheel={this.onPointerWheel}
             >
-                <div className={`formattedTextBox-inner${rounded}`} ref={this._proseRef} />
+                <div className={`formattedTextBox-inner${rounded}`} style={{ pointerEvents: this.props.Document.isButton ? "none" : "all" }} ref={this._proseRef} />
             </div>
         );
     }
-- 
cgit v1.2.3-70-g09d2

