From ec2b0b56058fce137ff28ae3ec125f9e695f315c Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Tue, 19 Feb 2019 05:19:50 -0500
Subject: Changed some names, added some comments, and got rid of some unused
 stuff

---
 .../views/collections/CollectionFreeFormView.tsx   | 42 +++++++++++-----------
 1 file changed, 21 insertions(+), 21 deletions(-)

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

diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index eca8a0adf..2c0a3f478 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -31,18 +31,18 @@ export class CollectionFreeFormView extends CollectionViewBase {
     }
 
     @computed
-    get isAnnotationOverlay() { return this.props.CollectionFieldKey == KeyStore.Annotations; }
+    get isAnnotationOverlay() { return this.props.fieldKey == KeyStore.Annotations; }
 
     @computed
-    get nativeWidth() { return this.props.DocumentForCollection.GetNumber(KeyStore.NativeWidth, 0); }
+    get nativeWidth() { return this.props.Document.GetNumber(KeyStore.NativeWidth, 0); }
     @computed
-    get nativeHeight() { return this.props.DocumentForCollection.GetNumber(KeyStore.NativeHeight, 0); }
+    get nativeHeight() { return this.props.Document.GetNumber(KeyStore.NativeHeight, 0); }
 
     @computed
-    get zoomScaling() { return this.props.DocumentForCollection.GetNumber(KeyStore.Scale, 1); }
+    get zoomScaling() { return this.props.Document.GetNumber(KeyStore.Scale, 1); }
 
     @computed
-    get resizeScaling() { return this.isAnnotationOverlay ? this.props.DocumentForCollection.GetNumber(KeyStore.Width, 0) / this.nativeWidth : 1; }
+    get resizeScaling() { return this.isAnnotationOverlay ? this.props.Document.GetNumber(KeyStore.Width, 0) / this.nativeWidth : 1; }
 
     @action
     drop = (e: Event, de: DragManager.DropEvent) => {
@@ -105,8 +105,8 @@ export class CollectionFreeFormView extends CollectionViewBase {
         if (!e.cancelBubble && this.active) {
             e.preventDefault();
             e.stopPropagation();
-            let x = this.props.DocumentForCollection.GetNumber(KeyStore.PanX, 0);
-            let y = this.props.DocumentForCollection.GetNumber(KeyStore.PanY, 0);
+            let x = this.props.Document.GetNumber(KeyStore.PanX, 0);
+            let y = this.props.Document.GetNumber(KeyStore.PanY, 0);
             let [dx, dy] = this.props.ScreenToLocalTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY);
 
             this.SetPan(x + dx, y + dy);
@@ -131,7 +131,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
         let localTransform = this.getLocalTransform();
         localTransform = localTransform.inverse().scaleAbout(deltaScale, x, y)
 
-        this.props.DocumentForCollection.SetNumber(KeyStore.Scale, localTransform.Scale);
+        this.props.Document.SetNumber(KeyStore.Scale, localTransform.Scale);
         this.SetPan(localTransform.TranslateX, localTransform.TranslateY);
     }
 
@@ -139,8 +139,8 @@ export class CollectionFreeFormView extends CollectionViewBase {
     private SetPan(panX: number, panY: number) {
         const newPanX = Math.max((1 - this.zoomScaling) * this.nativeWidth, Math.min(0, panX));
         const newPanY = Math.max((1 - this.zoomScaling) * this.nativeHeight, Math.min(0, panY));
-        this.props.DocumentForCollection.SetNumber(KeyStore.PanX, this.isAnnotationOverlay ? newPanX : panX);
-        this.props.DocumentForCollection.SetNumber(KeyStore.PanY, this.isAnnotationOverlay ? newPanY : panY);
+        this.props.Document.SetNumber(KeyStore.PanX, this.isAnnotationOverlay ? newPanX : panX);
+        this.props.Document.SetNumber(KeyStore.PanY, this.isAnnotationOverlay ? newPanY : panY);
     }
 
     @action
@@ -150,8 +150,8 @@ export class CollectionFreeFormView extends CollectionViewBase {
         let fReader = new FileReader()
         let file = e.dataTransfer.items[0].getAsFile();
         let that = this;
-        const panx: number = this.props.DocumentForCollection.GetNumber(KeyStore.PanX, 0);
-        const pany: number = this.props.DocumentForCollection.GetNumber(KeyStore.PanY, 0);
+        const panx: number = this.props.Document.GetNumber(KeyStore.PanX, 0);
+        const pany: number = this.props.Document.GetNumber(KeyStore.PanY, 0);
         let x = e.pageX - panx
         let y = e.pageY - pany
 
@@ -161,11 +161,11 @@ export class CollectionFreeFormView extends CollectionViewBase {
                 let doc = Documents.ImageDocument(url, {
                     x: x, y: y
                 })
-                let docs = that.props.DocumentForCollection.GetT(KeyStore.Data, ListField);
+                let docs = that.props.Document.GetT(KeyStore.Data, ListField);
                 if (docs != FieldWaiting) {
                     if (!docs) {
                         docs = new ListField<Document>();
-                        that.props.DocumentForCollection.Set(KeyStore.Data, docs)
+                        that.props.Document.Set(KeyStore.Data, docs)
                     }
                     docs.Data.push(doc);
                 }
@@ -182,7 +182,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
 
     @action
     bringToFront(doc: DocumentView) {
-        const { CollectionFieldKey: fieldKey, DocumentForCollection: Document } = this.props;
+        const { fieldKey: fieldKey, Document: Document } = this.props;
 
         const value: Document[] = Document.GetList<Document>(fieldKey, []);
         var topmost = value.reduce((topmost, d) => Math.max(d.GetNumber(KeyStore.ZIndex, 0), topmost), -1000);
@@ -200,14 +200,14 @@ export class CollectionFreeFormView extends CollectionViewBase {
 
     @computed
     get translate(): [number, number] {
-        const x = this.props.DocumentForCollection.GetNumber(KeyStore.PanX, 0);
-        const y = this.props.DocumentForCollection.GetNumber(KeyStore.PanY, 0);
+        const x = this.props.Document.GetNumber(KeyStore.PanX, 0);
+        const y = this.props.Document.GetNumber(KeyStore.PanY, 0);
         return [x, y];
     }
 
     @computed
     get scale(): number {
-        return this.props.DocumentForCollection.GetNumber(KeyStore.Scale, 1);
+        return this.props.Document.GetNumber(KeyStore.Scale, 1);
     }
 
     getTransform = (): Transform => {
@@ -220,8 +220,8 @@ export class CollectionFreeFormView extends CollectionViewBase {
     }
 
     render() {
-        const Document: Document = this.props.DocumentForCollection;
-        const value: Document[] = Document.GetList<Document>(this.props.CollectionFieldKey, []);
+        const Document: Document = this.props.Document;
+        const value: Document[] = Document.GetList<Document>(this.props.fieldKey, []);
         const panx: number = Document.GetNumber(KeyStore.PanX, 0);
         const pany: number = Document.GetNumber(KeyStore.PanY, 0);
         var me = this;
@@ -249,7 +249,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
                             ScreenToLocalTransform={this.getTransform}
                             isTopMost={false}
                             Scaling={1}
-                            ContainingCollectionView={this} DocumentView={this.props.ContainingDocumentView} />);
+                            ContainingCollectionView={this} />);
                     })}
                 </div>
             </div>
-- 
cgit v1.2.3-70-g09d2


From 813b5cbf0bb756bdb781707572622a57f8ec5d8a Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 19 Feb 2019 20:47:39 -0500
Subject: fixed doc decs so they don't appear on topmost collections

---
 src/client/views/DocumentDecorations.tsx                | 3 +--
 src/client/views/collections/CollectionFreeFormView.tsx | 3 +--
 src/client/views/nodes/DocumentView.tsx                 | 4 ++--
 3 files changed, 4 insertions(+), 6 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 7985b77dd..770433e27 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -23,8 +23,7 @@ export class DocumentDecorations extends React.Component {
     @computed
     get Bounds(): { x: number, y: number, b: number, r: number } {
         return SelectionManager.SelectedDocuments().reduce((bounds, element) => {
-            if (element.props.ContainingCollectionView != undefined &&
-                !(element.props.ContainingCollectionView instanceof CollectionFreeFormView)) {
+            if (element.props.isTopMost) {
                 return bounds;
             }
             let transform = element.props.ScreenToLocalTransform().inverse();
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index 1f15069fd..ce480acd1 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -40,7 +40,6 @@ export class CollectionFreeFormView extends CollectionViewBase {
     @action
     drop = (e: Event, de: DragManager.DropEvent) => {
         const doc: DocumentView = de.data["document"];
-        var me = this;
         if (doc.props.ContainingCollectionView && doc.props.ContainingCollectionView !== this) {
             doc.props.ContainingCollectionView.removeDocument(doc.props.Document);
             this.addDocument(doc.props.Document);
@@ -48,7 +47,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
         const xOffset = de.data["xOffset"] as number || 0;
         const yOffset = de.data["yOffset"] as number || 0;
         //this should be able to use translate and scale methods on an Identity transform, no?
-        const transform = me.getTransform();
+        const transform = this.getTransform();
         const screenX = de.x - xOffset;
         const screenY = de.y - yOffset;
         const [x, y] = transform.transformPoint(screenX, screenY);
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 518add0fc..97bcdd333 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -112,7 +112,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
 
     @computed
     get active(): boolean {
-        return SelectionManager.IsSelected(this) || this.props.ContainingCollectionView === undefined ||
+        return SelectionManager.IsSelected(this) || !this.props.ContainingCollectionView ||
             this.props.ContainingCollectionView.active;
     }
 
@@ -146,7 +146,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
 
     @computed
     get topMost(): boolean {
-        return this.props.ContainingCollectionView == undefined || this.props.ContainingCollectionView instanceof CollectionDockingView;
+        return !this.props.ContainingCollectionView || this.props.ContainingCollectionView instanceof CollectionDockingView;
     }
 
     onPointerMove = (e: PointerEvent): void => {
-- 
cgit v1.2.3-70-g09d2


From ef10a6bdf753f75cbc5b5d8b7dcc53c3d4c219ad Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Tue, 19 Feb 2019 21:53:57 -0500
Subject: cleanup and made bring to front work better

---
 .../views/collections/CollectionFreeFormView.tsx   | 22 +++++++++++-----------
 src/client/views/nodes/DocumentView.tsx            |  3 +--
 2 files changed, 12 insertions(+), 13 deletions(-)

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

diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index ce480acd1..54757cce5 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -179,18 +179,18 @@ export class CollectionFreeFormView extends CollectionViewBase {
     bringToFront(doc: DocumentView) {
         const { fieldKey: fieldKey, Document: Document } = this.props;
 
-        const value: Document[] = Document.GetList<Document>(fieldKey, []);
-        var topmost = value.reduce((topmost, d) => Math.max(d.GetNumber(KeyStore.ZIndex, 0), topmost), -1000);
-        value.map(d => {
-            var zind = d.GetNumber(KeyStore.ZIndex, 0);
-            if (zind != topmost - 1 - (topmost - zind) && d != doc.props.Document) {
-                d.SetData(KeyStore.ZIndex, topmost - 1 - (topmost - zind), NumberField);
+        const value: Document[] = Document.GetList<Document>(fieldKey, []).slice();
+        value.sort((doc1, doc2) => {
+            if (doc1 === doc.props.Document) {
+                return 1;
             }
-        })
-
-        if (doc.props.Document.GetNumber(KeyStore.ZIndex, 0) != 0) {
-            doc.props.Document.SetData(KeyStore.ZIndex, 0, NumberField);
-        }
+            if (doc2 === doc.props.Document) {
+                return -1;
+            }
+            return doc1.GetNumber(KeyStore.ZIndex, 0) - doc2.GetNumber(KeyStore.ZIndex, 0);
+        }).map((doc, index) => {
+            doc.SetNumber(KeyStore.ZIndex, index + 1)
+        });
     }
 
     @computed
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 4ad3a2dd7..3a4dbb2d5 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -246,8 +246,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     }
 
     screenToLocalTransform = () => {
-        var parentScrToLocalXf = this.props && this.props.ScreenToLocalTransform ? this.props.ScreenToLocalTransform() : new Transform(0, 0, 1);
-        return parentScrToLocalXf.transform(new Transform(0, 0, this.props ? 1 / this.props.Scaling : 1));
+        return this.props.ScreenToLocalTransform().transform(Transform.Identity.scale(1 / this.props.Scaling));
     }
     render() {
         let lkeys = this.props.Document.GetT(KeyStore.LayoutKeys, ListField);
-- 
cgit v1.2.3-70-g09d2


From 81b5269e4e934523a6dd69cf066f3e6c4e58019f Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 20 Feb 2019 17:29:53 -0500
Subject: working, but oh so confusing transforms for selections.

---
 src/client/views/DocumentDecorations.tsx           |  8 ++--
 .../views/collections/CollectionDockingView.tsx    |  1 +
 .../views/collections/CollectionFreeFormView.tsx   |  1 +
 .../views/collections/CollectionSchemaView.tsx     | 49 +++++++++++++++++++---
 src/client/views/nodes/DocumentView.tsx            | 35 ++++++++++++----
 5 files changed, 77 insertions(+), 17 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index dccab1dc5..0aaea7ae5 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -25,11 +25,13 @@ export class DocumentDecorations extends React.Component {
             if (element.props.isTopMost) {
                 return bounds;
             }
-            let transform = element.props.ScreenToLocalTransform().inverse();
+            let transform = element.ScreenToLocalTransform().inverse();
             var [sptX, sptY] = transform.transformPoint(0, 0);
-            // var [bptX, bptY] = transform.transformDirection(element.width, element.height);
             let doc = element.props.Document;
-            let [bptX, bptY] = [doc.GetNumber(KeyStore.Width, 0), doc.GetNumber(KeyStore.Height, 0)];
+            let [bptX, bptY] = [
+                element.props.PanelSize[0] > 0 ? element.props.PanelSize[0] : doc.GetNumber(KeyStore.Width, 0),
+                element.props.PanelSize[1] > 0 ? element.props.PanelSize[1] : doc.GetNumber(KeyStore.Height, 0)
+            ];
             [bptX, bptY] = transform.transformPoint(bptX, bptY);
             return {
                 x: Math.min(sptX, bounds.x), y: Math.min(sptY, bounds.y),
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index ceb638ab4..fc5b8dacd 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -253,6 +253,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
                     AddDocument={undefined}
                     RemoveDocument={undefined}
                     Scaling={this._parentScaling}
+                    PanelSize={[0, 0]}
                     ScreenToLocalTransform={() => {
                         let { scale, translateX, translateY } = Utils.GetScreenTransform(this._mainCont);
                         var props = CollectionDockingView.Instance.props;
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index 54757cce5..ffd4d211f 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -247,6 +247,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
                             ScreenToLocalTransform={this.getTransform}
                             isTopMost={false}
                             Scaling={1}
+                            PanelSize={[0, 0]}
                             ContainingCollectionView={this} />);
                     })}
                 </div>
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index fa37e0e76..0c7577421 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -1,5 +1,5 @@
 import React = require("react")
-import { action, observable } from "mobx";
+import { action, computed, observable } from "mobx";
 import { observer } from "mobx-react";
 import Measure from "react-measure";
 import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table";
@@ -14,6 +14,7 @@ import { DocumentView } from "../nodes/DocumentView";
 import { FieldView, FieldViewProps } from "../nodes/FieldView";
 import "./CollectionSchemaView.scss";
 import { CollectionViewBase, COLLECTION_BORDER_WIDTH } from "./CollectionViewBase";
+import { Z_DEFAULT_COMPRESSION } from "zlib";
 
 @observer
 export class CollectionSchemaView extends CollectionViewBase {
@@ -117,26 +118,63 @@ export class CollectionSchemaView extends CollectionViewBase {
     }
 
     innerScreenToLocal(tx: number, ty: number) {
-        return () => this.props.ScreenToLocalTransform().transform(new Transform(-tx - 5 - COLLECTION_BORDER_WIDTH, -ty - COLLECTION_BORDER_WIDTH, 1))
+        var zoom = this.props.Document.GetNumber(KeyStore.Scale, 1);
+        var xf = this.props.ScreenToLocalTransform().transform(new Transform(- 5 - COLLECTION_BORDER_WIDTH, - COLLECTION_BORDER_WIDTH, 1)).translate(-tx, -ty);
+        var center = [0, 0];
+        var sabout = new Transform(center[0] / zoom, center[1] / zoom, 1).scaled(1 / this._parentScaling).translated(-center[0] / zoom, -center[1] / zoom);
+        var total = xf.transformed(sabout);
+        return () => total
+    }
+    @computed
+    get scale(): number {
+        return this.props.Document.GetNumber(KeyStore.Scale, 1);
+    }
+    @computed
+    get translate(): [number, number] {
+        const x = this.props.Document.GetNumber(KeyStore.PanX, 0);
+        const y = this.props.Document.GetNumber(KeyStore.PanY, 0);
+        return [x, y];
+    }
+
+    getTransform = (): Transform => {
+        return this.props.ScreenToLocalTransform().translate(- COLLECTION_BORDER_WIDTH - this._dividerX - 5, - COLLECTION_BORDER_WIDTH).transform(this.getLocalTransform())
+    }
+
+    getLocalTransform = (): Transform => {
+        const [x, y] = this.translate;
+        return Transform.Identity.translate(-x, -y).scale(1 / this.scale / this._parentScaling);
+    }
+
+    @action
+    setScaling = (r: any) => {
+        var me = this;
+        const children = this.props.Document.GetList<Document>(this.props.fieldKey, []);
+        const selected = children.length > this.selectedIndex ? children[this.selectedIndex] : undefined;
+        this._panelWidth = r.entry.width;
+        if (r.entry.height)
+            this._panelHeight = r.entry.height;
+        me._parentScaling = r.entry.width / selected!.GetNumber(KeyStore.NativeWidth, r.entry.width);
     }
 
     @observable _parentScaling = 1; // used to transfer the dimensions of the content pane in the DOM to the ParentScaling prop of the DocumentView
     @observable _dividerX = 0;
-    @observable _dividerY = 0;
+    @observable _panelWidth = 0;
+    @observable _panelHeight = 0;
     render() {
         const columns = this.props.Document.GetList(KeyStore.ColumnsKey, [KeyStore.Title, KeyStore.Data, KeyStore.Author])
         const children = this.props.Document.GetList<Document>(this.props.fieldKey, []);
         const selected = children.length > this.selectedIndex ? children[this.selectedIndex] : undefined;
         let me = this;
         let content = this.selectedIndex == -1 || !selected ? (null) : (
-            <Measure onResize={action((r: any) => this._parentScaling = r.entry.width / selected.GetNumber(KeyStore.NativeWidth, r.entry.width))}>
+            <Measure onResize={this.setScaling}>
                 {({ measureRef }) =>
                     <div ref={measureRef}>
                         <DocumentView Document={selected}
                             AddDocument={this.addDocument} RemoveDocument={this.removeDocument}
-                            ScreenToLocalTransform={this.innerScreenToLocal(me._dividerX, me._dividerY)}//TODO This should probably be an actual transform
+                            ScreenToLocalTransform={this.getTransform}//TODO This should probably be an actual transform
                             Scaling={this._parentScaling}
                             isTopMost={false}
+                            PanelSize={[this._panelWidth, this._panelHeight]}
                             ContainingCollectionView={me} />
                     </div>
                 }
@@ -146,6 +184,7 @@ export class CollectionSchemaView extends CollectionViewBase {
             <div onPointerDown={this.onPointerDown} ref={this._mainCont} className="collectionSchemaView-container" style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }} >
                 <Measure onResize={action((r: any) => {
                     this._dividerX = r.entry.width;
+                    this._panelHeight = r.entry.height;
                 })}>
                     {({ measureRef }) =>
                         <div ref={measureRef} className="collectionSchemaView-tableContainer" style={{ position: "relative", float: "left", width: `${this._splitPercentage}%`, height: "100%" }}>
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index e9b1d5c8a..fa39ad09a 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -31,6 +31,7 @@ export interface DocumentViewProps {
     isTopMost: boolean;
     //tfs: This shouldn't be necessary I don't think
     Scaling: number;
+    PanelSize: number[];
 }
 export interface JsxArgs extends DocumentViewProps {
     Keys: { [name: string]: Key }
@@ -245,8 +246,19 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         SelectionManager.SelectDoc(this, ctrlPressed)
     }
 
-    screenToLocalTransform = () => {
-        return this.props.ScreenToLocalTransform().transform(Transform.Identity.scale(1 / this.props.Scaling));
+    ScreenToLocalTransform = () => {
+        return this.props.PanelSize[0] ? this.backgroundScreenToLocalTransform() : this.props.ScreenToLocalTransform();
+    }
+
+    backgroundScreenToLocalTransform = () => {
+        if (this.props.PanelSize[0])
+            return this.props.ScreenToLocalTransform().scale(this.props.Scaling);
+        else return this.props.ScreenToLocalTransform().scale(1 / this.props.Scaling);
+    }
+    documentScreenToLocalTransform = () => {
+        if (this.props.PanelSize[0])
+            return this.props.ScreenToLocalTransform();
+        else return this.backgroundScreenToLocalTransform();
     }
     render() {
         if (!this.props.Document)
@@ -255,18 +267,23 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         if (!lkeys || lkeys === "<Waiting>") {
             return <p>Error loading layout keys</p>;
         }
-        let bindings = {
+        let backgroundBindings = {
             ...this.props,
-            ScreenToLocalTransform: this.screenToLocalTransform, // adds 'Scaling' to the screen to local Xf
+            ScreenToLocalTransform: this.backgroundScreenToLocalTransform, // adds 'Scaling' to the screen to local Xf
             isSelected: this.isSelected,
             select: this.select
         } as any;
         for (const key of this.layoutKeys) {
-            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
+            backgroundBindings[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) {
             let field = this.props.Document.Get(key);
-            bindings[key.Name] = field && field != FieldWaiting ? field.GetValue() : field;
+            backgroundBindings[key.Name] = field && field != FieldWaiting ? field.GetValue() : field;
+        }
+
+        let documentBindings = {
+            ...backgroundBindings,
+            ScreenToLocalTransform: this.documentScreenToLocalTransform, // adds 'Scaling' to the screen to local Xf
         }
         /*
         tfs:
@@ -278,12 +295,12 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         if (backgroundLayout) {
             let backgroundView = () => (<JsxParser
                 components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView }}
-                bindings={bindings}
+                bindings={backgroundBindings}
                 jsx={this.backgroundLayout}
                 showWarnings={true}
                 onError={(test: any) => { console.log(test) }}
             />);
-            bindings.BackgroundView = backgroundView;
+            documentBindings.BackgroundView = backgroundView;
         }
 
         var width = this.props.Document.GetNumber(KeyStore.NativeWidth, 0);
@@ -297,7 +314,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
                 onPointerDown={this.onPointerDown} >
                 <JsxParser
                     components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView }}
-                    bindings={bindings}
+                    bindings={documentBindings}
                     jsx={this.layout}
                     showWarnings={true}
                     onError={(test: any) => { console.log(test) }}
-- 
cgit v1.2.3-70-g09d2


From d500c57290bff9d82d542b5756601b466a46c8c7 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 20 Feb 2019 19:42:24 -0500
Subject: cleaned up screen transforms at last.

---
 src/client/views/DocumentDecorations.tsx            |  9 ++-------
 .../views/collections/CollectionFreeFormView.tsx    |  2 +-
 .../views/nodes/CollectionFreeFormDocumentView.tsx  |  9 +++++++--
 src/client/views/nodes/DocumentView.tsx             | 21 +--------------------
 4 files changed, 11 insertions(+), 30 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 0aaea7ae5..4e109d475 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -25,14 +25,9 @@ export class DocumentDecorations extends React.Component {
             if (element.props.isTopMost) {
                 return bounds;
             }
-            let transform = element.ScreenToLocalTransform().inverse();
+            let transform = (element.props.ScreenToLocalTransform().scale(element.props.Scaling)).inverse();
             var [sptX, sptY] = transform.transformPoint(0, 0);
-            let doc = element.props.Document;
-            let [bptX, bptY] = [
-                element.props.PanelSize[0] > 0 ? element.props.PanelSize[0] : doc.GetNumber(KeyStore.Width, 0),
-                element.props.PanelSize[1] > 0 ? element.props.PanelSize[1] : doc.GetNumber(KeyStore.Height, 0)
-            ];
-            [bptX, bptY] = transform.transformPoint(bptX, bptY);
+            let [bptX, bptY] = transform.transformPoint(element.props.PanelSize[0], element.props.PanelSize[1]);
             return {
                 x: Math.min(sptX, bounds.x), y: Math.min(sptY, bounds.y),
                 r: Math.max(bptX, bounds.r), b: Math.max(bptY, bounds.b)
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index ffd4d211f..412a4d03d 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -247,7 +247,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
                             ScreenToLocalTransform={this.getTransform}
                             isTopMost={false}
                             Scaling={1}
-                            PanelSize={[0, 0]}
+                            PanelSize={[doc.GetNumber(KeyStore.Width, 0), doc.GetNumber(KeyStore.Height, 0)]}
                             ContainingCollectionView={this} />);
                     })}
                 </div>
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index bb85f85a3..7cad6ffc1 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -77,7 +77,9 @@ export class CollectionFreeFormDocumentView extends React.Component<DocumentView
 
 
     getTransform = (): Transform => {
-        return this.props.ScreenToLocalTransform().translate(-this.props.Document.GetNumber(KeyStore.X, 0), -this.props.Document.GetNumber(KeyStore.Y, 0));
+        var parentScaling = this.nativeWidth > 0 ? this.width / this.nativeWidth : 1;
+        return this.props.ScreenToLocalTransform().
+            translate(-this.props.Document.GetNumber(KeyStore.X, 0), -this.props.Document.GetNumber(KeyStore.Y, 0)).scale(1 / parentScaling);
     }
 
     render() {
@@ -93,7 +95,10 @@ export class CollectionFreeFormDocumentView extends React.Component<DocumentView
                 backgroundColor: "transparent"
             }} >
 
-                <DocumentView {...this.props} Scaling={parentScaling} ScreenToLocalTransform={this.getTransform} />
+                <DocumentView {...this.props}
+                    Scaling={parentScaling}
+                    ScreenToLocalTransform={this.getTransform}
+                />
             </div>
         );
     }
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 4eb49f18f..20875586d 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -246,20 +246,6 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         SelectionManager.SelectDoc(this, ctrlPressed)
     }
 
-    ScreenToLocalTransform = () => {
-        return this.props.PanelSize[0] ? this.backgroundScreenToLocalTransform() : this.props.ScreenToLocalTransform();
-    }
-
-    backgroundScreenToLocalTransform = () => {
-        if (this.props.PanelSize[0])
-            return this.props.ScreenToLocalTransform().scale(this.props.Scaling);
-        else return this.props.ScreenToLocalTransform().scale(1 / this.props.Scaling);
-    }
-    documentScreenToLocalTransform = () => {
-        if (this.props.PanelSize[0])
-            return this.props.ScreenToLocalTransform();
-        else return this.backgroundScreenToLocalTransform();
-    }
     render() {
         if (!this.props.Document)
             return <div></div>
@@ -269,7 +255,6 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         }
         let documentBindings = {
             ...this.props,
-            ScreenToLocalTransform: this.documentScreenToLocalTransform, // adds 'Scaling' to the screen to local Xf
             isSelected: this.isSelected,
             select: this.select
         } as any;
@@ -289,13 +274,9 @@ export class DocumentView extends React.Component<DocumentViewProps> {
          */
         let backgroundLayout = this.backgroundLayout;
         if (backgroundLayout) {
-            let backgroundBindings = {
-                ...documentBindings,
-                ScreenToLocalTransform: this.backgroundScreenToLocalTransform, // adds 'Scaling' to the screen to local Xf
-            }
             let backgroundView = () => (<JsxParser
                 components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView }}
-                bindings={backgroundBindings}
+                bindings={documentBindings}
                 jsx={this.backgroundLayout}
                 showWarnings={true}
                 onError={(test: any) => { console.log(test) }}
-- 
cgit v1.2.3-70-g09d2


From d218c0998b333c9bf6e905e999ce8b0bf02a72f7 Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Wed, 20 Feb 2019 20:18:21 -0500
Subject: Added undo/redo

---
 src/client/util/UndoManager.ts                     | 121 +++++++++++++++++++++
 src/client/views/Main.tsx                          |  24 ++++
 .../views/collections/CollectionFreeFormView.tsx   |   2 +
 src/fields/BasicField.ts                           |  11 +-
 src/fields/Document.ts                             |  10 +-
 src/fields/ListField.ts                            |  16 ++-
 6 files changed, 179 insertions(+), 5 deletions(-)
 create mode 100644 src/client/util/UndoManager.ts

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

diff --git a/src/client/util/UndoManager.ts b/src/client/util/UndoManager.ts
new file mode 100644
index 000000000..34910bac3
--- /dev/null
+++ b/src/client/util/UndoManager.ts
@@ -0,0 +1,121 @@
+import { observable, action } from "mobx";
+import { Opt } from "../../fields/Field";
+
+export function undoBatch(target: any, key: string | symbol, descriptor?: TypedPropertyDescriptor<any>): any {
+    let fn: (...args: any[]) => any;
+    let patchedFn: Opt<(...args: any[]) => any>;
+
+    if (descriptor) {
+        fn = descriptor.value;
+    }
+
+    return {
+        configurable: true,
+        enumerable: false,
+        get() {
+            if (!patchedFn) {
+                patchedFn = (...args: any[]) => {
+                    try {
+                        UndoManager.StartBatch()
+                        return fn.call(this, ...args)
+                    } finally {
+                        UndoManager.EndBatch()
+                    }
+                };
+            }
+            return patchedFn;
+        },
+        set(newFn: any) {
+            patchedFn = undefined;
+            fn = newFn;
+        }
+    }
+}
+export namespace UndoManager {
+    export interface UndoEvent {
+        undo: () => void;
+        redo: () => void;
+    }
+    type UndoBatch = UndoEvent[];
+
+    let undoStack: UndoBatch[] = observable([]);
+    let redoStack: UndoBatch[] = observable([]);
+    let currentBatch: UndoBatch | undefined;
+    let batchCounter = 0;
+    let undoing = false;
+
+    export function AddEvent(event: UndoEvent): void {
+        if (currentBatch && batchCounter && !undoing) {
+            currentBatch.push(event);
+        }
+    }
+
+    export function CanUndo(): boolean {
+        return undoStack.length > 0;
+    }
+
+    export function CanRedo(): boolean {
+        return redoStack.length > 0;
+    }
+
+    export function StartBatch(): void {
+        batchCounter++;
+        if (batchCounter > 0) {
+            currentBatch = [];
+        }
+    }
+
+    export const EndBatch = action(() => {
+        batchCounter--;
+        if (batchCounter === 0 && currentBatch && currentBatch.length) {
+            undoStack.push(currentBatch);
+            redoStack.length = 0;
+            currentBatch = undefined;
+        }
+    })
+
+    export function RunInBatch(fn: () => void) {
+        StartBatch();
+        fn();
+        EndBatch();
+    }
+
+    export const Undo = action(() => {
+        if (undoStack.length === 0) {
+            return;
+        }
+
+        let commands = undoStack.pop();
+        if (!commands) {
+            return;
+        }
+
+        undoing = true;
+        for (let i = commands.length - 1; i >= 0; i--) {
+            commands[i].undo();
+        }
+        undoing = false;
+
+        redoStack.push(commands);
+    })
+
+    export const Redo = action(() => {
+        if (redoStack.length === 0) {
+            return;
+        }
+
+        let commands = redoStack.pop();
+        if (!commands) {
+            return;
+        }
+
+        undoing = true;
+        for (let i = 0; i < commands.length; i++) {
+            commands[i].redo();
+        }
+        undoing = false;
+
+        undoStack.push(commands);
+    })
+
+}
\ No newline at end of file
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index f44ad0a74..6d3d4d4c2 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -16,6 +16,7 @@ import { MessageStore, DocumentTransfer } from '../../server/Message';
 import { Transform } from '../util/Transform';
 import { CollectionDockingView } from './collections/CollectionDockingView';
 import { FieldWaiting } from '../../fields/Field';
+import { UndoManager } from '../util/UndoManager';
 
 
 configure({
@@ -94,6 +95,11 @@ Documents.initProtos(() => {
                 x: 0, y: 300, width: 200, height: 200, title: "added note"
             }));
         })
+        let addSchemaNode = action(() => {
+            mainfreeform.GetList<Document>(KeyStore.Data, []).push(Documents.SchemaDocument([Documents.TextDocument()], {
+                x: 0, y: 300, width: 200, height: 200, title: "added note"
+            }));
+        })
 
         let clearDatabase = action(() => {
             Utils.Emit(Server.Socket, MessageStore.DeleteAll, {});
@@ -126,12 +132,30 @@ Documents.initProtos(() => {
                     left: '0px',
                     width: '150px'
                 }} onClick={addColNode}>Add Collection</button>
+                <button style={{
+                    position: 'absolute',
+                    bottom: '100',
+                    left: '0px',
+                    width: '150px'
+                }} onClick={addSchemaNode}>Add Schema</button>
                 <button style={{
                     position: 'absolute',
                     bottom: '75px',
                     left: '0px',
                     width: '150px'
                 }} onClick={clearDatabase}>Clear Database</button>
+                <button style={{
+                    position: 'absolute',
+                    bottom: '25',
+                    right: '0px',
+                    width: '150px'
+                }} onClick={() => UndoManager.Undo()}>Undo</button>
+                <button style={{
+                    position: 'absolute',
+                    bottom: '0',
+                    right: '0px',
+                    width: '150px'
+                }} onClick={() => UndoManager.Redo()}>Redo</button>
             </div>),
             document.getElementById('root'));
     })
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index 54757cce5..a6f34dfdf 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -13,6 +13,7 @@ import { Documents } from "../../documents/Documents";
 import { FieldWaiting } from "../../../fields/Field";
 import { Transform } from "../../util/Transform";
 import { DocumentView } from "../nodes/DocumentView";
+import { undoBatch } from "../../util/UndoManager";
 
 @observer
 export class CollectionFreeFormView extends CollectionViewBase {
@@ -37,6 +38,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
     @computed
     get resizeScaling() { return this.isAnnotationOverlay ? this.props.Document.GetNumber(KeyStore.Width, 0) / this.nativeWidth : 1; }
 
+    @undoBatch
     @action
     drop = (e: Event, de: DragManager.DropEvent) => {
         const doc: DocumentView = de.data["document"];
diff --git a/src/fields/BasicField.ts b/src/fields/BasicField.ts
index 8728b7145..91977b243 100644
--- a/src/fields/BasicField.ts
+++ b/src/fields/BasicField.ts
@@ -1,6 +1,7 @@
 import { Field, FieldId } from "./Field"
 import { observable, computed, action } from "mobx";
 import { Server } from "../client/Server";
+import { UndoManager } from "../client/util/UndoManager";
 
 export abstract class BasicField<T> extends Field {
     constructor(data: T, save: boolean, id?: FieldId) {
@@ -27,9 +28,15 @@ export abstract class BasicField<T> extends Field {
     }
 
     set Data(value: T) {
-        if (this.data != value) {
-            this.data = value;
+        if (this.data === value) {
+            return;
         }
+        let oldValue = this.data;
+        this.data = value;
+        UndoManager.AddEvent({
+            undo: () => this.Data = oldValue,
+            redo: () => this.Data = value
+        })
         Server.UpdateField(this);
     }
 
diff --git a/src/fields/Document.ts b/src/fields/Document.ts
index 0c2ad0fdb..d8522fb5b 100644
--- a/src/fields/Document.ts
+++ b/src/fields/Document.ts
@@ -7,6 +7,7 @@ import { TextField } from "./TextField";
 import { ListField } from "./ListField";
 import { Server } from "../client/Server";
 import { Types } from "../server/Message";
+import { UndoManager } from "../client/util/UndoManager";
 
 export class Document extends Field {
     public fields: ObservableMap<string, { key: Key, field: Field }> = new ObservableMap();
@@ -127,7 +128,8 @@ export class Document extends Field {
 
     @action
     Set(key: Key, field: Field | undefined): void {
-        console.log("Assign: " + key.Name + " = " + (field ? field.GetValue() : "<undefined>") + " (" + (field ? field.Id : "<undefined>") + ")");
+        let old = this.fields.get(key.Id);
+        let oldField = old ? old.field : undefined;
         if (field) {
             this.fields.set(key.Id, { key, field });
             this._proxies.set(key.Id, field.Id)
@@ -137,6 +139,12 @@ export class Document extends Field {
             this._proxies.delete(key.Id)
             // Server.DeleteDocumentField(this, key);
         }
+        if (oldField || field) {
+            UndoManager.AddEvent({
+                undo: () => this.Set(key, oldField),
+                redo: () => this.Set(key, field)
+            })
+        }
         Server.UpdateField(this);
     }
 
diff --git a/src/fields/ListField.ts b/src/fields/ListField.ts
index 2e192bf90..ad5374dc9 100644
--- a/src/fields/ListField.ts
+++ b/src/fields/ListField.ts
@@ -1,9 +1,10 @@
 import { Field, FieldId, FieldValue, Opt } from "./Field";
 import { BasicField } from "./BasicField";
 import { Types } from "../server/Message";
-import { observe, action } from "mobx";
+import { observe, action, IArrayChange, IArraySplice, IObservableArray } from "mobx";
 import { Server } from "../client/Server";
 import { ServerUtils } from "../server/ServerUtil";
+import { UndoManager } from "../client/util/UndoManager";
 
 export class ListField<T extends Field> extends BasicField<T[]> {
     private _proxies: string[] = []
@@ -13,8 +14,19 @@ export class ListField<T extends Field> extends BasicField<T[]> {
         if (save) {
             Server.UpdateField(this);
         }
-        observe(this.Data, () => {
+        observe(this.Data as IObservableArray<T>, (change: IArrayChange<T> | IArraySplice<T>) => {
             this.updateProxies()
+            if (change.type == "splice") {
+                UndoManager.AddEvent({
+                    undo: () => this.Data.splice(change.index, change.addedCount, ...change.removed),
+                    redo: () => this.Data.splice(change.index, change.removedCount, ...change.added)
+                })
+            } else {
+                UndoManager.AddEvent({
+                    undo: () => this.Data[change.index] = change.oldValue,
+                    redo: () => this.Data[change.index] = change.newValue
+                })
+            }
             Server.UpdateField(this);
         })
     }
-- 
cgit v1.2.3-70-g09d2


From 7339b4b1f8e9f92160b753dfd3d81faf2887c02f Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Wed, 20 Feb 2019 22:02:56 -0500
Subject: Kind of fixed undo decorator, more work needed to get it to work with
 arrow functions

---
 src/client/util/UndoManager.ts                     | 57 +++++++++++++---------
 .../views/collections/CollectionFreeFormView.tsx   | 12 +++--
 2 files changed, 44 insertions(+), 25 deletions(-)

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

diff --git a/src/client/util/UndoManager.ts b/src/client/util/UndoManager.ts
index 34910bac3..8e9e11a11 100644
--- a/src/client/util/UndoManager.ts
+++ b/src/client/util/UndoManager.ts
@@ -1,36 +1,49 @@
 import { observable, action } from "mobx";
 import { Opt } from "../../fields/Field";
 
-export function undoBatch(target: any, key: string | symbol, descriptor?: TypedPropertyDescriptor<any>): any {
-    let fn: (...args: any[]) => any;
-    let patchedFn: Opt<(...args: any[]) => any>;
-
-    if (descriptor) {
-        fn = descriptor.value;
-    }
-
-    return {
+function propertyDecorator(target: any, key: string | symbol) {
+    Object.defineProperty(target, key, {
         configurable: true,
         enumerable: false,
-        get() {
-            if (!patchedFn) {
-                patchedFn = (...args: any[]) => {
+        get: function () {
+            return 5;
+        },
+        set: function (value: any) {
+            Object.defineProperty(this, key, {
+                enumerable: false,
+                writable: true,
+                configurable: true,
+                value: function (...args: any[]) {
                     try {
-                        UndoManager.StartBatch()
-                        return fn.call(this, ...args)
+                        UndoManager.StartBatch();
+                        return value.apply(this, args);
                     } finally {
-                        UndoManager.EndBatch()
+                        UndoManager.EndBatch();
                     }
-                };
-            }
-            return patchedFn;
-        },
-        set(newFn: any) {
-            patchedFn = undefined;
-            fn = newFn;
+                }
+            })
+        }
+    })
+}
+export function undoBatch(target: any, key: string | symbol, descriptor: TypedPropertyDescriptor<any>): any {
+    if (!descriptor) {
+        propertyDecorator(target, key);
+        return;
+    }
+    const oldFunction = descriptor.value;
+
+    descriptor.value = function (...args: any[]) {
+        try {
+            UndoManager.StartBatch()
+            return oldFunction.apply(this, args)
+        } finally {
+            UndoManager.EndBatch()
         }
     }
+
+    return descriptor;
 }
+
 export namespace UndoManager {
     export interface UndoEvent {
         undo: () => void;
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index 3a66ebb75..07e9c0899 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -4,7 +4,7 @@ import { action, computed } from "mobx";
 import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView";
 import { DragManager } from "../../util/DragManager";
 import "./CollectionFreeFormView.scss";
-import { CollectionViewBase, COLLECTION_BORDER_WIDTH } from "./CollectionViewBase";
+import { CollectionViewBase, COLLECTION_BORDER_WIDTH, CollectionViewProps } from "./CollectionViewBase";
 import { KeyStore } from "../../../fields/KeyStore";
 import { Document } from "../../../fields/Document";
 import { ListField } from "../../../fields/ListField";
@@ -38,9 +38,15 @@ export class CollectionFreeFormView extends CollectionViewBase {
     @computed
     get resizeScaling() { return this.isAnnotationOverlay ? this.props.Document.GetNumber(KeyStore.Width, 0) / this.nativeWidth : 1; }
 
-    @undoBatch
+    constructor(props: CollectionViewProps) {
+        super(props);
+
+        this.drop = this.drop.bind(this);
+    }
+
     @action
-    drop = (e: Event, de: DragManager.DropEvent) => {
+    @undoBatch
+    drop(e: Event, de: DragManager.DropEvent) {
         const doc: DocumentView = de.data["document"];
         if (doc.props.ContainingCollectionView && doc.props.ContainingCollectionView !== this) {
             doc.props.ContainingCollectionView.removeDocument(doc.props.Document);
-- 
cgit v1.2.3-70-g09d2


From 8e56ee4c6f1f16402edd8abee9daa55678117466 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Thu, 21 Feb 2019 13:44:58 -0500
Subject: everything works.

---
 src/client/util/UndoManager.ts                          | 2 +-
 src/client/views/Main.tsx                               | 2 +-
 src/client/views/collections/CollectionDockingView.tsx  | 2 ++
 src/client/views/collections/CollectionFreeFormView.tsx | 6 ++----
 4 files changed, 6 insertions(+), 6 deletions(-)

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

diff --git a/src/client/util/UndoManager.ts b/src/client/util/UndoManager.ts
index 8e9e11a11..edb75b55f 100644
--- a/src/client/util/UndoManager.ts
+++ b/src/client/util/UndoManager.ts
@@ -25,7 +25,7 @@ function propertyDecorator(target: any, key: string | symbol) {
         }
     })
 }
-export function undoBatch(target: any, key: string | symbol, descriptor: TypedPropertyDescriptor<any>): any {
+export function undoBatch(target: any, key: string | symbol, descriptor?: TypedPropertyDescriptor<any>): any {
     if (!descriptor) {
         propertyDecorator(target, key);
         return;
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index f35362fd4..c7a6a44e8 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -76,7 +76,7 @@ Documents.initProtos(() => {
                 var docs = [mainfreeform].map(doc => CollectionDockingView.makeDocumentConfig(doc));
                 mainContainer.SetText(KeyStore.Data, JSON.stringify({ content: [{ type: 'row', content: docs }] }));
                 mainContainer.Set(KeyStore.ActiveFrame, mainfreeform);
-            }, 25);
+            }, 0);
         }
 
         let addImageNode = action(() => {
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index e8a1eaf92..35b130a9a 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -16,6 +16,7 @@ import { Server } from "../../Server";
 import { observer } from "mobx-react";
 import { KeyStore } from "../../../fields/KeyStore";
 import { Opt } from "../../../fields/Field";
+import { undoBatch } from "../../util/UndoManager";
 
 @observer
 export class CollectionDockingView extends CollectionViewBase {
@@ -201,6 +202,7 @@ export class CollectionDockingView extends CollectionViewBase {
         }
     }
 
+    @undoBatch
     stateChanged = () => {
         var json = JSON.stringify(this._goldenLayout.toConfig());
         this.props.Document.SetText(KeyStore.Data, json)
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index 07e9c0899..986bcdcee 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -40,13 +40,11 @@ export class CollectionFreeFormView extends CollectionViewBase {
 
     constructor(props: CollectionViewProps) {
         super(props);
-
-        this.drop = this.drop.bind(this);
     }
 
-    @action
     @undoBatch
-    drop(e: Event, de: DragManager.DropEvent) {
+    @action
+    drop = (e: Event, de: DragManager.DropEvent) => {
         const doc: DocumentView = de.data["document"];
         if (doc.props.ContainingCollectionView && doc.props.ContainingCollectionView !== this) {
             doc.props.ContainingCollectionView.removeDocument(doc.props.Document);
-- 
cgit v1.2.3-70-g09d2


From fed460a9dffd85b32e30aeb112f2c7c47371bce6 Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Fri, 22 Feb 2019 03:01:30 -0500
Subject: Added CollectionView Switched sub-collections to not inherit from
 CollectionViewBase

---
 src/client/Server.ts                               |   5 +-
 src/client/documents/Documents.ts                  |  81 +++++---------
 src/client/views/Main.tsx                          |   8 +-
 .../views/collections/CollectionDockingView.tsx    |  11 +-
 .../views/collections/CollectionFreeFormView.tsx   |  25 ++---
 .../views/collections/CollectionSchemaView.tsx     |  13 ++-
 src/client/views/collections/CollectionView.tsx    | 116 +++++++++++++++++++++
 .../views/collections/CollectionViewBase.tsx       |  61 -----------
 src/client/views/nodes/DocumentView.tsx            |  13 ++-
 src/client/views/nodes/FieldView.tsx               |   3 +-
 src/fields/BasicField.ts                           |   6 +-
 src/fields/Document.ts                             |   9 ++
 src/fields/KeyStore.ts                             |   1 +
 src/fields/ListField.ts                            |  19 +++-
 14 files changed, 212 insertions(+), 159 deletions(-)
 create mode 100644 src/client/views/collections/CollectionView.tsx
 delete mode 100644 src/client/views/collections/CollectionViewBase.tsx

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

diff --git a/src/client/Server.ts b/src/client/Server.ts
index 3e61729ab..06ac22c61 100644
--- a/src/client/Server.ts
+++ b/src/client/Server.ts
@@ -60,13 +60,16 @@ export class Server {
         });
     }
 
-    public static GetDocumentField(doc: Document, key: Key) {
+    public static GetDocumentField(doc: Document, key: Key, callback?: (field: Field) => void) {
         let field = doc._proxies.get(key.Id);
         if (field) {
             this.GetField(field,
                 action((fieldfromserver: Opt<Field>) => {
                     if (fieldfromserver) {
                         doc.fields.set(key.Id, { key, field: fieldfromserver });
+                        if (callback) {
+                            callback(fieldfromserver);
+                        }
                     }
                 }));
         }
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 920068273..bfa6cb7a9 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -11,6 +11,7 @@ import { ImageField } from "../../fields/ImageField";
 import { ImageBox } from "../views/nodes/ImageBox";
 import { CollectionFreeFormView } from "../views/collections/CollectionFreeFormView";
 import { FieldId } from "../../fields/Field";
+import { CollectionView, CollectionViewType } from "../views/collections/CollectionView";
 
 interface DocumentOptions {
     x?: number;
@@ -24,12 +25,10 @@ interface DocumentOptions {
 
 export namespace Documents {
     export function initProtos(callback: () => void) {
-        Server.GetFields([collectionProtoId, textProtoId, imageProtoId, schemaProtoId, dockProtoId], (fields) => {
+        Server.GetFields([collectionProtoId, textProtoId, imageProtoId], (fields) => {
             collectionProto = fields[collectionProtoId] as Document;
             imageProto = fields[imageProtoId] as Document;
             textProto = fields[textProtoId] as Document;
-            dockProto = fields[dockProtoId] as Document;
-            schemaProto = fields[schemaProtoId] as Document;
             callback()
         });
     }
@@ -83,52 +82,6 @@ export namespace Documents {
         return doc;
     }
 
-    let schemaProto: Document;
-    const schemaProtoId = "schemaProto";
-    function GetSchemaPrototype(): Document {
-        if (!schemaProto) {
-            schemaProto = new Document(schemaProtoId);
-            schemaProto.Set(KeyStore.X, new NumberField(0));
-            schemaProto.Set(KeyStore.Y, new NumberField(0));
-            schemaProto.Set(KeyStore.Width, new NumberField(300));
-            schemaProto.Set(KeyStore.Height, new NumberField(150));
-            schemaProto.Set(KeyStore.Layout, new TextField(CollectionSchemaView.LayoutString()));
-            schemaProto.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data]));
-        }
-        return schemaProto;
-    }
-
-    export function SchemaDocument(documents: Array<Document>, options: DocumentOptions = {}): Document {
-        let doc = GetSchemaPrototype().MakeDelegate();
-        setupOptions(doc, options);
-        doc.Set(KeyStore.Data, new ListField(documents));
-        return doc;
-    }
-
-
-    let dockProto: Document;
-    const dockProtoId = "dockProto";
-    function GetDockPrototype(): Document {
-        if (!dockProto) {
-            dockProto = new Document();
-            dockProto.Set(KeyStore.X, new NumberField(0));
-            dockProto.Set(KeyStore.Y, new NumberField(0));
-            dockProto.Set(KeyStore.Width, new NumberField(300));
-            dockProto.Set(KeyStore.Height, new NumberField(150));
-            dockProto.Set(KeyStore.Layout, new TextField(CollectionDockingView.LayoutString()));
-            dockProto.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data]));
-        }
-        return dockProto;
-    }
-
-    export function DockDocument(config: string, options: DocumentOptions = {}, id?: string): Document {
-        let doc = GetDockPrototype().MakeDelegate(id);
-        setupOptions(doc, options);
-        doc.SetText(KeyStore.Data, config);
-        return doc;
-    }
-
-
     let imageProto: Document;
     const imageProtoId = "imageProto";
     function GetImagePrototype(): Document {
@@ -141,7 +94,8 @@ export namespace Documents {
             imageProto.Set(KeyStore.NativeHeight, new NumberField(300));
             imageProto.Set(KeyStore.Width, new NumberField(300));
             imageProto.Set(KeyStore.Height, new NumberField(300));
-            imageProto.Set(KeyStore.Layout, new TextField(CollectionFreeFormView.LayoutString("AnnotationsKey")));
+            imageProto.Set(KeyStore.Layout, new TextField(CollectionView.LayoutString("AnnotationsKey")));
+            imageProto.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform)
             imageProto.Set(KeyStore.BackgroundLayout, new TextField(ImageBox.LayoutString()));
             // imageProto.SetField(KeyStore.Layout, new TextField('<div style={"background-image: " + {Data}} />'));
             imageProto.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data, KeyStore.Annotations]));
@@ -165,23 +119,36 @@ export namespace Documents {
     function GetCollectionPrototype(): Document {
         if (!collectionProto) {
             collectionProto = new Document(collectionProtoId);
-            collectionProto.Set(KeyStore.X, new NumberField(0));
-            collectionProto.Set(KeyStore.Y, new NumberField(0));
             collectionProto.Set(KeyStore.Scale, new NumberField(1));
             collectionProto.Set(KeyStore.PanX, new NumberField(0));
             collectionProto.Set(KeyStore.PanY, new NumberField(0));
-            collectionProto.Set(KeyStore.Width, new NumberField(300));
-            collectionProto.Set(KeyStore.Height, new NumberField(300));
-            collectionProto.Set(KeyStore.Layout, new TextField(CollectionFreeFormView.LayoutString("DataKey")));
+            collectionProto.Set(KeyStore.Layout, new TextField(CollectionView.LayoutString("DataKey")));
             collectionProto.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data]));
         }
         return collectionProto;
     }
 
-    export function CollectionDocument(documents: Array<Document>, options: DocumentOptions = {}, id?: string): Document {
+    export function CollectionDocument(data: Array<Document> | string, viewType: CollectionViewType, options: DocumentOptions = {}, id?: string): Document {
         let doc = GetCollectionPrototype().MakeDelegate(id);
         setupOptions(doc, options);
-        doc.Set(KeyStore.Data, new ListField(documents));
+        if (typeof data === "string") {
+            doc.SetText(KeyStore.Data, data);
+        } else {
+            doc.SetData(KeyStore.Data, data, ListField);
+        }
+        doc.SetNumber(KeyStore.ViewType, viewType);
         return doc;
     }
+
+    export function FreeformDocument(documents: Array<Document>, options: DocumentOptions, id?: string) {
+        return CollectionDocument(documents, CollectionViewType.Freeform, options, id)
+    }
+
+    export function SchemaDocument(documents: Array<Document>, options: DocumentOptions, id?: string) {
+        return CollectionDocument(documents, CollectionViewType.Schema, options, id)
+    }
+
+    export function DockDocument(config: string, options: DocumentOptions, id?: string) {
+        return CollectionDocument(config, CollectionViewType.Docking, options, id)
+    }
 }
\ No newline at end of file
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index c7a6a44e8..fe1a999ec 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -61,16 +61,14 @@ Documents.initProtos(() => {
         let mainfreeform: Document;
         if (res) {
             mainContainer = ServerUtils.FromJson(res) as Document;
-            mainfreeform = mainContainer.Get(KeyStore.ActiveFrame) as Document;
-            if (!mainfreeform)
-                Server.GetField(mainContainer._proxies.get(KeyStore.ActiveFrame.Id)!, (field) => mainfreeform = field as Document);
+            mainContainer.GetAsync(KeyStore.ActiveFrame, field => mainfreeform = field as Document);
         }
         else {
             mainContainer = Documents.DockDocument(JSON.stringify({ content: [{ type: 'row', content: [] }] }), { title: "main container" }, mainDocId);
             Utils.Emit(Server.Socket, MessageStore.AddDocument, new DocumentTransfer(mainContainer.ToJson()))
 
             setTimeout(() => {
-                mainfreeform = Documents.CollectionDocument([], { x: 0, y: 400, title: "mini collection" });
+                mainfreeform = Documents.FreeformDocument([], { x: 0, y: 400, title: "mini collection" });
                 Utils.Emit(Server.Socket, MessageStore.AddDocument, new DocumentTransfer(mainfreeform.ToJson()));
 
                 var docs = [mainfreeform].map(doc => CollectionDockingView.makeDocumentConfig(doc));
@@ -90,7 +88,7 @@ Documents.initProtos(() => {
             }));
         })
         let addColNode = action(() => {
-            mainfreeform.GetList<Document>(KeyStore.Data, []).push(Documents.CollectionDocument([], {
+            mainfreeform.GetList<Document>(KeyStore.Data, []).push(Documents.FreeformDocument([], {
                 x: 0, y: 300, width: 200, height: 200, title: "added note"
             }));
         })
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 60dc24b5f..6d91aef5e 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -14,13 +14,12 @@ import { DragManager } from "../../util/DragManager";
 import { undoBatch } from "../../util/UndoManager";
 import { DocumentView } from "../nodes/DocumentView";
 import "./CollectionDockingView.scss";
-import { CollectionViewBase, CollectionViewProps, COLLECTION_BORDER_WIDTH } from "./CollectionViewBase";
+import { CollectionViewProps, COLLECTION_BORDER_WIDTH, SubCollectionViewProps } from "./CollectionView";
 import React = require("react");
 
 @observer
-export class CollectionDockingView extends CollectionViewBase {
+export class CollectionDockingView extends React.Component<SubCollectionViewProps> {
     public static Instance: CollectionDockingView;
-    public static LayoutString() { return CollectionViewBase.LayoutString("CollectionDockingView"); }
     public static makeDocumentConfig(document: Document) {
         return {
             type: 'react-component',
@@ -41,7 +40,7 @@ export class CollectionDockingView extends CollectionViewBase {
     private _containerRef = React.createRef<HTMLDivElement>();
     private _fullScreen: any = null;
 
-    constructor(props: CollectionViewProps) {
+    constructor(props: SubCollectionViewProps) {
         super(props);
         CollectionDockingView.Instance = this;
         (window as any).React = React;
@@ -187,7 +186,7 @@ export class CollectionDockingView extends CollectionViewBase {
     }
     @action
     onPointerDown = (e: React.PointerEvent): void => {
-        if (e.button === 2 && this.active) {
+        if (e.button === 2 && this.props.active()) {
             e.stopPropagation();
             e.preventDefault();
         } else {
@@ -195,7 +194,7 @@ export class CollectionDockingView extends CollectionViewBase {
             if (className == "lm_drag_handle" || className == "lm_close" || className == "lm_maximise" || className == "lm_minimise" || className == "lm_close_tab") {
                 this._flush = true;
             }
-            if (e.buttons === 1 && this.active) {
+            if (e.buttons === 1 && this.props.active()) {
                 e.stopPropagation();
             }
         }
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index 986bcdcee..bd7ca5b6f 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -4,7 +4,7 @@ import { action, computed } from "mobx";
 import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView";
 import { DragManager } from "../../util/DragManager";
 import "./CollectionFreeFormView.scss";
-import { CollectionViewBase, COLLECTION_BORDER_WIDTH, CollectionViewProps } from "./CollectionViewBase";
+import { COLLECTION_BORDER_WIDTH, CollectionViewProps, SubCollectionViewProps } from "./CollectionView";
 import { KeyStore } from "../../../fields/KeyStore";
 import { Document } from "../../../fields/Document";
 import { ListField } from "../../../fields/ListField";
@@ -16,8 +16,7 @@ import { DocumentView } from "../nodes/DocumentView";
 import { undoBatch } from "../../util/UndoManager";
 
 @observer
-export class CollectionFreeFormView extends CollectionViewBase {
-    public static LayoutString(fieldKey: string = "DataKey") { return CollectionViewBase.LayoutString("CollectionFreeFormView", fieldKey); }
+export class CollectionFreeFormView extends React.Component<SubCollectionViewProps> {
     private _canvasRef = React.createRef<HTMLDivElement>();
     private _lastX: number = 0;
     private _lastY: number = 0;
@@ -38,7 +37,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
     @computed
     get resizeScaling() { return this.isAnnotationOverlay ? this.props.Document.GetNumber(KeyStore.Width, 0) / this.nativeWidth : 1; }
 
-    constructor(props: CollectionViewProps) {
+    constructor(props: SubCollectionViewProps) {
         super(props);
     }
 
@@ -46,9 +45,11 @@ export class CollectionFreeFormView extends CollectionViewBase {
     @action
     drop = (e: Event, de: DragManager.DropEvent) => {
         const doc: DocumentView = de.data["document"];
-        if (doc.props.ContainingCollectionView && doc.props.ContainingCollectionView !== this) {
-            doc.props.ContainingCollectionView.removeDocument(doc.props.Document);
-            this.addDocument(doc.props.Document);
+        if (doc.props.ContainingCollectionView && doc.props.ContainingCollectionView !== this.props.CollectionView) {
+            if (doc.props.RemoveDocument) {
+                doc.props.RemoveDocument(doc.props.Document);
+            }
+            this.props.addDocument(doc.props.Document);
         }
         const xOffset = de.data["xOffset"] as number || 0;
         const yOffset = de.data["yOffset"] as number || 0;
@@ -79,7 +80,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
 
     @action
     onPointerDown = (e: React.PointerEvent): void => {
-        if ((e.button === 2 && this.active) ||
+        if ((e.button === 2 && this.props.active()) ||
             !e.defaultPrevented) {
             document.removeEventListener("pointermove", this.onPointerMove);
             document.addEventListener("pointermove", this.onPointerMove);
@@ -104,7 +105,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
 
     @action
     onPointerMove = (e: PointerEvent): void => {
-        if (!e.cancelBubble && this.active) {
+        if (!e.cancelBubble && this.props.active()) {
             e.preventDefault();
             e.stopPropagation();
             let x = this.props.Document.GetNumber(KeyStore.PanX, 0);
@@ -248,13 +249,13 @@ export class CollectionFreeFormView extends CollectionViewBase {
                     {this.props.BackgroundView ? this.props.BackgroundView() : null}
                     {lvalue.Data.map(doc => {
                         return (<CollectionFreeFormDocumentView key={doc.Id} Document={doc}
-                            AddDocument={this.addDocument}
-                            RemoveDocument={this.removeDocument}
+                            AddDocument={this.props.addDocument}
+                            RemoveDocument={this.props.removeDocument}
                             ScreenToLocalTransform={this.getTransform}
                             isTopMost={false}
                             Scaling={1}
                             PanelSize={[doc.GetNumber(KeyStore.Width, 0), doc.GetNumber(KeyStore.Height, 0)]}
-                            ContainingCollectionView={this} />);
+                            ContainingCollectionView={this.props.CollectionView} />);
                     })}
                 </div>
             </div>
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 5ec288b13..9405c820f 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -13,12 +13,10 @@ import { EditableView } from "../EditableView";
 import { DocumentView } from "../nodes/DocumentView";
 import { FieldView, FieldViewProps } from "../nodes/FieldView";
 import "./CollectionSchemaView.scss";
-import { CollectionViewBase, COLLECTION_BORDER_WIDTH } from "./CollectionViewBase";
+import { COLLECTION_BORDER_WIDTH, CollectionViewProps, SubCollectionViewProps } from "./CollectionView";
 
 @observer
-export class CollectionSchemaView extends CollectionViewBase {
-    public static LayoutString(fieldKey: string = "DataKey") { return CollectionViewBase.LayoutString("CollectionSchemaView", fieldKey); }
-
+export class CollectionSchemaView extends React.Component<SubCollectionViewProps> {
     private _mainCont = React.createRef<HTMLDivElement>();
 
     private DIVIDER_WIDTH = 5;
@@ -34,6 +32,7 @@ export class CollectionSchemaView extends CollectionViewBase {
             doc: rowProps.value[0],
             fieldKey: rowProps.value[1],
             isSelected: () => false,
+            select: () => { },
             isTopMost: false
         }
         let contents = (
@@ -112,7 +111,7 @@ export class CollectionSchemaView extends CollectionViewBase {
         //     e.preventDefault();
         // } else 
         {
-            if (e.buttons === 1 && this.active) {
+            if (e.buttons === 1 && this.props.active()) {
                 e.stopPropagation();
             }
         }
@@ -145,12 +144,12 @@ export class CollectionSchemaView extends CollectionViewBase {
                 {({ measureRef }) =>
                     <div ref={measureRef}>
                         <DocumentView Document={selected}
-                            AddDocument={this.addDocument} RemoveDocument={this.removeDocument}
+                            AddDocument={this.props.addDocument} RemoveDocument={this.props.removeDocument}
                             ScreenToLocalTransform={this.getTransform}
                             Scaling={this._parentScaling}
                             isTopMost={false}
                             PanelSize={[this._panelWidth, this._panelHeight]}
-                            ContainingCollectionView={me} />
+                            ContainingCollectionView={this.props.CollectionView} />
                     </div>
                 }
             </Measure>
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
new file mode 100644
index 000000000..651d85879
--- /dev/null
+++ b/src/client/views/collections/CollectionView.tsx
@@ -0,0 +1,116 @@
+import { action, computed } from "mobx";
+import { observer } from "mobx-react";
+import { Document } from "../../../fields/Document";
+import { Key } from "../../../fields/Key";
+import { ListField } from "../../../fields/ListField";
+import { SelectionManager } from "../../util/SelectionManager";
+import { ContextMenu } from "../ContextMenu";
+import React = require("react");
+import { Transform } from "../../util/Transform";
+import { KeyStore } from "../../../fields/KeyStore";
+import { NumberField } from "../../../fields/NumberField";
+import { CollectionFreeFormView } from "./CollectionFreeFormView";
+import { CollectionDockingView } from "./CollectionDockingView";
+import { CollectionSchemaView } from "./CollectionSchemaView";
+import { Opt } from "../../../fields/Field";
+
+
+export interface CollectionViewProps {
+    fieldKey: Key;
+    Document: Document;
+    ScreenToLocalTransform: () => Transform;
+    isSelected: () => boolean;
+    isTopMost: boolean;
+    select: (ctrlPressed: boolean) => void;
+    BackgroundView?: () => JSX.Element;
+}
+
+export interface SubCollectionViewProps extends CollectionViewProps {
+    active: () => boolean;
+    addDocument: (doc: Document) => void;
+    removeDocument: (doc: Document) => boolean;
+    CollectionView: Opt<CollectionView>;
+}
+
+export enum CollectionViewType {
+    Invalid,
+    Freeform,
+    Schema,
+    Docking,
+}
+
+export const COLLECTION_BORDER_WIDTH = 2;
+
+@observer
+export class CollectionView extends React.Component<CollectionViewProps> {
+
+    public static LayoutString(fieldKey: string = "DataKey") {
+        return `<CollectionView Document={Document}
+                    ScreenToLocalTransform={ScreenToLocalTransform} fieldKey={${fieldKey}} isSelected={isSelected} select={select}
+                    isTopMost={isTopMost} BackgroundView={BackgroundView} />`;
+    }
+    public active = () => {
+        var isSelected = this.props.isSelected();
+        var childSelected = SelectionManager.SelectedDocuments().some(view => view.props.ContainingCollectionView == this);
+        var topMost = this.props.isTopMost;
+        return isSelected || childSelected || topMost;
+    }
+    @action
+    addDocument = (doc: Document): void => {
+        //TODO This won't create the field if it doesn't already exist
+        const value = this.props.Document.GetData(this.props.fieldKey, ListField, new Array<Document>())
+        value.push(doc);
+    }
+
+    @action
+    removeDocument = (doc: Document): boolean => {
+        //TODO This won't create the field if it doesn't already exist
+        const value = this.props.Document.GetData(this.props.fieldKey, ListField, new Array<Document>())
+        let index = value.indexOf(doc);
+        if (index !== -1) {
+            value.splice(index, 1)
+
+            SelectionManager.DeselectAll()
+            ContextMenu.Instance.clearItems()
+            return true;
+        }
+        return false
+    }
+
+    get collectionViewType(): CollectionViewType {
+        let Document = this.props.Document;
+        let viewField = Document.GetT(KeyStore.ViewType, NumberField);
+        if (viewField === "<Waiting>") {
+            return CollectionViewType.Invalid;
+        } else if (viewField) {
+            return viewField.Data;
+        } else {
+            return CollectionViewType.Freeform;
+        }
+    }
+
+    set collectionViewType(type: CollectionViewType) {
+        let Document = this.props.Document;
+        Document.SetData(KeyStore.ViewType, type, NumberField);
+    }
+
+    render() {
+        let viewType = this.collectionViewType;
+        switch (viewType) {
+            case CollectionViewType.Freeform:
+                return (<CollectionFreeFormView {...this.props}
+                    addDocument={this.addDocument} removeDocument={this.removeDocument} active={this.active}
+                    CollectionView={this} />)
+            case CollectionViewType.Schema:
+                return (<CollectionSchemaView {...this.props}
+                    addDocument={this.addDocument} removeDocument={this.removeDocument} active={this.active}
+                    CollectionView={this} />)
+            case CollectionViewType.Docking:
+                return (<CollectionDockingView {...this.props}
+                    addDocument={this.addDocument} removeDocument={this.removeDocument} active={this.active}
+                    CollectionView={this} />)
+            default:
+                return <div></div>
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx
deleted file mode 100644
index 0acc890d8..000000000
--- a/src/client/views/collections/CollectionViewBase.tsx
+++ /dev/null
@@ -1,61 +0,0 @@
-import { action, computed } from "mobx";
-import { observer } from "mobx-react";
-import { Document } from "../../../fields/Document";
-import { Key } from "../../../fields/Key";
-import { ListField } from "../../../fields/ListField";
-import { SelectionManager } from "../../util/SelectionManager";
-import { ContextMenu } from "../ContextMenu";
-import React = require("react");
-import { Transform } from "../../util/Transform";
-
-
-export interface CollectionViewProps {
-    fieldKey: Key;
-    Document: Document;
-    ScreenToLocalTransform: () => Transform;
-    isSelected: () => boolean;
-    isTopMost: boolean;
-    select: (ctrlPressed: boolean) => void;
-    BackgroundView?: () => JSX.Element;
-}
-
-export const COLLECTION_BORDER_WIDTH = 2;
-
-@observer
-export class CollectionViewBase extends React.Component<CollectionViewProps> {
-
-    public static LayoutString(collectionType: string, fieldKey: string = "DataKey") {
-        return `<${collectionType} Document={Document}
-                    ScreenToLocalTransform={ScreenToLocalTransform} fieldKey={${fieldKey}} isSelected={isSelected} select={select}
-                    isTopMost={isTopMost} BackgroundView={BackgroundView} />`;
-    }
-    @computed
-    public get active(): boolean {
-        var isSelected = this.props.isSelected();
-        var childSelected = SelectionManager.SelectedDocuments().some(view => view.props.ContainingCollectionView == this);
-        var topMost = this.props.isTopMost;
-        return isSelected || childSelected || topMost;
-    }
-    @action
-    addDocument = (doc: Document): void => {
-        //TODO This won't create the field if it doesn't already exist
-        const value = this.props.Document.GetData(this.props.fieldKey, ListField, new Array<Document>())
-        value.push(doc);
-    }
-
-    @action
-    removeDocument = (doc: Document): boolean => {
-        //TODO This won't create the field if it doesn't already exist
-        const value = this.props.Document.GetData(this.props.fieldKey, ListField, new Array<Document>())
-        let index = value.indexOf(doc);
-        if (index !== -1) {
-            value.splice(index, 1)
-
-            SelectionManager.DeselectAll()
-            ContextMenu.Instance.clearItems()
-            return true;
-        }
-        return false
-    }
-
-}
\ No newline at end of file
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 7cf00a116..2114a5697 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -9,7 +9,7 @@ import { Utils } from "../../../Utils";
 import { CollectionDockingView } from "../collections/CollectionDockingView";
 import { CollectionFreeFormView } from "../collections/CollectionFreeFormView";
 import { CollectionSchemaView } from "../collections/CollectionSchemaView";
-import { CollectionViewBase, COLLECTION_BORDER_WIDTH } from "../collections/CollectionViewBase";
+import { COLLECTION_BORDER_WIDTH, CollectionView, CollectionViewType } from "../collections/CollectionView";
 import { FormattedTextBox } from "../nodes/FormattedTextBox";
 import { ImageBox } from "../nodes/ImageBox";
 import "./DocumentView.scss";
@@ -22,7 +22,7 @@ import { TextField } from "../../../fields/TextField";
 const JsxParser = require('react-jsx-parser').default;//TODO Why does this need to be imported like this?
 
 export interface DocumentViewProps {
-    ContainingCollectionView: Opt<CollectionViewBase>;
+    ContainingCollectionView: Opt<CollectionView>;
 
     Document: Document;
     AddDocument?: (doc: Document) => void;
@@ -114,7 +114,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     @computed
     get active(): boolean {
         return SelectionManager.IsSelected(this) || !this.props.ContainingCollectionView ||
-            this.props.ContainingCollectionView.active;
+            this.props.ContainingCollectionView.active();
     }
 
     private _contextMenuCanOpen = false;
@@ -233,6 +233,9 @@ export class DocumentView extends React.Component<DocumentViewProps> {
             ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked })
             ContextMenu.Instance.addItem({ description: "Open Right", event: this.openRight })
             ContextMenu.Instance.addItem({ description: "Delete", event: this.deleteClicked })
+            ContextMenu.Instance.addItem({ description: "Freeform", event: () => { this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform) } })
+            ContextMenu.Instance.addItem({ description: "Schema", event: () => { this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Schema) } })
+            ContextMenu.Instance.addItem({ description: "Docking", event: () => { this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Docking) } })
             ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15)
             SelectionManager.SelectDoc(this, e.ctrlKey);
         }
@@ -275,7 +278,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         let backgroundLayout = this.backgroundLayout;
         if (backgroundLayout) {
             let backgroundView = () => (<JsxParser
-                components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView }}
+                components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView }}
                 bindings={documentBindings}
                 jsx={this.backgroundLayout}
                 showWarnings={true}
@@ -294,7 +297,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
                 onContextMenu={this.onContextMenu}
                 onPointerDown={this.onPointerDown} >
                 <JsxParser
-                    components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView }}
+                    components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView }}
                     bindings={documentBindings}
                     jsx={this.layout}
                     showWarnings={true}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 918acff4c..821172d71 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -20,12 +20,13 @@ export interface FieldViewProps {
     fieldKey: Key;
     doc: Document;
     isSelected: () => boolean;
+    select: () => void;
     isTopMost: boolean;
 }
 
 @observer
 export class FieldView extends React.Component<FieldViewProps> {
-    public static LayoutString(fieldType: { name: string }) { return `<${fieldType.name} doc={Document} DocumentViewForField={DocumentView} fieldKey={DataKey} isSelected={isSelected} isTopMost={isTopMost} />`; }
+    public static LayoutString(fieldType: { name: string }) { return `<${fieldType.name} doc={Document} DocumentViewForField={DocumentView} fieldKey={DataKey} isSelected={isSelected} select={select} isTopMost={isTopMost} />`; }
     @computed
     get field(): FieldValue<Field> {
         const { doc, fieldKey } = this.props;
diff --git a/src/fields/BasicField.ts b/src/fields/BasicField.ts
index 91977b243..a92c4a236 100644
--- a/src/fields/BasicField.ts
+++ b/src/fields/BasicField.ts
@@ -32,7 +32,7 @@ export abstract class BasicField<T> extends Field {
             return;
         }
         let oldValue = this.data;
-        this.data = value;
+        this.setData(value);
         UndoManager.AddEvent({
             undo: () => this.Data = oldValue,
             redo: () => this.Data = value
@@ -40,6 +40,10 @@ export abstract class BasicField<T> extends Field {
         Server.UpdateField(this);
     }
 
+    protected setData(value: T) {
+        this.data = value;
+    }
+
     @action
     TrySetValue(value: any): boolean {
         if (typeof value == typeof this.data) {
diff --git a/src/fields/Document.ts b/src/fields/Document.ts
index 6667485b6..ff13732b3 100644
--- a/src/fields/Document.ts
+++ b/src/fields/Document.ts
@@ -90,6 +90,15 @@ export class Document extends Field {
         return field;
     }
 
+    GetAsync(key: Key, callback: (field: Field) => void): boolean {
+        //This currently doesn't deal with prototypes
+        if (this._proxies.has(key.Id)) {
+            Server.GetDocumentField(this, key, callback);
+            return true;
+        }
+        return false;
+    }
+
     GetT<T extends Field = Field>(key: Key, ctor: { new(...args: any[]): T }, ignoreProto: boolean = false): FieldValue<T> {
         var getfield = this.Get(key, ignoreProto);
         if (getfield != FieldWaiting) {
diff --git a/src/fields/KeyStore.ts b/src/fields/KeyStore.ts
index 7056886aa..6d6c6a546 100644
--- a/src/fields/KeyStore.ts
+++ b/src/fields/KeyStore.ts
@@ -16,6 +16,7 @@ export namespace KeyStore {
     export const ZIndex = new Key("ZIndex");
     export const Data = new Key("Data");
     export const Annotations = new Key("Annotations");
+    export const ViewType = new Key("ViewType");
     export const Layout = new Key("Layout");
     export const BackgroundLayout = new Key("BackgroundLayout");
     export const LayoutKeys = new Key("LayoutKeys");
diff --git a/src/fields/ListField.ts b/src/fields/ListField.ts
index 75c2eb343..700600804 100644
--- a/src/fields/ListField.ts
+++ b/src/fields/ListField.ts
@@ -1,4 +1,4 @@
-import { action, IArrayChange, IArraySplice, IObservableArray, observe } from "mobx";
+import { action, IArrayChange, IArraySplice, IObservableArray, observe, observable, Lambda } from "mobx";
 import { Server } from "../client/Server";
 import { UndoManager } from "../client/util/UndoManager";
 import { Types } from "../server/Message";
@@ -13,7 +13,12 @@ export class ListField<T extends Field> extends BasicField<T[]> {
         if (save) {
             Server.UpdateField(this);
         }
-        observe(this.Data as IObservableArray<T>, (change: IArrayChange<T> | IArraySplice<T>) => {
+        this.observeList();
+    }
+
+    private observeDisposer: Lambda | undefined;
+    private observeList(): void {
+        this.observeDisposer = observe(this.Data as IObservableArray<T>, (change: IArrayChange<T> | IArraySplice<T>) => {
             this.updateProxies()
             if (change.type == "splice") {
                 UndoManager.AddEvent({
@@ -27,7 +32,15 @@ export class ListField<T extends Field> extends BasicField<T[]> {
                 })
             }
             Server.UpdateField(this);
-        })
+        });
+    }
+
+    protected setData(value: T[]) {
+        if (this.observeDisposer) {
+            this.observeDisposer()
+        }
+        this.data = observable(value);
+        this.observeList();
     }
 
     private updateProxies() {
-- 
cgit v1.2.3-70-g09d2


From 27412300a3f6fd87f73fc5c1a303013113755765 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 22 Feb 2019 10:07:26 -0500
Subject: fixed some exceptions.  fixed spurious context menu.  fixed excessive
 rendering.

---
 src/client/views/DocumentDecorations.tsx           |  5 +++
 .../views/collections/CollectionDockingView.tsx    | 11 +++++-
 .../views/collections/CollectionFreeFormView.tsx   | 43 ++++++++++++----------
 .../views/collections/CollectionSchemaView.tsx     |  3 +-
 src/client/views/nodes/DocumentView.tsx            |  3 +-
 5 files changed, 40 insertions(+), 25 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 4e109d475..395a37ba5 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -5,6 +5,7 @@ import { observer } from "mobx-react";
 import './DocumentDecorations.scss'
 import { KeyStore } from '../../fields/KeyStore'
 import { NumberField } from "../../fields/NumberField";
+import { number } from "prop-types";
 
 @observer
 export class DocumentDecorations extends React.Component {
@@ -142,6 +143,10 @@ export class DocumentDecorations extends React.Component {
         if (this.Hidden) {
             return (null);
         }
+        if (isNaN(bounds.r) || isNaN(bounds.b) || isNaN(bounds.x) || isNaN(bounds.y)) {
+            console.log("DocumentDecorations: Bounds Error")
+            return (null);
+        }
         return (
             <div id="documentDecorations-container" style={{
                 width: (bounds.r - bounds.x + 40) + "px",
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 6d91aef5e..752007439 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -6,7 +6,7 @@ import { observer } from "mobx-react";
 import * as ReactDOM from 'react-dom';
 import Measure from "react-measure";
 import { Document } from "../../../fields/Document";
-import { FieldId, Opt } from "../../../fields/Field";
+import { FieldId, Opt, Field } from "../../../fields/Field";
 import { KeyStore } from "../../../fields/KeyStore";
 import { Utils } from "../../../Utils";
 import { Server } from "../../Server";
@@ -148,6 +148,13 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
             this._goldenLayout.on('stackCreated', this.stackCreated);
             this._goldenLayout.registerComponent('DocumentFrameRenderer', DockedFrameRenderer);
             this._goldenLayout.container = this._containerRef.current;
+            if (this._goldenLayout.config.maximisedItemId === '__glMaximised') {
+                try {
+                    this._goldenLayout.config.root.getItemsById(this._goldenLayout.config.maximisedItemId)[0].toggleMaximise();
+                } catch (e) {
+                    this._goldenLayout.config.maximisedItemId = null;
+                }
+            }
             this._goldenLayout.init();
         }
     }
@@ -261,7 +268,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
 
     constructor(props: any) {
         super(props);
-        Server.GetField(this.props.documentId, f => this._document = f as Document)
+        Server.GetField(this.props.documentId, action((f: Opt<Field>) => this._document = f as Document));
     }
 
     @computed private get _nativeWidth() { return this._document!.GetNumber(KeyStore.NativeWidth, 0); }
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index bd7ca5b6f..c44381f13 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -1,6 +1,6 @@
 import { observer } from "mobx-react";
 import React = require("react");
-import { action, computed } from "mobx";
+import { action, computed, trace } from "mobx";
 import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView";
 import { DragManager } from "../../util/DragManager";
 import "./CollectionFreeFormView.scss";
@@ -14,6 +14,7 @@ import { FieldWaiting } from "../../../fields/Field";
 import { Transform } from "../../util/Transform";
 import { DocumentView } from "../nodes/DocumentView";
 import { undoBatch } from "../../util/UndoManager";
+import { jSXElement } from "babel-types";
 
 @observer
 export class CollectionFreeFormView extends React.Component<SubCollectionViewProps> {
@@ -221,16 +222,29 @@ export class CollectionFreeFormView extends React.Component<SubCollectionViewPro
         return Transform.Identity.translate(-x, -y).scale(1 / this.scale);
     }
 
-    render() {
+    @computed
+    get views() {
         const { fieldKey, Document } = this.props;
-        // const value: Document[] = Document.GetList<Document>(fieldKey, []);
         const lvalue = Document.GetT<ListField<Document>>(fieldKey, ListField);
-        if (!lvalue || lvalue === "<Waiting>") {
-            return <p>Error loading collection data</p>
+        if (lvalue && lvalue != FieldWaiting) {
+            return lvalue.Data.map(doc => {
+                return (<CollectionFreeFormDocumentView key={doc.Id} Document={doc}
+                    AddDocument={this.props.addDocument}
+                    RemoveDocument={this.props.removeDocument}
+                    ScreenToLocalTransform={this.getTransform}
+                    isTopMost={false}
+                    Scaling={1}
+                    PanelSize={[doc.GetNumber(KeyStore.Width, 0), doc.GetNumber(KeyStore.Height, 0)]}
+                    ContainingCollectionView={this.props.CollectionView} />);
+            })
         }
-        const panx: number = Document.GetNumber(KeyStore.PanX, 0);
-        const pany: number = Document.GetNumber(KeyStore.PanY, 0);
+        return null;
+    }
 
+    render() {
+        const panx: number = this.props.Document.GetNumber(KeyStore.PanX, 0);
+        const pany: number = this.props.Document.GetNumber(KeyStore.PanY, 0);
+        trace()
         return (
             <div className="collectionfreeformview-container"
                 onPointerDown={this.onPointerDown}
@@ -238,25 +252,14 @@ export class CollectionFreeFormView extends React.Component<SubCollectionViewPro
                 onContextMenu={(e) => e.preventDefault()}
                 onDrop={this.onDrop}
                 onDragOver={this.onDragOver}
-                style={{
-                    borderWidth: `${COLLECTION_BORDER_WIDTH}px`,
-                }}
+                style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px`, }}
                 ref={this.createDropTarget}>
                 <div className="collectionfreeformview"
                     style={{ width: "100%", transformOrigin: "left top", transform: ` translate(${panx}px, ${pany}px) scale(${this.zoomScaling}, ${this.zoomScaling})` }}
                     ref={this._canvasRef}>
 
                     {this.props.BackgroundView ? this.props.BackgroundView() : null}
-                    {lvalue.Data.map(doc => {
-                        return (<CollectionFreeFormDocumentView key={doc.Id} Document={doc}
-                            AddDocument={this.props.addDocument}
-                            RemoveDocument={this.props.removeDocument}
-                            ScreenToLocalTransform={this.getTransform}
-                            isTopMost={false}
-                            Scaling={1}
-                            PanelSize={[doc.GetNumber(KeyStore.Width, 0), doc.GetNumber(KeyStore.Height, 0)]}
-                            ContainingCollectionView={this.props.CollectionView} />);
-                    })}
+                    {this.views}
                 </div>
             </div>
         );
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 9405c820f..f25e721c0 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -1,5 +1,5 @@
 import React = require("react")
-import { action, observable } from "mobx";
+import { action, observable, trace } from "mobx";
 import { observer } from "mobx-react";
 import Measure from "react-measure";
 import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table";
@@ -138,7 +138,6 @@ export class CollectionSchemaView extends React.Component<SubCollectionViewProps
         const columns = this.props.Document.GetList(KeyStore.ColumnsKey, [KeyStore.Title, KeyStore.Data, KeyStore.Author])
         const children = this.props.Document.GetList<Document>(this.props.fieldKey, []);
         const selected = children.length > this.selectedIndex ? children[this.selectedIndex] : undefined;
-        let me = this;
         let content = this.selectedIndex == -1 || !selected ? (null) : (
             <Measure onResize={this.setScaling}>
                 {({ measureRef }) =>
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 2114a5697..69e413c6f 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -211,10 +211,11 @@ export class DocumentView extends React.Component<DocumentViewProps> {
 
     @action
     onContextMenu = (e: React.MouseEvent): void => {
+        e.preventDefault()
+        e.stopPropagation();
         if (!SelectionManager.IsSelected(this)) {
             return;
         }
-        e.preventDefault()
 
         if (!this._contextMenuCanOpen) {
             return;
-- 
cgit v1.2.3-70-g09d2


From 1dc667d3a6b5113aa7706e97d94419dd7d50079e Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 22 Feb 2019 10:08:36 -0500
Subject: from last.

---
 src/client/views/collections/CollectionFreeFormView.tsx | 1 -
 1 file changed, 1 deletion(-)

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

diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index c44381f13..b78b1a3b6 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -244,7 +244,6 @@ export class CollectionFreeFormView extends React.Component<SubCollectionViewPro
     render() {
         const panx: number = this.props.Document.GetNumber(KeyStore.PanX, 0);
         const pany: number = this.props.Document.GetNumber(KeyStore.PanY, 0);
-        trace()
         return (
             <div className="collectionfreeformview-container"
                 onPointerDown={this.onPointerDown}
-- 
cgit v1.2.3-70-g09d2


From 9b23c5123abf42c3751938d831556cdb94ad3951 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 22 Feb 2019 13:42:25 -0500
Subject: moved common code into CollectionViewBase.

---
 src/client/documents/Documents.ts                  |  2 +-
 src/client/util/DragManager.ts                     |  1 +
 .../views/collections/CollectionDockingView.tsx    |  3 +-
 .../views/collections/CollectionFreeFormView.tsx   | 59 ++--------------
 .../views/collections/CollectionSchemaView.tsx     | 13 ++--
 src/client/views/collections/CollectionView.tsx    | 20 +-----
 .../views/collections/CollectionViewBase.tsx       | 82 ++++++++++++++++++++++
 7 files changed, 102 insertions(+), 78 deletions(-)
 create mode 100644 src/client/views/collections/CollectionViewBase.tsx

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index bfa6cb7a9..156a09316 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -13,7 +13,7 @@ import { CollectionFreeFormView } from "../views/collections/CollectionFreeFormV
 import { FieldId } from "../../fields/Field";
 import { CollectionView, CollectionViewType } from "../views/collections/CollectionView";
 
-interface DocumentOptions {
+export interface DocumentOptions {
     x?: number;
     y?: number;
     width?: number;
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 6d5fe12a7..eb4b3aeaa 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -44,6 +44,7 @@ export namespace DragManager {
         drop: (e: Event, de: DropEvent) => void;
     }
 
+
     export function MakeDropTarget(element: HTMLElement, options: DropOptions): DragDropDisposer {
         if ("canDrop" in element.dataset) {
             throw new Error("Element is already droppable, can't make it droppable again");
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 752007439..857af023d 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -14,8 +14,9 @@ import { DragManager } from "../../util/DragManager";
 import { undoBatch } from "../../util/UndoManager";
 import { DocumentView } from "../nodes/DocumentView";
 import "./CollectionDockingView.scss";
-import { CollectionViewProps, COLLECTION_BORDER_WIDTH, SubCollectionViewProps } from "./CollectionView";
+import { COLLECTION_BORDER_WIDTH } from "./CollectionView";
 import React = require("react");
+import { SubCollectionViewProps } from "./CollectionViewBase";
 
 @observer
 export class CollectionDockingView extends React.Component<SubCollectionViewProps> {
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index b78b1a3b6..b8312aff7 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -4,20 +4,18 @@ import { action, computed, trace } from "mobx";
 import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView";
 import { DragManager } from "../../util/DragManager";
 import "./CollectionFreeFormView.scss";
-import { COLLECTION_BORDER_WIDTH, CollectionViewProps, SubCollectionViewProps } from "./CollectionView";
+import { COLLECTION_BORDER_WIDTH } from "./CollectionView";
 import { KeyStore } from "../../../fields/KeyStore";
 import { Document } from "../../../fields/Document";
 import { ListField } from "../../../fields/ListField";
-import { NumberField } from "../../../fields/NumberField";
-import { Documents } from "../../documents/Documents";
 import { FieldWaiting } from "../../../fields/Field";
 import { Transform } from "../../util/Transform";
 import { DocumentView } from "../nodes/DocumentView";
 import { undoBatch } from "../../util/UndoManager";
-import { jSXElement } from "babel-types";
+import { CollectionViewBase, SubCollectionViewProps } from "./CollectionViewBase";
 
 @observer
-export class CollectionFreeFormView extends React.Component<SubCollectionViewProps> {
+export class CollectionFreeFormView extends CollectionViewBase {
     private _canvasRef = React.createRef<HTMLDivElement>();
     private _lastX: number = 0;
     private _lastY: number = 0;
@@ -45,13 +43,8 @@ export class CollectionFreeFormView extends React.Component<SubCollectionViewPro
     @undoBatch
     @action
     drop = (e: Event, de: DragManager.DropEvent) => {
+        super.drop(e, de);
         const doc: DocumentView = de.data["document"];
-        if (doc.props.ContainingCollectionView && doc.props.ContainingCollectionView !== this.props.CollectionView) {
-            if (doc.props.RemoveDocument) {
-                doc.props.RemoveDocument(doc.props.Document);
-            }
-            this.props.addDocument(doc.props.Document);
-        }
         const xOffset = de.data["xOffset"] as number || 0;
         const yOffset = de.data["yOffset"] as number || 0;
         //this should be able to use translate and scale methods on an Identity transform, no?
@@ -62,21 +55,6 @@ export class CollectionFreeFormView extends React.Component<SubCollectionViewPro
         doc.props.Document.SetNumber(KeyStore.X, x);
         doc.props.Document.SetNumber(KeyStore.Y, y);
         this.bringToFront(doc);
-        e.stopPropagation();
-    }
-
-    private dropDisposer?: DragManager.DragDropDisposer;
-    createDropTarget = (ele: HTMLDivElement) => {
-        if (this.dropDisposer) {
-            this.dropDisposer();
-        }
-        if (ele) {
-            this.dropDisposer = DragManager.MakeDropTarget(ele, {
-                handlers: {
-                    drop: this.drop
-                }
-            });
-        }
     }
 
     @action
@@ -148,36 +126,11 @@ export class CollectionFreeFormView extends React.Component<SubCollectionViewPro
 
     @action
     onDrop = (e: React.DragEvent): void => {
-        e.stopPropagation()
-        e.preventDefault()
-        let fReader = new FileReader()
-        let file = e.dataTransfer.items[0].getAsFile();
-        let that = this;
         const panx: number = this.props.Document.GetNumber(KeyStore.PanX, 0);
         const pany: number = this.props.Document.GetNumber(KeyStore.PanY, 0);
         let x = e.pageX - panx
         let y = e.pageY - pany
-
-        fReader.addEventListener("load", action("drop", () => {
-            if (fReader.result) {
-                let url = "" + fReader.result;
-                let doc = Documents.ImageDocument(url, {
-                    x: x, y: y
-                })
-                let docs = that.props.Document.GetT(KeyStore.Data, ListField);
-                if (docs != FieldWaiting) {
-                    if (!docs) {
-                        docs = new ListField<Document>();
-                        that.props.Document.Set(KeyStore.Data, docs)
-                    }
-                    docs.Data.push(doc);
-                }
-            }
-        }), false)
-
-        if (file) {
-            fReader.readAsDataURL(file)
-        }
+        super.onDrop(e, { x: x, y: y });
     }
 
     onDragOver = (): void => {
@@ -249,7 +202,7 @@ export class CollectionFreeFormView extends React.Component<SubCollectionViewPro
                 onPointerDown={this.onPointerDown}
                 onWheel={this.onPointerWheel}
                 onContextMenu={(e) => e.preventDefault()}
-                onDrop={this.onDrop}
+                onDrop={this.onDrop.bind(this)}
                 onDragOver={this.onDragOver}
                 style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px`, }}
                 ref={this.createDropTarget}>
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index f25e721c0..df732308a 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -5,7 +5,7 @@ import Measure from "react-measure";
 import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table";
 import "react-table/react-table.css";
 import { Document } from "../../../fields/Document";
-import { Field } from "../../../fields/Field";
+import { Field, FieldWaiting } from "../../../fields/Field";
 import { KeyStore } from "../../../fields/KeyStore";
 import { CompileScript, ToField } from "../../util/Scripting";
 import { Transform } from "../../util/Transform";
@@ -13,10 +13,11 @@ import { EditableView } from "../EditableView";
 import { DocumentView } from "../nodes/DocumentView";
 import { FieldView, FieldViewProps } from "../nodes/FieldView";
 import "./CollectionSchemaView.scss";
-import { COLLECTION_BORDER_WIDTH, CollectionViewProps, SubCollectionViewProps } from "./CollectionView";
+import { COLLECTION_BORDER_WIDTH } from "./CollectionView";
+import { CollectionViewBase } from "./CollectionViewBase";
 
 @observer
-export class CollectionSchemaView extends React.Component<SubCollectionViewProps> {
+export class CollectionSchemaView extends CollectionViewBase {
     private _mainCont = React.createRef<HTMLDivElement>();
 
     private DIVIDER_WIDTH = 5;
@@ -117,6 +118,7 @@ export class CollectionSchemaView extends React.Component<SubCollectionViewProps
         }
     }
 
+
     getTransform = (): Transform => {
         return this.props.ScreenToLocalTransform().translate(- COLLECTION_BORDER_WIDTH - this.DIVIDER_WIDTH - this._dividerX, - COLLECTION_BORDER_WIDTH).scale(1 / this._parentScaling);
     }
@@ -181,7 +183,10 @@ export class CollectionSchemaView extends React.Component<SubCollectionViewProps
                     }
                 </Measure>
                 <div className="collectionSchemaView-dividerDragger" style={{ position: "relative", background: "black", float: "left", width: `${this.DIVIDER_WIDTH}px`, height: "100%" }} onPointerDown={this.onDividerDown} />
-                <div className="collectionSchemaView-previewRegion" style={{ position: "relative", float: "left", width: `calc(${100 - this._splitPercentage}% - ${this.DIVIDER_WIDTH}px)`, height: "100%" }}>
+                <div className="collectionSchemaView-previewRegion"
+                    onDrop={(e: React.DragEvent) => this.onDrop(e, {})}
+                    ref={this.createDropTarget}
+                    style={{ position: "relative", float: "left", width: `calc(${100 - this._splitPercentage}% - ${this.DIVIDER_WIDTH}px)`, height: "100%" }}>
                     {content}
                 </div>
             </div >
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 651d85879..ff1803ec3 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -1,36 +1,18 @@
 import { action, computed } from "mobx";
 import { observer } from "mobx-react";
 import { Document } from "../../../fields/Document";
-import { Key } from "../../../fields/Key";
 import { ListField } from "../../../fields/ListField";
 import { SelectionManager } from "../../util/SelectionManager";
 import { ContextMenu } from "../ContextMenu";
 import React = require("react");
-import { Transform } from "../../util/Transform";
 import { KeyStore } from "../../../fields/KeyStore";
 import { NumberField } from "../../../fields/NumberField";
 import { CollectionFreeFormView } from "./CollectionFreeFormView";
 import { CollectionDockingView } from "./CollectionDockingView";
 import { CollectionSchemaView } from "./CollectionSchemaView";
-import { Opt } from "../../../fields/Field";
+import { CollectionViewProps } from "./CollectionViewBase";
 
 
-export interface CollectionViewProps {
-    fieldKey: Key;
-    Document: Document;
-    ScreenToLocalTransform: () => Transform;
-    isSelected: () => boolean;
-    isTopMost: boolean;
-    select: (ctrlPressed: boolean) => void;
-    BackgroundView?: () => JSX.Element;
-}
-
-export interface SubCollectionViewProps extends CollectionViewProps {
-    active: () => boolean;
-    addDocument: (doc: Document) => void;
-    removeDocument: (doc: Document) => boolean;
-    CollectionView: Opt<CollectionView>;
-}
 
 export enum CollectionViewType {
     Invalid,
diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx
new file mode 100644
index 000000000..06de56383
--- /dev/null
+++ b/src/client/views/collections/CollectionViewBase.tsx
@@ -0,0 +1,82 @@
+import { action, computed } from "mobx";
+import { Document } from "../../../fields/Document";
+import { ListField } from "../../../fields/ListField";
+import React = require("react");
+import { KeyStore } from "../../../fields/KeyStore";
+import { Opt, FieldWaiting } from "../../../fields/Field";
+import { undoBatch } from "../../util/UndoManager";
+import { DragManager } from "../../util/DragManager";
+import { DocumentView } from "../nodes/DocumentView";
+import { Documents, DocumentOptions } from "../../documents/Documents";
+import { Key } from "../../../fields/Key";
+import { Transform } from "../../util/Transform";
+
+
+export interface CollectionViewProps {
+    fieldKey: Key;
+    Document: Document;
+    ScreenToLocalTransform: () => Transform;
+    isSelected: () => boolean;
+    isTopMost: boolean;
+    select: (ctrlPressed: boolean) => void;
+    BackgroundView?: () => JSX.Element;
+}
+export interface SubCollectionViewProps extends CollectionViewProps {
+    active: () => boolean;
+    addDocument: (doc: Document) => void;
+    removeDocument: (doc: Document) => boolean;
+    CollectionView: any;
+}
+
+export class CollectionViewBase extends React.Component<SubCollectionViewProps> {
+    private dropDisposer?: DragManager.DragDropDisposer;
+    protected createDropTarget = (ele: HTMLDivElement) => {
+        if (this.dropDisposer) {
+            this.dropDisposer();
+        }
+        if (ele) {
+            this.dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } });
+        }
+    }
+
+    @undoBatch
+    @action
+    protected drop(e: Event, de: DragManager.DropEvent) {
+        const doc: DocumentView = de.data["document"];
+        if (doc.props.ContainingCollectionView && doc.props.ContainingCollectionView !== this.props.CollectionView) {
+            if (doc.props.RemoveDocument) {
+                doc.props.RemoveDocument(doc.props.Document);
+            }
+            this.props.addDocument(doc.props.Document);
+        }
+        e.stopPropagation();
+    }
+
+    @action
+    protected onDrop(e: React.DragEvent, options: DocumentOptions): void {
+        e.stopPropagation()
+        e.preventDefault()
+        let fReader = new FileReader()
+        let file = e.dataTransfer.items[0].getAsFile();
+        let that = this;
+
+        fReader.addEventListener("load", action("drop", () => {
+            if (fReader.result) {
+                let url = "" + fReader.result;
+                let doc = Documents.ImageDocument(url, options)
+                let docs = that.props.Document.GetT(KeyStore.Data, ListField);
+                if (docs != FieldWaiting) {
+                    if (!docs) {
+                        docs = new ListField<Document>();
+                        that.props.Document.Set(KeyStore.Data, docs)
+                    }
+                    docs.Data.push(doc);
+                }
+            }
+        }), false)
+
+        if (file) {
+            fReader.readAsDataURL(file)
+        }
+    }
+}
-- 
cgit v1.2.3-70-g09d2


From 1e83695f1380b7824d36bdc55305c44117f6da2c Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 22 Feb 2019 15:24:42 -0500
Subject: changed PanelSize to PanelWidth/Height

---
 src/client/views/DocumentDecorations.tsx           |  2 +-
 src/client/views/Main.tsx                          |  3 ++-
 .../views/collections/CollectionDockingView.tsx    |  3 ++-
 .../views/collections/CollectionFreeFormView.tsx   |  3 ++-
 .../views/collections/CollectionSchemaView.tsx     |  3 ++-
 .../views/nodes/CollectionFreeFormDocumentView.tsx | 24 ++++++++++++++--------
 src/client/views/nodes/DocumentView.tsx            |  3 ++-
 7 files changed, 26 insertions(+), 15 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 395a37ba5..7b64a4c2c 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -28,7 +28,7 @@ export class DocumentDecorations extends React.Component {
             }
             let transform = (element.props.ScreenToLocalTransform().scale(element.props.Scaling)).inverse();
             var [sptX, sptY] = transform.transformPoint(0, 0);
-            let [bptX, bptY] = transform.transformPoint(element.props.PanelSize[0], element.props.PanelSize[1]);
+            let [bptX, bptY] = transform.transformPoint(element.props.PanelWidth, element.props.PanelHeight);
             return {
                 x: Math.min(sptX, bounds.x), y: Math.min(sptY, bounds.y),
                 r: Math.max(bptX, bounds.r), b: Math.max(bptY, bounds.b)
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index fe1a999ec..6f6a89839 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -107,7 +107,8 @@ Documents.initProtos(() => {
                 <DocumentView Document={mainContainer}
                     AddDocument={undefined} RemoveDocument={undefined} ScreenToLocalTransform={() => Transform.Identity}
                     Scaling={1}
-                    PanelSize={[0, 0]}
+                    PanelWidth={0}
+                    PanelHeight={0}
                     isTopMost={true}
                     ContainingCollectionView={undefined} />
                 <DocumentDecorations />
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 857af023d..7ac8ea5e4 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -290,7 +290,8 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
                     AddDocument={undefined}
                     RemoveDocument={undefined}
                     Scaling={this._parentScaling}
-                    PanelSize={[this._nativeWidth, this._nativeHeight]}
+                    PanelWidth={this._nativeWidth}
+                    PanelHeight={this._nativeHeight}
                     ScreenToLocalTransform={this.ScreenToLocalTransform}
                     isTopMost={true}
                     ContainingCollectionView={undefined} />
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index b8312aff7..e31fb25b9 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -187,7 +187,8 @@ export class CollectionFreeFormView extends CollectionViewBase {
                     ScreenToLocalTransform={this.getTransform}
                     isTopMost={false}
                     Scaling={1}
-                    PanelSize={[doc.GetNumber(KeyStore.Width, 0), doc.GetNumber(KeyStore.Height, 0)]}
+                    PanelWidth={doc.GetNumber(KeyStore.Width, 0)}
+                    PanelHeight={doc.GetNumber(KeyStore.Height, 0)}
                     ContainingCollectionView={this.props.CollectionView} />);
             })
         }
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index df732308a..7e7d23fe4 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -149,7 +149,8 @@ export class CollectionSchemaView extends CollectionViewBase {
                             ScreenToLocalTransform={this.getTransform}
                             Scaling={this._parentScaling}
                             isTopMost={false}
-                            PanelSize={[this._panelWidth, this._panelHeight]}
+                            PanelWidth={this._panelWidth}
+                            PanelHeight={this._panelHeight}
                             ContainingCollectionView={this.props.CollectionView} />
                     </div>
                 }
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 5568935fa..ad6756918 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -1,4 +1,4 @@
-import { computed } from "mobx";
+import { computed, trace } from "mobx";
 import { observer } from "mobx-react";
 import { KeyStore } from "../../../fields/KeyStore";
 import { NumberField } from "../../../fields/NumberField";
@@ -69,15 +69,25 @@ export class CollectionFreeFormDocumentView extends React.Component<DocumentView
         this.props.Document.SetData(KeyStore.ZIndex, h, NumberField)
     }
 
+    @computed
+    get parentScaling() {
+        return this.nativeWidth > 0 ? this.width / this.nativeWidth : 1;
+    }
 
     getTransform = (): Transform => {
-        var parentScaling = this.nativeWidth > 0 ? this.width / this.nativeWidth : 1;
         return this.props.ScreenToLocalTransform().
-            translate(-this.props.Document.GetNumber(KeyStore.X, 0), -this.props.Document.GetNumber(KeyStore.Y, 0)).scale(1 / parentScaling);
+            translate(-this.props.Document.GetNumber(KeyStore.X, 0), -this.props.Document.GetNumber(KeyStore.Y, 0)).scale(1 / this.parentScaling);
+    }
+
+    @computed
+    get docView() {
+        return <DocumentView {...this.props}
+            Scaling={this.parentScaling}
+            ScreenToLocalTransform={this.getTransform}
+        />
     }
 
     render() {
-        var parentScaling = this.nativeWidth > 0 ? this.width / this.nativeWidth : 1;
         return (
             <div ref={this._mainCont} style={{
                 transformOrigin: "left top",
@@ -88,11 +98,7 @@ export class CollectionFreeFormDocumentView extends React.Component<DocumentView
                 zIndex: this.zIndex,
                 backgroundColor: "transparent"
             }} >
-
-                <DocumentView {...this.props}
-                    Scaling={parentScaling}
-                    ScreenToLocalTransform={this.getTransform}
-                />
+                {this.docView}
             </div>
         );
     }
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 69e413c6f..c026e13cd 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -31,7 +31,8 @@ export interface DocumentViewProps {
     isTopMost: boolean;
     //tfs: This shouldn't be necessary I don't think
     Scaling: number;
-    PanelSize: number[];
+    PanelWidth: number;
+    PanelHeight: number;
 }
 export interface JsxArgs extends DocumentViewProps {
     Keys: { [name: string]: Key }
-- 
cgit v1.2.3-70-g09d2


From f6822450875291159daac6d7b6abd4da9cfed9b6 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 22 Feb 2019 17:10:44 -0500
Subject: fixed re-render issue for collection free form documents.

---
 src/client/views/DocumentDecorations.tsx           |  5 +--
 src/client/views/Main.tsx                          |  6 +--
 .../views/collections/CollectionDockingView.tsx    | 10 ++---
 .../views/collections/CollectionFreeFormView.tsx   | 46 ++++++-------------
 .../views/collections/CollectionSchemaView.tsx     | 52 ++++++++++------------
 .../views/nodes/CollectionFreeFormDocumentView.tsx |  9 ++--
 src/client/views/nodes/DocumentView.tsx            |  8 ++--
 src/fields/Document.ts                             |  4 ++
 8 files changed, 59 insertions(+), 81 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 7b64a4c2c..efd50e49e 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -5,7 +5,6 @@ import { observer } from "mobx-react";
 import './DocumentDecorations.scss'
 import { KeyStore } from '../../fields/KeyStore'
 import { NumberField } from "../../fields/NumberField";
-import { number } from "prop-types";
 
 @observer
 export class DocumentDecorations extends React.Component {
@@ -26,9 +25,9 @@ export class DocumentDecorations extends React.Component {
             if (element.props.isTopMost) {
                 return bounds;
             }
-            let transform = (element.props.ScreenToLocalTransform().scale(element.props.Scaling)).inverse();
+            let transform = (element.props.ScreenToLocalTransform().scale(element.props.ContentScaling())).inverse();
             var [sptX, sptY] = transform.transformPoint(0, 0);
-            let [bptX, bptY] = transform.transformPoint(element.props.PanelWidth, element.props.PanelHeight);
+            let [bptX, bptY] = transform.transformPoint(element.props.PanelWidth(), element.props.PanelHeight());
             return {
                 x: Math.min(sptX, bounds.x), y: Math.min(sptY, bounds.y),
                 r: Math.max(bptX, bounds.r), b: Math.max(bptY, bounds.b)
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 6f6a89839..661a2ac20 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -106,9 +106,9 @@ Documents.initProtos(() => {
             <div style={{ position: "absolute", width: "100%", height: "100%" }}>
                 <DocumentView Document={mainContainer}
                     AddDocument={undefined} RemoveDocument={undefined} ScreenToLocalTransform={() => Transform.Identity}
-                    Scaling={1}
-                    PanelWidth={0}
-                    PanelHeight={0}
+                    ContentScaling={() => 1}
+                    PanelWidth={() => 0}
+                    PanelHeight={() => 0}
                     isTopMost={true}
                     ContainingCollectionView={undefined} />
                 <DocumentDecorations />
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 7ac8ea5e4..86dc66e39 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -272,13 +272,13 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
         Server.GetField(this.props.documentId, action((f: Opt<Field>) => this._document = f as Document));
     }
 
-    @computed private get _nativeWidth() { return this._document!.GetNumber(KeyStore.NativeWidth, 0); }
-    @computed private get _nativeHeight() { return this._document!.GetNumber(KeyStore.NativeHeight, 0); }
-    @computed private get _parentScaling() { return this._panelWidth / (this._nativeWidth ? this._nativeWidth : this._panelWidth); }; // used to transfer the dimensions of the content pane in the DOM to the ParentScaling prop of the DocumentView
+    private _nativeWidth = () => { return this._document!.GetNumber(KeyStore.NativeWidth, 0); }
+    private _nativeHeight = () => { return this._document!.GetNumber(KeyStore.NativeHeight, 0); }
+    private _contentScaling = () => { return this._panelWidth / (this._nativeWidth() ? this._nativeWidth() : this._panelWidth); }
 
     ScreenToLocalTransform = () => {
         let { scale, translateX, translateY } = Utils.GetScreenTransform(this._mainCont.current!);
-        return CollectionDockingView.Instance.props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(scale / this._parentScaling)
+        return CollectionDockingView.Instance.props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(scale / this._contentScaling())
     }
 
     render() {
@@ -289,7 +289,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
                 <DocumentView key={this._document.Id} Document={this._document}
                     AddDocument={undefined}
                     RemoveDocument={undefined}
-                    Scaling={this._parentScaling}
+                    ContentScaling={this._contentScaling}
                     PanelWidth={this._nativeWidth}
                     PanelHeight={this._nativeHeight}
                     ScreenToLocalTransform={this.ScreenToLocalTransform}
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index e31fb25b9..43bc24a12 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -22,23 +22,14 @@ export class CollectionFreeFormView extends CollectionViewBase {
     private _downX: number = 0;
     private _downY: number = 0;
 
-    @computed
-    get isAnnotationOverlay() { return this.props.fieldKey == KeyStore.Annotations; }
-
-    @computed
-    get nativeWidth() { return this.props.Document.GetNumber(KeyStore.NativeWidth, 0); }
-    @computed
-    get nativeHeight() { return this.props.Document.GetNumber(KeyStore.NativeHeight, 0); }
-
-    @computed
-    get zoomScaling() { return this.props.Document.GetNumber(KeyStore.Scale, 1); }
-
-    @computed
-    get resizeScaling() { return this.isAnnotationOverlay ? this.props.Document.GetNumber(KeyStore.Width, 0) / this.nativeWidth : 1; }
 
-    constructor(props: SubCollectionViewProps) {
-        super(props);
-    }
+    @computed get panX(): number { return this.props.Document.GetNumber(KeyStore.PanX, 0) }
+    @computed get panY(): number { return this.props.Document.GetNumber(KeyStore.PanY, 0) }
+    @computed get scale(): number { return this.props.Document.GetNumber(KeyStore.Scale, 1); }
+    @computed get isAnnotationOverlay() { return this.props.fieldKey == KeyStore.Annotations; }
+    @computed get nativeWidth() { return this.props.Document.GetNumber(KeyStore.NativeWidth, 0); }
+    @computed get nativeHeight() { return this.props.Document.GetNumber(KeyStore.NativeHeight, 0); }
+    @computed get zoomScaling() { return this.props.Document.GetNumber(KeyStore.Scale, 1); }
 
     @undoBatch
     @action
@@ -154,27 +145,16 @@ export class CollectionFreeFormView extends CollectionViewBase {
         });
     }
 
-    @computed
-    get translate(): [number, number] {
-        const x = this.props.Document.GetNumber(KeyStore.PanX, 0);
-        const y = this.props.Document.GetNumber(KeyStore.PanY, 0);
-        return [x, y];
-    }
-
-    @computed
-    get scale(): number {
-        return this.props.Document.GetNumber(KeyStore.Scale, 1);
-    }
-
     getTransform = (): Transform => {
         return this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH).transform(this.getLocalTransform())
     }
 
     getLocalTransform = (): Transform => {
-        const [x, y] = this.translate;
-        return Transform.Identity.translate(-x, -y).scale(1 / this.scale);
+        return Transform.Identity.translate(-this.panX, -this.panY).scale(1 / this.scale);
     }
 
+    noScaling = () => 1;
+
     @computed
     get views() {
         const { fieldKey, Document } = this.props;
@@ -186,9 +166,9 @@ export class CollectionFreeFormView extends CollectionViewBase {
                     RemoveDocument={this.props.removeDocument}
                     ScreenToLocalTransform={this.getTransform}
                     isTopMost={false}
-                    Scaling={1}
-                    PanelWidth={doc.GetNumber(KeyStore.Width, 0)}
-                    PanelHeight={doc.GetNumber(KeyStore.Height, 0)}
+                    ContentScaling={this.noScaling}
+                    PanelWidth={doc.Width}
+                    PanelHeight={doc.Height}
                     ContainingCollectionView={this.props.CollectionView} />);
             })
         }
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 7e7d23fe4..ca47f6998 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -19,14 +19,14 @@ import { CollectionViewBase } from "./CollectionViewBase";
 @observer
 export class CollectionSchemaView extends CollectionViewBase {
     private _mainCont = React.createRef<HTMLDivElement>();
-
     private DIVIDER_WIDTH = 5;
 
-    @observable
-    selectedIndex = 0;
-
-    @observable
-    _splitPercentage: number = 50;
+    @observable _contentScaling = 1; // used to transfer the dimensions of the content pane in the DOM to the ContentScaling prop of the DocumentView
+    @observable _dividerX = 0;
+    @observable _panelWidth = 0;
+    @observable _panelHeight = 0;
+    @observable _selectedIndex = 0;
+    @observable _splitPercentage: number = 50;
 
     renderCell = (rowProps: CellInfo) => {
         let props: FieldViewProps = {
@@ -67,7 +67,6 @@ export class CollectionSchemaView extends CollectionViewBase {
         )
     }
 
-
     private getTrProps: ComponentPropsGetterR = (state, rowInfo) => {
         const that = this;
         if (!rowInfo) {
@@ -75,7 +74,7 @@ export class CollectionSchemaView extends CollectionViewBase {
         }
         return {
             onClick: action((e: React.MouseEvent, handleOriginal: Function) => {
-                that.selectedIndex = rowInfo.index;
+                that._selectedIndex = rowInfo.index;
                 this._splitPercentage += 0.05; // bcz - ugh - needed to force Measure to do its thing and call onResize
 
                 if (handleOriginal) {
@@ -83,8 +82,8 @@ export class CollectionSchemaView extends CollectionViewBase {
                 }
             }),
             style: {
-                background: rowInfo.index == this.selectedIndex ? "#00afec" : "white",
-                color: rowInfo.index == this.selectedIndex ? "white" : "black"
+                background: rowInfo.index == this._selectedIndex ? "#00afec" : "white",
+                color: rowInfo.index == this._selectedIndex ? "white" : "black"
             }
         };
     }
@@ -94,7 +93,6 @@ export class CollectionSchemaView extends CollectionViewBase {
         let nativeWidth = this._mainCont.current!.getBoundingClientRect();
         this._splitPercentage = Math.round((e.clientX - nativeWidth.left) / nativeWidth.width * 100);
     }
-
     onDividerUp = (e: PointerEvent): void => {
         document.removeEventListener("pointermove", this.onDividerMove);
         document.removeEventListener('pointerup', this.onDividerUp);
@@ -118,39 +116,37 @@ export class CollectionSchemaView extends CollectionViewBase {
         }
     }
 
-
-    getTransform = (): Transform => {
-        return this.props.ScreenToLocalTransform().translate(- COLLECTION_BORDER_WIDTH - this.DIVIDER_WIDTH - this._dividerX, - COLLECTION_BORDER_WIDTH).scale(1 / this._parentScaling);
-    }
-
     @action
     setScaling = (r: any) => {
         const children = this.props.Document.GetList<Document>(this.props.fieldKey, []);
-        const selected = children.length > this.selectedIndex ? children[this.selectedIndex] : undefined;
+        const selected = children.length > this._selectedIndex ? children[this._selectedIndex] : undefined;
         this._panelWidth = r.entry.width;
         this._panelHeight = r.entry.height ? r.entry.height : this._panelHeight;
-        this._parentScaling = r.entry.width / selected!.GetNumber(KeyStore.NativeWidth, r.entry.width);
+        this._contentScaling = r.entry.width / selected!.GetNumber(KeyStore.NativeWidth, r.entry.width);
+    }
+
+    getContentScaling = (): number => this._contentScaling;
+    getPanelWidth = (): number => this._panelWidth;
+    getPanelHeight = (): number => this._panelHeight;
+    getTransform = (): Transform => {
+        return this.props.ScreenToLocalTransform().translate(- COLLECTION_BORDER_WIDTH - this.DIVIDER_WIDTH - this._dividerX, - COLLECTION_BORDER_WIDTH).scale(1 / this._contentScaling);
     }
 
-    @observable _parentScaling = 1; // used to transfer the dimensions of the content pane in the DOM to the ParentScaling prop of the DocumentView
-    @observable _dividerX = 0;
-    @observable _panelWidth = 0;
-    @observable _panelHeight = 0;
     render() {
         const columns = this.props.Document.GetList(KeyStore.ColumnsKey, [KeyStore.Title, KeyStore.Data, KeyStore.Author])
         const children = this.props.Document.GetList<Document>(this.props.fieldKey, []);
-        const selected = children.length > this.selectedIndex ? children[this.selectedIndex] : undefined;
-        let content = this.selectedIndex == -1 || !selected ? (null) : (
+        const selected = children.length > this._selectedIndex ? children[this._selectedIndex] : undefined;
+        let content = this._selectedIndex == -1 || !selected ? (null) : (
             <Measure onResize={this.setScaling}>
                 {({ measureRef }) =>
                     <div ref={measureRef}>
                         <DocumentView Document={selected}
                             AddDocument={this.props.addDocument} RemoveDocument={this.props.removeDocument}
-                            ScreenToLocalTransform={this.getTransform}
-                            Scaling={this._parentScaling}
                             isTopMost={false}
-                            PanelWidth={this._panelWidth}
-                            PanelHeight={this._panelHeight}
+                            ScreenToLocalTransform={this.getTransform}
+                            ContentScaling={this.getContentScaling}
+                            PanelWidth={this.getPanelWidth}
+                            PanelHeight={this.getPanelHeight}
                             ContainingCollectionView={this.props.CollectionView} />
                     </div>
                 }
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index ad6756918..17123bf52 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -24,7 +24,7 @@ export class CollectionFreeFormDocumentView extends React.Component<DocumentView
 
     @computed
     get transform(): string {
-        return `scale(${this.props.Scaling}, ${this.props.Scaling}) translate(${this.props.Document.GetNumber(KeyStore.X, 0)}px, ${this.props.Document.GetNumber(KeyStore.Y, 0)}px)`;
+        return `scale(${this.props.ContentScaling()}, ${this.props.ContentScaling()}) translate(${this.props.Document.GetNumber(KeyStore.X, 0)}px, ${this.props.Document.GetNumber(KeyStore.Y, 0)}px)`;
     }
 
     @computed
@@ -69,20 +69,19 @@ export class CollectionFreeFormDocumentView extends React.Component<DocumentView
         this.props.Document.SetData(KeyStore.ZIndex, h, NumberField)
     }
 
-    @computed
-    get parentScaling() {
+    contentScaling = () => {
         return this.nativeWidth > 0 ? this.width / this.nativeWidth : 1;
     }
 
     getTransform = (): Transform => {
         return this.props.ScreenToLocalTransform().
-            translate(-this.props.Document.GetNumber(KeyStore.X, 0), -this.props.Document.GetNumber(KeyStore.Y, 0)).scale(1 / this.parentScaling);
+            translate(-this.props.Document.GetNumber(KeyStore.X, 0), -this.props.Document.GetNumber(KeyStore.Y, 0)).scale(1 / this.contentScaling());
     }
 
     @computed
     get docView() {
         return <DocumentView {...this.props}
-            Scaling={this.parentScaling}
+            ContentScaling={this.contentScaling}
             ScreenToLocalTransform={this.getTransform}
         />
     }
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index c026e13cd..34a230669 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -30,9 +30,9 @@ export interface DocumentViewProps {
     ScreenToLocalTransform: () => Transform;
     isTopMost: boolean;
     //tfs: This shouldn't be necessary I don't think
-    Scaling: number;
-    PanelWidth: number;
-    PanelHeight: number;
+    ContentScaling: () => number;
+    PanelWidth: () => number;
+    PanelHeight: () => number;
 }
 export interface JsxArgs extends DocumentViewProps {
     Keys: { [name: string]: Key }
@@ -293,7 +293,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         var nativeHeight = this.props.Document.GetNumber(KeyStore.NativeHeight, 0);
         var nodeWidth = nativeWidth > 0 ? nativeWidth.toString() + "px" : "100%";
         var nodeHeight = nativeHeight > 0 ? nativeHeight.toString() + "px" : "100%";
-        var scaling = this.props.Scaling;
+        var scaling = this.props.ContentScaling();
         return (
             <div className="documentView-node" ref={this._mainCont} style={{ width: nodeWidth, height: nodeHeight, transformOrigin: "left top", transform: `scale(${scaling},${scaling})` }}
                 onContextMenu={this.onContextMenu}
diff --git a/src/fields/Document.ts b/src/fields/Document.ts
index ff13732b3..0d7d357a0 100644
--- a/src/fields/Document.ts
+++ b/src/fields/Document.ts
@@ -30,6 +30,10 @@ export class Document extends Field {
         }
     }
 
+    public Width = () => { return this.GetNumber(KeyStore.Width, 0) }
+    public Height = () => { return this.GetNumber(KeyStore.Height, 0) }
+    public Scale = () => { return this.GetNumber(KeyStore.Scale, 1) }
+
     @computed
     public get Title() {
         return this.GetText(KeyStore.Title, "<untitled>");
-- 
cgit v1.2.3-70-g09d2


From 5fc58916b07453d212645b313c9074b5dcc1ee84 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Fri, 22 Feb 2019 21:39:40 -0500
Subject: moved backgroundLayout to CollectionFreeForm

---
 src/client/views/DocumentDecorations.tsx           |  2 +-
 .../views/collections/CollectionFreeFormView.tsx   | 58 ++++++++++++++--------
 .../views/collections/CollectionSchemaView.tsx     |  3 +-
 src/client/views/collections/CollectionView.tsx    |  2 +-
 .../views/collections/CollectionViewBase.tsx       |  2 +-
 src/client/views/nodes/DocumentView.tsx            | 41 ++++-----------
 src/client/views/nodes/FieldView.tsx               |  3 +-
 src/client/views/nodes/FormattedTextBox.tsx        |  1 -
 8 files changed, 55 insertions(+), 57 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index efd50e49e..09df8cdaa 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -101,7 +101,7 @@ export class DocumentDecorations extends React.Component {
         }
 
         SelectionManager.SelectedDocuments().forEach(element => {
-            const rect = element.screenRect;
+            const rect = element.screenRect();
             if (rect.width !== 0) {
                 let doc = element.props.Document;
                 let width = doc.GetOrCreate(KeyStore.Width, NumberField);
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index 43bc24a12..565402046 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -1,18 +1,25 @@
+import { action, computed } from "mobx";
 import { observer } from "mobx-react";
-import React = require("react");
-import { action, computed, trace } from "mobx";
-import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView";
-import { DragManager } from "../../util/DragManager";
-import "./CollectionFreeFormView.scss";
-import { COLLECTION_BORDER_WIDTH } from "./CollectionView";
-import { KeyStore } from "../../../fields/KeyStore";
 import { Document } from "../../../fields/Document";
-import { ListField } from "../../../fields/ListField";
 import { FieldWaiting } from "../../../fields/Field";
+import { KeyStore } from "../../../fields/KeyStore";
+import { ListField } from "../../../fields/ListField";
+import { TextField } from "../../../fields/TextField";
+import { DragManager } from "../../util/DragManager";
 import { Transform } from "../../util/Transform";
-import { DocumentView } from "../nodes/DocumentView";
 import { undoBatch } from "../../util/UndoManager";
-import { CollectionViewBase, SubCollectionViewProps } from "./CollectionViewBase";
+import { CollectionDockingView } from "../collections/CollectionDockingView";
+import { CollectionSchemaView } from "../collections/CollectionSchemaView";
+import { CollectionView } from "../collections/CollectionView";
+import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView";
+import { DocumentView } from "../nodes/DocumentView";
+import { FormattedTextBox } from "../nodes/FormattedTextBox";
+import { ImageBox } from "../nodes/ImageBox";
+import "./CollectionFreeFormView.scss";
+import { COLLECTION_BORDER_WIDTH } from "./CollectionView";
+import { CollectionViewBase } from "./CollectionViewBase";
+import React = require("react");
+const JsxParser = require('react-jsx-parser').default;//TODO Why does this need to be imported like this?
 
 @observer
 export class CollectionFreeFormView extends CollectionViewBase {
@@ -145,16 +152,13 @@ export class CollectionFreeFormView extends CollectionViewBase {
         });
     }
 
-    getTransform = (): Transform => {
-        return this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH).transform(this.getLocalTransform())
-    }
 
-    getLocalTransform = (): Transform => {
-        return Transform.Identity.translate(-this.panX, -this.panY).scale(1 / this.scale);
+    @computed get backgroundLayout(): string | undefined {
+        let field = this.props.Document.GetT(KeyStore.BackgroundLayout, TextField);
+        if (field && field !== "<Waiting>") {
+            return field.Data;
+        }
     }
-
-    noScaling = () => 1;
-
     @computed
     get views() {
         const { fieldKey, Document } = this.props;
@@ -175,6 +179,21 @@ export class CollectionFreeFormView extends CollectionViewBase {
         return null;
     }
 
+    @computed
+    get backgroundView() {
+        return !this.backgroundLayout ? (null) :
+            (<JsxParser
+                components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView }}
+                bindings={this.props.bindings}
+                jsx={this.backgroundLayout}
+                showWarnings={true}
+                onError={(test: any) => console.log(test)}
+            />);
+    }
+    getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH).transform(this.getLocalTransform())
+    getLocalTransform = (): Transform => Transform.Identity.translate(-this.panX, -this.panY).scale(1 / this.scale);
+    noScaling = () => 1;
+
     render() {
         const panx: number = this.props.Document.GetNumber(KeyStore.PanX, 0);
         const pany: number = this.props.Document.GetNumber(KeyStore.PanY, 0);
@@ -190,8 +209,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
                 <div className="collectionfreeformview"
                     style={{ width: "100%", transformOrigin: "left top", transform: ` translate(${panx}px, ${pany}px) scale(${this.zoomScaling}, ${this.zoomScaling})` }}
                     ref={this._canvasRef}>
-
-                    {this.props.BackgroundView ? this.props.BackgroundView() : null}
+                    {this.backgroundView}
                     {this.views}
                 </div>
             </div>
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index ca47f6998..d2db93120 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -34,7 +34,8 @@ export class CollectionSchemaView extends CollectionViewBase {
             fieldKey: rowProps.value[1],
             isSelected: () => false,
             select: () => { },
-            isTopMost: false
+            isTopMost: false,
+            bindings: {}
         }
         let contents = (
             <FieldView {...props} />
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index ff1803ec3..90080ab43 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -28,7 +28,7 @@ export class CollectionView extends React.Component<CollectionViewProps> {
 
     public static LayoutString(fieldKey: string = "DataKey") {
         return `<CollectionView Document={Document}
-                    ScreenToLocalTransform={ScreenToLocalTransform} fieldKey={${fieldKey}} isSelected={isSelected} select={select}
+                    ScreenToLocalTransform={ScreenToLocalTransform} fieldKey={${fieldKey}} isSelected={isSelected} select={select} bindings={bindings}
                     isTopMost={isTopMost} BackgroundView={BackgroundView} />`;
     }
     public active = () => {
diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx
index 06de56383..da7f71163 100644
--- a/src/client/views/collections/CollectionViewBase.tsx
+++ b/src/client/views/collections/CollectionViewBase.tsx
@@ -19,7 +19,7 @@ export interface CollectionViewProps {
     isSelected: () => boolean;
     isTopMost: boolean;
     select: (ctrlPressed: boolean) => void;
-    BackgroundView?: () => JSX.Element;
+    bindings: any;
 }
 export interface SubCollectionViewProps extends CollectionViewProps {
     active: () => boolean;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index d9b1d90d8..a9e211431 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -5,7 +5,6 @@ import { Field, FieldWaiting, Opt } from "../../../fields/Field";
 import { Key } from "../../../fields/Key";
 import { KeyStore } from "../../../fields/KeyStore";
 import { ListField } from "../../../fields/ListField";
-import { TextField } from "../../../fields/TextField";
 import { DragManager } from "../../util/DragManager";
 import { SelectionManager } from "../../util/SelectionManager";
 import { Transform } from "../../util/Transform";
@@ -84,21 +83,13 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     private _downX: number = 0;
     private _downY: number = 0;
 
-    get screenRect(): ClientRect | DOMRect {
-        return (this._mainCont.current) ? this._mainCont.current.getBoundingClientRect() : new DOMRect();
-    }
     @computed get active(): boolean { return SelectionManager.IsSelected(this) || !this.props.ContainingCollectionView || this.props.ContainingCollectionView.active(); }
     @computed get topMost(): boolean { return !this.props.ContainingCollectionView || this.props.ContainingCollectionView.collectionViewType == CollectionViewType.Docking; }
     @computed get layout(): string { return this.props.Document.GetText(KeyStore.Layout, "<p>Error loading layout data</p>"); }
     @computed get layoutKeys(): Key[] { return this.props.Document.GetData(KeyStore.LayoutKeys, ListField, new Array<Key>()); }
     @computed get layoutFields(): Key[] { return this.props.Document.GetData(KeyStore.LayoutFields, ListField, new Array<Key>()); }
-    @computed get backgroundLayout(): string | undefined {
-        let field = this.props.Document.GetT(KeyStore.BackgroundLayout, TextField);
-        if (field && field !== "<Waiting>") {
-            return field.Data;
-        }
-    }
 
+    screenRect = (): ClientRect | DOMRect => this._mainCont.current ? this._mainCont.current.getBoundingClientRect() : new DOMRect();
 
     onPointerDown = (e: React.PointerEvent): void => {
         this._downX = e.clientX;
@@ -174,6 +165,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15)
     }
 
+    @action
     onContextMenu = (e: React.MouseEvent): void => {
         e.preventDefault()
         e.stopPropagation();
@@ -230,32 +222,19 @@ export class DocumentView extends React.Component<DocumentViewProps> {
             let field = this.props.Document.Get(key);
             this._documentBindings[key.Name] = field && field != FieldWaiting ? field.GetValue() : field;
         }
-
-        /*
-        tfs:
-        Should this be moved to CollectionFreeformView or another component that renders
-        Document backgrounds (or contents based on a layout key, which could be used here as well)
-         that CollectionFreeformView uses? It seems like a lot for it to be here considering only one view currently uses it...
-         */
-        let backgroundLayout = this.backgroundLayout;
-        if (backgroundLayout) {
-            let backgroundView = () => (<JsxParser
-                components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView }}
-                bindings={this._documentBindings}
-                jsx={this.backgroundLayout}
-                showWarnings={true}
-                onError={(test: any) => { console.log(test) }}
-            />);
-            this._documentBindings.BackgroundView = backgroundView;
-        }
+        this._documentBindings.bindings = this._documentBindings;
 
         var scaling = this.props.ContentScaling();
         var nativeWidth = this.props.Document.GetNumber(KeyStore.NativeWidth, 0);
         var nativeHeight = this.props.Document.GetNumber(KeyStore.NativeHeight, 0);
-        var nodeWidth = nativeWidth > 0 ? nativeWidth.toString() + "px" : "100%";
-        var nodeHeight = nativeHeight > 0 ? nativeHeight.toString() + "px" : "100%";
         return (
-            <div className="documentView-node" ref={this._mainCont} style={{ width: nodeWidth, height: nodeHeight, transformOrigin: "left top", transform: `scale(${scaling},${scaling})` }}
+            <div className="documentView-node" ref={this._mainCont}
+                style={{
+                    width: nativeWidth > 0 ? nativeWidth.toString() + "px" : "100%",
+                    height: nativeHeight > 0 ? nativeHeight.toString() + "px" : "100%",
+                    transformOrigin: "left top",
+                    transform: `scale(${scaling},${scaling})`
+                }}
                 onContextMenu={this.onContextMenu}
                 onPointerDown={this.onPointerDown} >
                 {this.mainContent}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 821172d71..97d3f2a85 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -22,11 +22,12 @@ export interface FieldViewProps {
     isSelected: () => boolean;
     select: () => void;
     isTopMost: boolean;
+    bindings: any;
 }
 
 @observer
 export class FieldView extends React.Component<FieldViewProps> {
-    public static LayoutString(fieldType: { name: string }) { return `<${fieldType.name} doc={Document} DocumentViewForField={DocumentView} fieldKey={DataKey} isSelected={isSelected} select={select} isTopMost={isTopMost} />`; }
+    public static LayoutString(fieldType: { name: string }) { return `<${fieldType.name} doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={DataKey} isSelected={isSelected} select={select} isTopMost={isTopMost} />`; }
     @computed
     get field(): FieldValue<Field> {
         const { doc, fieldKey } = this.props;
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index b17650d06..16728d471 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -6,7 +6,6 @@ import { schema } from "prosemirror-schema-basic";
 import { EditorState, Transaction } from "prosemirror-state";
 import { EditorView } from "prosemirror-view";
 import { Opt, FieldWaiting, FieldValue } from "../../../fields/Field";
-import { SelectionManager } from "../../util/SelectionManager";
 import "./FormattedTextBox.scss";
 import React = require("react")
 import { RichTextField } from "../../../fields/RichTextField";
-- 
cgit v1.2.3-70-g09d2


From b358acef21cbed80944407d0f562c990a1df4c16 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Fri, 22 Feb 2019 22:36:22 -0500
Subject: added dropping of image urls

---
 src/client/views/DocumentDecorations.tsx           |  8 ++--
 .../views/collections/CollectionFreeFormView.tsx   |  8 ++--
 .../views/collections/CollectionViewBase.tsx       | 55 +++++++++++++++-------
 3 files changed, 48 insertions(+), 23 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 09df8cdaa..2f012913d 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -21,13 +21,13 @@ export class DocumentDecorations extends React.Component {
 
     @computed
     get Bounds(): { x: number, y: number, b: number, r: number } {
-        return SelectionManager.SelectedDocuments().reduce((bounds, element) => {
-            if (element.props.isTopMost) {
+        return SelectionManager.SelectedDocuments().reduce((bounds, documentView) => {
+            if (documentView.props.isTopMost) {
                 return bounds;
             }
-            let transform = (element.props.ScreenToLocalTransform().scale(element.props.ContentScaling())).inverse();
+            let transform = (documentView.props.ScreenToLocalTransform().scale(documentView.props.ContentScaling())).inverse();
             var [sptX, sptY] = transform.transformPoint(0, 0);
-            let [bptX, bptY] = transform.transformPoint(element.props.PanelWidth(), element.props.PanelHeight());
+            let [bptX, bptY] = transform.transformPoint(documentView.props.PanelWidth(), documentView.props.PanelHeight());
             return {
                 x: Math.min(sptX, bounds.x), y: Math.min(sptY, bounds.y),
                 r: Math.max(bptX, bounds.r), b: Math.max(bptY, bounds.b)
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index 565402046..c12a82617 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -19,6 +19,7 @@ import "./CollectionFreeFormView.scss";
 import { COLLECTION_BORDER_WIDTH } from "./CollectionView";
 import { CollectionViewBase } from "./CollectionViewBase";
 import React = require("react");
+import { Documents } from "../../documents/Documents";
 const JsxParser = require('react-jsx-parser').default;//TODO Why does this need to be imported like this?
 
 @observer
@@ -126,9 +127,10 @@ export class CollectionFreeFormView extends CollectionViewBase {
     onDrop = (e: React.DragEvent): void => {
         const panx: number = this.props.Document.GetNumber(KeyStore.PanX, 0);
         const pany: number = this.props.Document.GetNumber(KeyStore.PanY, 0);
-        let x = e.pageX - panx
-        let y = e.pageY - pany
-        super.onDrop(e, { x: x, y: y });
+        let transform = this.getTransform();
+
+        var pt = transform.transformPoint(e.pageX, e.pageY);
+        super.onDrop(e, { x: pt[0], y: pt[1] });
     }
 
     onDragOver = (): void => {
diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx
index da7f71163..4bf0d074a 100644
--- a/src/client/views/collections/CollectionViewBase.tsx
+++ b/src/client/views/collections/CollectionViewBase.tsx
@@ -56,27 +56,50 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
     protected onDrop(e: React.DragEvent, options: DocumentOptions): void {
         e.stopPropagation()
         e.preventDefault()
-        let fReader = new FileReader()
-        let file = e.dataTransfer.items[0].getAsFile();
         let that = this;
 
-        fReader.addEventListener("load", action("drop", () => {
-            if (fReader.result) {
-                let url = "" + fReader.result;
-                let doc = Documents.ImageDocument(url, options)
-                let docs = that.props.Document.GetT(KeyStore.Data, ListField);
-                if (docs != FieldWaiting) {
-                    if (!docs) {
-                        docs = new ListField<Document>();
-                        that.props.Document.Set(KeyStore.Data, docs)
+        for (let i = 0; i < e.dataTransfer.items.length; i++) {
+            let item = e.dataTransfer.items[i];
+            if (item.kind === "string" && item.type.indexOf("uri") != -1) {
+                e.dataTransfer.items[i].getAsString(function (s) {
+                    action(() => {
+                        var img = Documents.ImageDocument(s, { ...options, nativeWidth: 300, nativeHeight: 300, width: 300, height: 300 })
+
+                        let docs = that.props.Document.GetT(KeyStore.Data, ListField);
+                        if (docs != FieldWaiting) {
+                            if (!docs) {
+                                docs = new ListField<Document>();
+                                that.props.Document.Set(KeyStore.Data, docs)
+                            }
+                            docs.Data.push(img);
+                        }
+                    })()
+
+                })
+            }
+            if (item.kind == "file" && item.type.indexOf("image")) {
+                let fReader = new FileReader()
+                let file = item.getAsFile();
+
+                fReader.addEventListener("load", action("drop", () => {
+                    if (fReader.result) {
+                        let url = "" + fReader.result;
+                        let doc = Documents.ImageDocument(url, options)
+                        let docs = that.props.Document.GetT(KeyStore.Data, ListField);
+                        if (docs != FieldWaiting) {
+                            if (!docs) {
+                                docs = new ListField<Document>();
+                                that.props.Document.Set(KeyStore.Data, docs)
+                            }
+                            docs.Data.push(doc);
+                        }
                     }
-                    docs.Data.push(doc);
+                }), false)
+
+                if (file) {
+                    fReader.readAsDataURL(file)
                 }
             }
-        }), false)
-
-        if (file) {
-            fReader.readAsDataURL(file)
         }
     }
 }
-- 
cgit v1.2.3-70-g09d2


From 451c31e529dad9fbec94e71790907848f7c3fb24 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sat, 23 Feb 2019 02:34:58 -0500
Subject: css hacking to fix layout issues related to making a captioned image
 style

---
 src/client/documents/Documents.ts                    | 20 ++++++++++++++++----
 .../views/collections/CollectionFreeFormView.scss    |  2 ++
 .../views/collections/CollectionFreeFormView.tsx     |  5 +++--
 src/client/views/nodes/FieldView.tsx                 |  3 ++-
 src/client/views/nodes/FormattedTextBox.scss         |  4 ++--
 src/client/views/nodes/FormattedTextBox.tsx          |  5 ++---
 src/client/views/nodes/ImageBox.scss                 |  3 ++-
 src/fields/KeyStore.ts                               |  1 +
 8 files changed, 30 insertions(+), 13 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 156a09316..6ec5aa711 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -5,13 +5,10 @@ import { TextField } from "../../fields/TextField";
 import { NumberField } from "../../fields/NumberField";
 import { ListField } from "../../fields/ListField";
 import { FormattedTextBox } from "../views/nodes/FormattedTextBox";
-import { CollectionDockingView } from "../views/collections/CollectionDockingView";
-import { CollectionSchemaView } from "../views/collections/CollectionSchemaView";
 import { ImageField } from "../../fields/ImageField";
 import { ImageBox } from "../views/nodes/ImageBox";
-import { CollectionFreeFormView } from "../views/collections/CollectionFreeFormView";
-import { FieldId } from "../../fields/Field";
 import { CollectionView, CollectionViewType } from "../views/collections/CollectionView";
+import { FieldView } from "../views/nodes/FieldView";
 
 export interface DocumentOptions {
     x?: number;
@@ -102,12 +99,27 @@ export namespace Documents {
             return imageProto;
         }
         return imageProto;
+
     }
 
+    // example of custom display string for an image that shows a caption.
+    function CaptionLayoutString() {
+        return `<div style="position:absolute; height:100%">
+            <div style="position:relative; margin:auto; width:85%; margin:auto" >`
+            + ImageBox.LayoutString() +
+            `</div>
+            <div style="position:relative; min-height:15%; overflow:scroll; max-height:15%; text-align:center; ">`
+            + FormattedTextBox.LayoutString("CaptionKey") +
+            `</div> 
+        </div>` };
+
     export function ImageDocument(url: string, options: DocumentOptions = {}): Document {
         let doc = GetImagePrototype().MakeDelegate();
         setupOptions(doc, options);
         doc.Set(KeyStore.Data, new ImageField(new URL(url)));
+        doc.Set(KeyStore.Caption, new TextField("my caption..."));
+        doc.Set(KeyStore.BackgroundLayout, new TextField(CaptionLayoutString()));
+        doc.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data, KeyStore.Annotations, KeyStore.Caption]));
 
         let annotation = Documents.TextDocument({ title: "hello" });
         doc.Set(KeyStore.Annotations, new ListField([annotation]));
diff --git a/src/client/views/collections/CollectionFreeFormView.scss b/src/client/views/collections/CollectionFreeFormView.scss
index 4cf474f77..6d678528a 100644
--- a/src/client/views/collections/CollectionFreeFormView.scss
+++ b/src/client/views/collections/CollectionFreeFormView.scss
@@ -11,5 +11,7 @@
         position: absolute;
         top: 0;
         left: 0;
+        width:100%;
+        height: 100%
     }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index c12a82617..6d2662105 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -34,7 +34,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
     @computed get panX(): number { return this.props.Document.GetNumber(KeyStore.PanX, 0) }
     @computed get panY(): number { return this.props.Document.GetNumber(KeyStore.PanY, 0) }
     @computed get scale(): number { return this.props.Document.GetNumber(KeyStore.Scale, 1); }
-    @computed get isAnnotationOverlay() { return this.props.fieldKey == KeyStore.Annotations; }
+    @computed get isAnnotationOverlay() { return this.props.fieldKey.Id === KeyStore.Annotations.Id; } // bcz: ? Why do we need to compare Id's?
     @computed get nativeWidth() { return this.props.Document.GetNumber(KeyStore.NativeWidth, 0); }
     @computed get nativeHeight() { return this.props.Document.GetNumber(KeyStore.NativeHeight, 0); }
     @computed get zoomScaling() { return this.props.Document.GetNumber(KeyStore.Scale, 1); }
@@ -91,6 +91,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
             let [dx, dy] = this.props.ScreenToLocalTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY);
 
             this.SetPan(x + dx, y + dy);
+            console.log("px = " + x + " " + y)
         }
         this._lastX = e.pageX;
         this._lastY = e.pageY;
@@ -209,7 +210,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
                 style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px`, }}
                 ref={this.createDropTarget}>
                 <div className="collectionfreeformview"
-                    style={{ width: "100%", transformOrigin: "left top", transform: ` translate(${panx}px, ${pany}px) scale(${this.zoomScaling}, ${this.zoomScaling})` }}
+                    style={{ transformOrigin: "left top", transform: ` translate(${panx}px, ${pany}px) scale(${this.zoomScaling}, ${this.zoomScaling})` }}
                     ref={this._canvasRef}>
                     {this.backgroundView}
                     {this.views}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 97d3f2a85..9dda08d8d 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -27,7 +27,8 @@ export interface FieldViewProps {
 
 @observer
 export class FieldView extends React.Component<FieldViewProps> {
-    public static LayoutString(fieldType: { name: string }) { return `<${fieldType.name} doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={DataKey} isSelected={isSelected} select={select} isTopMost={isTopMost} />`; }
+    public static LayoutString(fieldType: { name: string }, fieldStr: string = "DataKey") { return `<${fieldType.name} doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={${fieldStr}} isSelected={isSelected} select={select} isTopMost={isTopMost} />`; }
+
     @computed
     get field(): FieldValue<Field> {
         const { doc, fieldKey } = this.props;
diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss
index 5139d5d6b..872a2138b 100644
--- a/src/client/views/nodes/FormattedTextBox.scss
+++ b/src/client/views/nodes/FormattedTextBox.scss
@@ -1,7 +1,7 @@
 .ProseMirror {
-    margin-top: -1em;
     width: 100%;
-    height: 100%;
+    height: auto;
+    min-height: 100%
 }
 
 .ProseMirror:focus {
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 16728d471..c0969a8c3 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -10,8 +10,6 @@ import "./FormattedTextBox.scss";
 import React = require("react")
 import { RichTextField } from "../../../fields/RichTextField";
 import { FieldViewProps, FieldView } from "./FieldView";
-import { CollectionFreeFormDocumentView } from "./CollectionFreeFormDocumentView";
-import { observer } from "mobx-react";
 
 
 // FormattedTextBox: Displays an editable plain text node that maps to a specified Key of a Document
@@ -32,7 +30,7 @@ import { observer } from "mobx-react";
 //]
 export class FormattedTextBox extends React.Component<FieldViewProps> {
 
-    public static LayoutString() { return FieldView.LayoutString(FormattedTextBox) }
+    public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(FormattedTextBox, fieldStr) }
     private _ref: React.RefObject<HTMLDivElement>;
     private _editorView: Opt<EditorView>;
     private _reactionDisposer: Opt<IReactionDisposer>;
@@ -118,6 +116,7 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
             style={{
                 color: "initial",
                 whiteSpace: "initial",
+                height: "auto"
             }}
             onPointerDown={this.onPointerDown}
             ref={this._ref} />)
diff --git a/src/client/views/nodes/ImageBox.scss b/src/client/views/nodes/ImageBox.scss
index 36f5e0fe0..5b15b3329 100644
--- a/src/client/views/nodes/ImageBox.scss
+++ b/src/client/views/nodes/ImageBox.scss
@@ -1,7 +1,8 @@
 
 .imageBox-cont {
     padding: 0vw;
-    position: absolute;
+    position: relative;
+    text-align: center;
     width: 100%;
     max-width: 100%;
     max-height: 100%
diff --git a/src/fields/KeyStore.ts b/src/fields/KeyStore.ts
index 6d6c6a546..42e3f6b58 100644
--- a/src/fields/KeyStore.ts
+++ b/src/fields/KeyStore.ts
@@ -22,5 +22,6 @@ export namespace KeyStore {
     export const LayoutKeys = new Key("LayoutKeys");
     export const LayoutFields = new Key("LayoutFields");
     export const ColumnsKey = new Key("SchemaColumns");
+    export const Caption = new Key("Caption");
     export const ActiveFrame = new Key("ActiveFrame");
 }
-- 
cgit v1.2.3-70-g09d2


From 5b4ad5f5a567357b78c8aeed88554af3376532d2 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sat, 23 Feb 2019 02:36:01 -0500
Subject: from last

---
 src/client/views/collections/CollectionFreeFormView.tsx | 1 -
 1 file changed, 1 deletion(-)

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

diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index 6d2662105..4799eda97 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -91,7 +91,6 @@ export class CollectionFreeFormView extends CollectionViewBase {
             let [dx, dy] = this.props.ScreenToLocalTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY);
 
             this.SetPan(x + dx, y + dy);
-            console.log("px = " + x + " " + y)
         }
         this._lastX = e.pageX;
         this._lastY = e.pageY;
-- 
cgit v1.2.3-70-g09d2


From 9663623dbe9f54bd3f233c8de7cb9f112f17a7cc Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Sat, 23 Feb 2019 04:49:48 -0500
Subject: Added web clippings on drag and drop

---
 src/client/documents/Documents.ts                  | 24 +++++++++++++++++++++
 .../views/collections/CollectionFreeFormView.tsx   |  3 ++-
 .../views/collections/CollectionViewBase.tsx       |  9 ++++++++
 src/client/views/nodes/DocumentView.tsx            |  3 ++-
 src/client/views/nodes/FieldView.tsx               |  4 ++++
 src/client/views/nodes/WebView.tsx                 | 22 +++++++++++++++++++
 src/fields/HtmlField.ts                            | 25 ++++++++++++++++++++++
 src/fields/KeyStore.ts                             |  1 +
 src/fields/TextField.ts                            |  2 +-
 src/server/Message.ts                              |  2 +-
 src/server/ServerUtil.ts                           |  6 +++++-
 11 files changed, 96 insertions(+), 5 deletions(-)
 create mode 100644 src/client/views/nodes/WebView.tsx
 create mode 100644 src/fields/HtmlField.ts

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 6ec5aa711..d8e1db0b0 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -9,6 +9,8 @@ import { ImageField } from "../../fields/ImageField";
 import { ImageBox } from "../views/nodes/ImageBox";
 import { CollectionView, CollectionViewType } from "../views/collections/CollectionView";
 import { FieldView } from "../views/nodes/FieldView";
+import { HtmlField } from "../../fields/HtmlField";
+import { WebView } from "../views/nodes/WebView";
 
 export interface DocumentOptions {
     x?: number;
@@ -79,6 +81,28 @@ export namespace Documents {
         return doc;
     }
 
+    let htmlProto: Document;
+    const htmlProtoId = "htmlProto";
+    function GetHtmlPrototype(): Document {
+        if (!htmlProto) {
+            htmlProto = new Document(htmlProtoId);
+            htmlProto.Set(KeyStore.X, new NumberField(0));
+            htmlProto.Set(KeyStore.Y, new NumberField(0));
+            htmlProto.Set(KeyStore.Width, new NumberField(300));
+            htmlProto.Set(KeyStore.Height, new NumberField(150));
+            htmlProto.Set(KeyStore.Layout, new TextField(WebView.LayoutString()));
+            htmlProto.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data]));
+        }
+        return htmlProto;
+    }
+
+    export function HtmlDocument(html: string, options: DocumentOptions = {}): Document {
+        let doc = GetHtmlPrototype().MakeDelegate();
+        setupOptions(doc, options);
+        doc.Set(KeyStore.Data, new HtmlField(html));
+        return doc;
+    }
+
     let imageProto: Document;
     const imageProtoId = "imageProto";
     function GetImagePrototype(): Document {
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index 4799eda97..b031c35a7 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -13,6 +13,7 @@ import { CollectionSchemaView } from "../collections/CollectionSchemaView";
 import { CollectionView } from "../collections/CollectionView";
 import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView";
 import { DocumentView } from "../nodes/DocumentView";
+import { WebView } from "../nodes/WebView";
 import { FormattedTextBox } from "../nodes/FormattedTextBox";
 import { ImageBox } from "../nodes/ImageBox";
 import "./CollectionFreeFormView.scss";
@@ -185,7 +186,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
     get backgroundView() {
         return !this.backgroundLayout ? (null) :
             (<JsxParser
-                components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView }}
+                components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebView }}
                 bindings={this.props.bindings}
                 jsx={this.backgroundLayout}
                 showWarnings={true}
diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx
index 4bf0d074a..7e269caf1 100644
--- a/src/client/views/collections/CollectionViewBase.tsx
+++ b/src/client/views/collections/CollectionViewBase.tsx
@@ -58,6 +58,15 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
         e.preventDefault()
         let that = this;
 
+        let html = e.dataTransfer.getData("text/html");
+        let text = e.dataTransfer.getData("text/plain");
+        if (html) {
+            let htmlDoc = Documents.HtmlDocument(html, { ...options });
+            htmlDoc.SetText(KeyStore.DocumentText, text);
+            this.props.addDocument(htmlDoc);
+            return;
+        }
+
         for (let i = 0; i < e.dataTransfer.items.length; i++) {
             let item = e.dataTransfer.items[i];
             if (item.kind === "string" && item.type.indexOf("uri") != -1) {
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index a9e211431..ad1328e5d 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -12,6 +12,7 @@ import { CollectionDockingView } from "../collections/CollectionDockingView";
 import { CollectionFreeFormView } from "../collections/CollectionFreeFormView";
 import { CollectionSchemaView } from "../collections/CollectionSchemaView";
 import { CollectionView, CollectionViewType } from "../collections/CollectionView";
+import { WebView } from "./WebView";
 import { ContextMenu } from "../ContextMenu";
 import { FormattedTextBox } from "../nodes/FormattedTextBox";
 import { ImageBox } from "../nodes/ImageBox";
@@ -196,7 +197,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
 
     @computed get mainContent() {
         return <JsxParser
-            components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView }}
+            components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebView }}
             bindings={this._documentBindings}
             jsx={this.layout}
             showWarnings={true}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 9dda08d8d..1a9d325db 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -10,6 +10,8 @@ import { ImageField } from "../../../fields/ImageField";
 import { Key } from "../../../fields/Key";
 import { FormattedTextBox } from "./FormattedTextBox";
 import { ImageBox } from "./ImageBox";
+import { HtmlField } from "../../../fields/HtmlField";
+import { WebView } from "./WebView";
 
 //
 // these properties get assigned through the render() method of the DocumentView when it creates this node.
@@ -50,6 +52,8 @@ export class FieldView extends React.Component<FieldViewProps> {
         }
         else if (field instanceof NumberField) {
             return <p>{field.Data}</p>
+        } else if (field instanceof HtmlField) {
+            return <WebView {...this.props} />
         } else if (field != FieldWaiting) {
             return <p>{field.GetValue}</p>
         } else
diff --git a/src/client/views/nodes/WebView.tsx b/src/client/views/nodes/WebView.tsx
new file mode 100644
index 000000000..717aa8bf5
--- /dev/null
+++ b/src/client/views/nodes/WebView.tsx
@@ -0,0 +1,22 @@
+import { FieldViewProps, FieldView } from "./FieldView";
+import { computed } from "mobx";
+import { observer } from "mobx-react";
+import { KeyStore } from "../../../fields/KeyStore";
+import React = require('react')
+import { TextField } from "../../../fields/TextField";
+import { HtmlField } from "../../../fields/HtmlField";
+import { RichTextField } from "../../../fields/RichTextField";
+
+@observer
+export class WebView extends React.Component<FieldViewProps> {
+    public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(WebView, fieldStr) }
+
+    @computed
+    get html(): string {
+        return this.props.doc.GetData(KeyStore.Data, HtmlField, "" as string);
+    }
+
+    render() {
+        return <span dangerouslySetInnerHTML={{ __html: this.html }}></span>
+    }
+}
\ No newline at end of file
diff --git a/src/fields/HtmlField.ts b/src/fields/HtmlField.ts
new file mode 100644
index 000000000..a07326095
--- /dev/null
+++ b/src/fields/HtmlField.ts
@@ -0,0 +1,25 @@
+import { BasicField } from "./BasicField";
+import { Types } from "../server/Message";
+import { FieldId } from "./Field";
+
+export class HtmlField extends BasicField<string> {
+    constructor(data: string = "<html></html>", id?: FieldId, save: boolean = true) {
+        super(data, save, id);
+    }
+
+    ToScriptString(): string {
+        return `new HtmlField("${this.Data}")`;
+    }
+
+    Copy() {
+        return new HtmlField(this.Data);
+    }
+
+    ToJson(): { _id: string; type: Types; data: any; } {
+        return {
+            type: Types.Html,
+            data: this.Data,
+            _id: this.Id,
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/fields/KeyStore.ts b/src/fields/KeyStore.ts
index 42e3f6b58..290fa2be7 100644
--- a/src/fields/KeyStore.ts
+++ b/src/fields/KeyStore.ts
@@ -24,4 +24,5 @@ export namespace KeyStore {
     export const ColumnsKey = new Key("SchemaColumns");
     export const Caption = new Key("Caption");
     export const ActiveFrame = new Key("ActiveFrame");
+    export const DocumentText = new Key("DocumentText");
 }
diff --git a/src/fields/TextField.ts b/src/fields/TextField.ts
index ad96ab6d9..71d8ea310 100644
--- a/src/fields/TextField.ts
+++ b/src/fields/TextField.ts
@@ -22,4 +22,4 @@ export class TextField extends BasicField<string> {
             _id: this.Id
         }
     }
-}
+}
\ No newline at end of file
diff --git a/src/server/Message.ts b/src/server/Message.ts
index 7f3190f7f..80fc9a80d 100644
--- a/src/server/Message.ts
+++ b/src/server/Message.ts
@@ -45,7 +45,7 @@ export class GetFieldArgs {
 }
 
 export enum Types {
-    Number, List, Key, Image, Document, Text, RichText, DocumentReference
+    Number, List, Key, Image, Document, Text, RichText, DocumentReference, Html
 }
 
 export class DocumentTransfer implements Transferable {
diff --git a/src/server/ServerUtil.ts b/src/server/ServerUtil.ts
index 46c409ec4..08e72fdae 100644
--- a/src/server/ServerUtil.ts
+++ b/src/server/ServerUtil.ts
@@ -9,6 +9,7 @@ import { Document } from './../fields/Document';
 import { Server } from './../client/Server';
 import { Types } from './Message';
 import { Utils } from '../Utils';
+import { HtmlField } from '../fields/HtmlField';
 
 export class ServerUtils {
     public static FromJson(json: any): Field {
@@ -27,6 +28,8 @@ export class ServerUtils {
                 return new NumberField(data, id, false)
             case Types.Text:
                 return new TextField(data, id, false)
+            case Types.Html:
+                return new HtmlField(data, id, false)
             case Types.RichText:
                 return new RichTextField(data, id, false)
             case Types.Key:
@@ -42,7 +45,8 @@ export class ServerUtils {
                     doc._proxies.set(element[0], element[1]);
                 });
                 return doc
+            default:
+                throw Error("Error, unrecognized field type received from server. If you just created a new field type, be sure to add it here");
         }
-        return new TextField(data, id)
     }
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From cdcfa6efa54a79b304cdcb2ffb084451116aeaac Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sat, 23 Feb 2019 10:12:39 -0500
Subject: added an overlay layer to collections... but it blocks events.  not
 sure how to fix.

---
 src/client/documents/Documents.ts                  |  7 +++++++
 .../views/collections/CollectionFreeFormView.tsx   | 24 ++++++++++++++++++++++
 src/fields/KeyStore.ts                             |  1 +
 3 files changed, 32 insertions(+)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 6ec5aa711..e0d44e535 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -112,6 +112,12 @@ export namespace Documents {
             + FormattedTextBox.LayoutString("CaptionKey") +
             `</div> 
         </div>` };
+    function OverlayLayoutString() {
+        return `<div style="position:absolute; height:100%; width:100%">
+            <div style="position:absolute; max-height:10%;  width:100%; min-height:10%; overflow:scroll;text-align:center;bottom:0;">`
+            + FormattedTextBox.LayoutString("CaptionKey") +
+            `</div> 
+        </div>` };
 
     export function ImageDocument(url: string, options: DocumentOptions = {}): Document {
         let doc = GetImagePrototype().MakeDelegate();
@@ -119,6 +125,7 @@ export namespace Documents {
         doc.Set(KeyStore.Data, new ImageField(new URL(url)));
         doc.Set(KeyStore.Caption, new TextField("my caption..."));
         doc.Set(KeyStore.BackgroundLayout, new TextField(CaptionLayoutString()));
+        //doc.Set(KeyStore.OverlayLayout, new TextField(OverlayLayoutString()));
         doc.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data, KeyStore.Annotations, KeyStore.Caption]));
 
         let annotation = Documents.TextDocument({ title: "hello" });
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index 4799eda97..ee0f3730d 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -161,6 +161,12 @@ export class CollectionFreeFormView extends CollectionViewBase {
             return field.Data;
         }
     }
+    @computed get overlayLayout(): string | undefined {
+        let field = this.props.Document.GetT(KeyStore.OverlayLayout, TextField);
+        if (field && field !== "<Waiting>") {
+            return field.Data;
+        }
+    }
     @computed
     get views() {
         const { fieldKey, Document } = this.props;
@@ -192,6 +198,17 @@ export class CollectionFreeFormView extends CollectionViewBase {
                 onError={(test: any) => console.log(test)}
             />);
     }
+    @computed
+    get overlayView() {
+        return !this.overlayLayout ? (null) :
+            (<JsxParser
+                components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView }}
+                bindings={this.props.bindings}
+                jsx={this.overlayLayout}
+                showWarnings={true}
+                onError={(test: any) => console.log(test)}
+            />);
+    }
     getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH).transform(this.getLocalTransform())
     getLocalTransform = (): Transform => Transform.Identity.translate(-this.panX, -this.panY).scale(1 / this.scale);
     noScaling = () => 1;
@@ -199,6 +216,12 @@ export class CollectionFreeFormView extends CollectionViewBase {
     render() {
         const panx: number = this.props.Document.GetNumber(KeyStore.PanX, 0);
         const pany: number = this.props.Document.GetNumber(KeyStore.PanY, 0);
+        var overlay = this.overlayView ?
+            <div style={{ position: "absolute", width: "100%", height: "100%" }}>
+                {this.overlayView}
+            </div>
+            :
+            (null);
         return (
             <div className="collectionfreeformview-container"
                 onPointerDown={this.onPointerDown}
@@ -214,6 +237,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
                     {this.backgroundView}
                     {this.views}
                 </div>
+                {overlay}
             </div>
         );
     }
diff --git a/src/fields/KeyStore.ts b/src/fields/KeyStore.ts
index 42e3f6b58..78ed09efd 100644
--- a/src/fields/KeyStore.ts
+++ b/src/fields/KeyStore.ts
@@ -19,6 +19,7 @@ export namespace KeyStore {
     export const ViewType = new Key("ViewType");
     export const Layout = new Key("Layout");
     export const BackgroundLayout = new Key("BackgroundLayout");
+    export const OverlayLayout = new Key("OverlayLayout");
     export const LayoutKeys = new Key("LayoutKeys");
     export const LayoutFields = new Key("LayoutFields");
     export const ColumnsKey = new Key("SchemaColumns");
-- 
cgit v1.2.3-70-g09d2


From d9d55e422826da1fe87aa7973c92e54bc0c99f02 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sat, 23 Feb 2019 11:38:15 -0500
Subject: working overlays

---
 src/client/documents/Documents.ts                        | 14 +++++++-------
 src/client/views/collections/CollectionFreeFormView.scss |  9 +++++++++
 src/client/views/collections/CollectionFreeFormView.tsx  |  6 +++---
 src/client/views/nodes/FormattedTextBox.scss             |  2 +-
 4 files changed, 20 insertions(+), 11 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 72efb45f5..4c5f26fbd 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -127,18 +127,18 @@ export namespace Documents {
     }
 
     // example of custom display string for an image that shows a caption.
-    function CaptionLayoutString() {
+    function EmbeddedCaption() {
         return `<div style="position:absolute; height:100%">
             <div style="position:relative; margin:auto; width:85%; margin:auto" >`
             + ImageBox.LayoutString() +
             `</div>
-            <div style="position:relative; min-height:15%; overflow:scroll; max-height:15%; text-align:center; ">`
+            <div style="position:relative; overflow:auto; height:15%; text-align:center; ">`
             + FormattedTextBox.LayoutString("CaptionKey") +
             `</div> 
         </div>` };
-    function OverlayLayoutString() {
-        return `<div style="position:absolute; height:100%; width:100%">
-            <div style="position:absolute; max-height:10%;  width:100%; min-height:10%; overflow:scroll;text-align:center;bottom:0;">`
+    function FixedCaption() {
+        return `<div style="position:absolute; height:30px; bottom:0; width:100%">
+            <div style="position:absolute; width:100%; height:100%; overflow:auto;text-align:center;bottom:0;">`
             + FormattedTextBox.LayoutString("CaptionKey") +
             `</div> 
         </div>` };
@@ -148,8 +148,8 @@ export namespace Documents {
         setupOptions(doc, options);
         doc.Set(KeyStore.Data, new ImageField(new URL(url)));
         doc.Set(KeyStore.Caption, new TextField("my caption..."));
-        doc.Set(KeyStore.BackgroundLayout, new TextField(CaptionLayoutString()));
-        //doc.Set(KeyStore.OverlayLayout, new TextField(OverlayLayoutString()));
+        doc.Set(KeyStore.BackgroundLayout, new TextField(EmbeddedCaption()));
+        doc.Set(KeyStore.OverlayLayout, new TextField(FixedCaption()));
         doc.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data, KeyStore.Annotations, KeyStore.Caption]));
 
         let annotation = Documents.TextDocument({ title: "hello" });
diff --git a/src/client/views/collections/CollectionFreeFormView.scss b/src/client/views/collections/CollectionFreeFormView.scss
index 6d678528a..e682b9815 100644
--- a/src/client/views/collections/CollectionFreeFormView.scss
+++ b/src/client/views/collections/CollectionFreeFormView.scss
@@ -1,4 +1,13 @@
 .collectionfreeformview-container {
+
+    ::-webkit-scrollbar {
+        -webkit-appearance: none;
+        width: 10px;
+    }
+    ::-webkit-scrollbar-thumb {
+        border-radius: 5px;
+        background-color: rgba(0,0,0,.5);
+    }
     border-style: solid;
     box-sizing: border-box;
     position: relative;
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index 85f7d5677..cb6668634 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -120,8 +120,8 @@ export class CollectionFreeFormView extends CollectionViewBase {
     private SetPan(panX: number, panY: number) {
         const newPanX = Math.max((1 - this.zoomScaling) * this.nativeWidth, Math.min(0, panX));
         const newPanY = Math.max((1 - this.zoomScaling) * this.nativeHeight, Math.min(0, panY));
-        this.props.Document.SetNumber(KeyStore.PanX, this.isAnnotationOverlay ? newPanX : panX);
-        this.props.Document.SetNumber(KeyStore.PanY, this.isAnnotationOverlay ? newPanY : panY);
+        this.props.Document.SetNumber(KeyStore.PanX, false && this.isAnnotationOverlay ? newPanX : panX);
+        this.props.Document.SetNumber(KeyStore.PanY, false && this.isAnnotationOverlay ? newPanY : panY);
     }
 
     @action
@@ -238,7 +238,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
                     {this.backgroundView}
                     {this.views}
                 </div>
-                {overlay}
+                {this.overlayView}
             </div>
         );
     }
diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss
index 872a2138b..226456fab 100644
--- a/src/client/views/nodes/FormattedTextBox.scss
+++ b/src/client/views/nodes/FormattedTextBox.scss
@@ -10,5 +10,5 @@
 
 .formattedTextBox-cont {
     background: beige;
-    padding: 1vw;
+    padding: 0;
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From e57c8ed3944bf737afdb2f564d159a53f8a6b1c6 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Mon, 25 Feb 2019 01:56:29 -0500
Subject: more css cleanup

---
 src/client/documents/Documents.ts                  |  4 +-
 src/client/views/EditableView.tsx                  |  2 +-
 .../views/collections/CollectionDockingView.tsx    |  2 +-
 .../views/collections/CollectionFreeFormView.scss  |  6 ++
 .../views/collections/CollectionFreeFormView.tsx   |  6 --
 .../views/collections/CollectionSchemaView.scss    | 73 ++++++++++------------
 .../views/collections/CollectionSchemaView.tsx     |  7 ++-
 .../views/nodes/CollectionFreeFormDocumentView.tsx |  2 +-
 src/client/views/nodes/FormattedTextBox.scss       |  4 ++
 src/client/views/nodes/FormattedTextBox.tsx        |  6 +-
 src/client/views/nodes/ImageBox.scss               |  6 +-
 11 files changed, 58 insertions(+), 60 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 4c5f26fbd..2dfff6235 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -128,8 +128,8 @@ export namespace Documents {
 
     // example of custom display string for an image that shows a caption.
     function EmbeddedCaption() {
-        return `<div style="position:absolute; height:100%">
-            <div style="position:relative; margin:auto; width:85%; margin:auto" >`
+        return `<div style="height:100%">
+            <div style="position:relative; margin:auto; height:85%;" >`
             + ImageBox.LayoutString() +
             `</div>
             <div style="position:relative; overflow:auto; height:15%; text-align:center; ">`
diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index 3d1c2ebf4..8d9a47eaa 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -30,7 +30,7 @@ export class EditableView extends React.Component<EditableProps> {
                 style={{ width: "100%" }}></input>
         } else {
             return (
-                <div style={{ alignItems: "center", display: "flex", height: "100%", maxHeight: `${this.props.height}` }}
+                <div className="editableView-container-editing" style={{ display: "flex", height: "100%", maxHeight: `${this.props.height}` }}
                     onClick={action(() => this.editing = true)}
                 >
                     {this.props.contents}
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 86dc66e39..2230ec14f 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -285,7 +285,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
         if (!this._document)
             return (null);
         var content =
-            <div ref={this._mainCont}>
+            <div className="collectionDockingView-content" ref={this._mainCont}>
                 <DocumentView key={this._document.Id} Document={this._document}
                     AddDocument={undefined}
                     RemoveDocument={undefined}
diff --git a/src/client/views/collections/CollectionFreeFormView.scss b/src/client/views/collections/CollectionFreeFormView.scss
index e682b9815..d583a8218 100644
--- a/src/client/views/collections/CollectionFreeFormView.scss
+++ b/src/client/views/collections/CollectionFreeFormView.scss
@@ -8,6 +8,12 @@
         border-radius: 5px;
         background-color: rgba(0,0,0,.5);
     }
+    
+    .collectionfreeformview > .jsx-parser{
+        position:absolute;
+        height: 100%;
+    }
+        
     border-style: solid;
     box-sizing: border-box;
     position: relative;
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index cb6668634..c40da6eaa 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -217,12 +217,6 @@ export class CollectionFreeFormView extends CollectionViewBase {
     render() {
         const panx: number = this.props.Document.GetNumber(KeyStore.PanX, 0);
         const pany: number = this.props.Document.GetNumber(KeyStore.PanY, 0);
-        var overlay = this.overlayView ?
-            <div style={{ position: "absolute", width: "100%", height: "100%" }}>
-                {this.overlayView}
-            </div>
-            :
-            (null);
         return (
             <div className="collectionfreeformview-container"
                 onPointerDown={this.onPointerDown}
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index ba9afee62..3bf84f3cd 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -14,16 +14,6 @@
         background-color: rgba(0,0,0,.5);
     }
 
-    .collectionfreeformview-container {
-        border-width: 0px;
-        .collectionfreeformview > .jsx-parser{
-            position:absolute
-        }
-    }
-    .imageBox-cont {
-        position:relative;
-        max-height:100%;
-    }
     .ReactTable {
         position: absolute;
        // display: inline-block;
@@ -32,23 +22,40 @@
         height: 100%;
         background: white;
         box-sizing: border-box;
-    }
-    .ReactTable .rt-table {
-        overflow-y: auto;
-        overflow-x: auto;
-        height: 100%;
+        .rt-table {
+            overflow-y: auto;
+            overflow-x: auto;
+            height: 100%;
 
-        display: -webkit-inline-box;
-        direction: ltr;
-        // direction:rtl;
-        // display:block;
-    }
-    .ReactTable .rt-tbody {
-        //direction: ltr;
-        direction: rtl;
-    }
-    .ReactTable .rt-tr-group {
-        direction: ltr;
+            display: -webkit-inline-box;
+            direction: ltr;
+            // direction:rtl;
+            // display:block;
+        }
+        .rt-tbody {
+            //direction: ltr;
+            direction: rtl;
+        }
+        .rt-tr-group {
+            direction: ltr;
+        }
+        .rt-td {
+            border-width: 1;
+            border-right-color: #aaa;
+            .imageBox-cont {
+                position:relative;
+                max-height:100%;
+            }
+            .imageBox-cont img {
+                object-fit: contain;
+                max-width: 100%;
+                height: 100%
+            }
+        }
+        .rt-tr-group {
+            border-width: 1;
+            border-bottom-color: #aaa
+        }
     }
     .ReactTable .rt-thead.-header {
             background:grey;
@@ -61,24 +68,10 @@
         border-bottom-style: solid;
         border-bottom-width: 1;
     }
-    .ReactTable .rt-td {
-        border-width: 1;
-        border-right-color: #aaa
-    }
-    .ReactTable .rt-tr-group {
-        border-width: 1;
-        border-bottom-color: #aaa
-    }
-    .imageBox-cont img {
-        object-fit: contain;
-        height: 100%
-    }
     .documentView-node:first-child {
         background: grey;
         .imageBox-cont img {
             object-fit: contain;
-            max-width: 100%;
-            height: 100%
         }
     }
 }
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index d2db93120..dc952ef82 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -16,6 +16,8 @@ import "./CollectionSchemaView.scss";
 import { COLLECTION_BORDER_WIDTH } from "./CollectionView";
 import { CollectionViewBase } from "./CollectionViewBase";
 
+// bcz: need to add drag and drop of rows and columns.  This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657
+
 @observer
 export class CollectionSchemaView extends CollectionViewBase {
     private _mainCont = React.createRef<HTMLDivElement>();
@@ -140,7 +142,7 @@ export class CollectionSchemaView extends CollectionViewBase {
         let content = this._selectedIndex == -1 || !selected ? (null) : (
             <Measure onResize={this.setScaling}>
                 {({ measureRef }) =>
-                    <div ref={measureRef}>
+                    <div className="collectionSchemaView-content" ref={measureRef}>
                         <DocumentView Document={selected}
                             AddDocument={this.props.addDocument} RemoveDocument={this.props.removeDocument}
                             isTopMost={false}
@@ -173,7 +175,8 @@ export class CollectionSchemaView extends CollectionViewBase {
                                 }))}
                                 column={{
                                     ...ReactTableDefaults.column,
-                                    Cell: this.renderCell
+                                    Cell: this.renderCell,
+
                                 }}
                                 getTrProps={this.getTrProps}
                             />
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 17123bf52..d7243421a 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -88,7 +88,7 @@ export class CollectionFreeFormDocumentView extends React.Component<DocumentView
 
     render() {
         return (
-            <div ref={this._mainCont} style={{
+            <div className="collectionFreeFormDocumentView-container" ref={this._mainCont} style={{
                 transformOrigin: "left top",
                 transform: this.transform,
                 width: this.width,
diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss
index 226456fab..0389a3f85 100644
--- a/src/client/views/nodes/FormattedTextBox.scss
+++ b/src/client/views/nodes/FormattedTextBox.scss
@@ -11,4 +11,8 @@
 .formattedTextBox-cont {
     background: beige;
     padding: 0;
+    overflow-y: scroll;
+    overflow-x: hidden;
+    color: initial;
+    height: 100%;
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index c0969a8c3..60ee0b5e1 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -112,12 +112,8 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
         }
     }
     render() {
+        var val = this.props.doc.Get(this.props.fieldKey);
         return (<div className="formattedTextBox-cont"
-            style={{
-                color: "initial",
-                whiteSpace: "initial",
-                height: "auto"
-            }}
             onPointerDown={this.onPointerDown}
             ref={this._ref} />)
     }
diff --git a/src/client/views/nodes/ImageBox.scss b/src/client/views/nodes/ImageBox.scss
index 5b15b3329..ea459b911 100644
--- a/src/client/views/nodes/ImageBox.scss
+++ b/src/client/views/nodes/ImageBox.scss
@@ -4,12 +4,14 @@
     position: relative;
     text-align: center;
     width: 100%;
+    height: auto;
     max-width: 100%;
     max-height: 100%
 }
+
 .imageBox-cont img {
-    max-width: 100%;
-    max-height: 100%
+    object-fit: contain;
+    height: 100%;
 }
 
 .imageBox-button {
-- 
cgit v1.2.3-70-g09d2

