From 00a4534c535281aaecf4b47da64f1a0770e3bf68 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Mon, 4 Feb 2019 18:10:27 -0500
Subject: not working

---
 src/views/collections/CollectionFreeFormView.tsx | 37 ++++++++++++------------
 1 file changed, 19 insertions(+), 18 deletions(-)

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

diff --git a/src/views/collections/CollectionFreeFormView.tsx b/src/views/collections/CollectionFreeFormView.tsx
index ab2aeee64..d0dea7a79 100644
--- a/src/views/collections/CollectionFreeFormView.tsx
+++ b/src/views/collections/CollectionFreeFormView.tsx
@@ -15,6 +15,7 @@ import { CollectionViewBase, CollectionViewProps, COLLECTION_BORDER_WIDTH } from
 
 @observer
 export class CollectionFreeFormView extends CollectionViewBase {
+    public static LayoutString() { return '<CollectionFreeFormView DocumentForCollection={Document} CollectionFieldKey={DataKey} DocumentContentsContainingCollection={ContainingDocumentContentsView}/>'; }
     private _containerRef = React.createRef<HTMLDivElement>();
     private _canvasRef = React.createRef<HTMLDivElement>();
     private _nodeContainerRef = React.createRef<HTMLDivElement>();
@@ -36,14 +37,14 @@ export class CollectionFreeFormView extends CollectionViewBase {
             const xOffset = de.data["xOffset"] as number || 0;
             const yOffset = de.data["yOffset"] as number || 0;
             const { scale, translateX, translateY } = Utils.GetScreenTransform(this._canvasRef.current!);
-            let sscale = this.props.ContainingDocumentView!.props.Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1))
+            let sscale = this.props.DocumentContentsContainingCollection!.props.Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1))
             const screenX = de.x - xOffset;
             const screenY = de.y - yOffset;
             const docX = (screenX - translateX) / sscale / scale;
             const docY = (screenY - translateY) / sscale / scale;
             doc.x = docX;
             doc.y = docY;
-            this.bringToFront(doc);
+            //this.bringToFront(doc);
         }
         e.stopPropagation();
     }
@@ -82,11 +83,11 @@ export class CollectionFreeFormView extends CollectionViewBase {
         if (!e.cancelBubble) {
             e.preventDefault();
             e.stopPropagation();
-            let currScale: number = this.props.ContainingDocumentView!.ScalingToScreenSpace;
-            let x = this.props.Document.GetFieldValue(KeyStore.PanX, NumberField, Number(0));
-            let y = this.props.Document.GetFieldValue(KeyStore.PanY, NumberField, Number(0));
-            this.props.Document.SetFieldValue(KeyStore.PanX, x + (e.pageX - this._lastX) / currScale, NumberField);
-            this.props.Document.SetFieldValue(KeyStore.PanY, y + (e.pageY - this._lastY) / currScale, NumberField);
+            let currScale: number = this.props.DocumentContentsContainingCollection!.ScalingToScreenSpace;
+            let x = this.props.DocumentForCollection.GetFieldValue(KeyStore.PanX, NumberField, Number(0));
+            let y = this.props.DocumentForCollection.GetFieldValue(KeyStore.PanY, NumberField, Number(0));
+            this.props.DocumentForCollection.SetFieldValue(KeyStore.PanX, x + (e.pageX - this._lastX) / currScale, NumberField);
+            this.props.DocumentForCollection.SetFieldValue(KeyStore.PanY, y + (e.pageY - this._lastY) / currScale, NumberField);
             this._lastX = e.pageX;
             this._lastY = e.pageY;
         }
@@ -96,7 +97,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
     onPointerWheel = (e: React.WheelEvent): void => {
         e.stopPropagation();
 
-        let { LocalX, Ss, Panxx, Xx, LocalY, Panyy, Yy, ContainerX, ContainerY } = this.props.ContainingDocumentView!.TransformToLocalPoint(e.pageX, e.pageY);
+        let { LocalX, Ss, Panxx, Xx, LocalY, Panyy, Yy, ContainerX, ContainerY } = this.props.DocumentContentsContainingCollection!.TransformToLocalPoint(e.pageX, e.pageY);
 
         var deltaScale = (1 - (e.deltaY / 1000)) * Ss;
 
@@ -106,9 +107,9 @@ export class CollectionFreeFormView extends CollectionViewBase {
         let dx = ContainerX - newContainerX;
         let dy = ContainerY - newContainerY;
 
-        this.props.Document.SetField(KeyStore.Scale, new NumberField(deltaScale));
-        this.props.Document.SetFieldValue(KeyStore.PanX, Panxx + dx, NumberField);
-        this.props.Document.SetFieldValue(KeyStore.PanY, Panyy + dy, NumberField);
+        this.props.DocumentForCollection.SetField(KeyStore.Scale, new NumberField(deltaScale));
+        this.props.DocumentForCollection.SetFieldValue(KeyStore.PanX, Panxx + dx, NumberField);
+        this.props.DocumentForCollection.SetFieldValue(KeyStore.PanY, Panyy + dy, NumberField);
     }
 
     @action
@@ -118,8 +119,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.Document.GetFieldValue(KeyStore.PanX, NumberField, Number(0));
-        const pany: number = this.props.Document.GetFieldValue(KeyStore.PanY, NumberField, Number(0));
+        const panx: number = this.props.DocumentForCollection.GetFieldValue(KeyStore.PanX, NumberField, Number(0));
+        const pany: number = this.props.DocumentForCollection.GetFieldValue(KeyStore.PanY, NumberField, Number(0));
         let x = e.pageX - panx
         let y = e.pageY - pany
 
@@ -129,10 +130,10 @@ export class CollectionFreeFormView extends CollectionViewBase {
                 let doc = Documents.ImageDocument(url, {
                     x: x, y: y
                 })
-                let docs = that.props.Document.GetFieldT(KeyStore.Data, ListField);
+                let docs = that.props.DocumentForCollection.GetFieldT(KeyStore.Data, ListField);
                 if (!docs) {
                     docs = new ListField<Document>();
-                    that.props.Document.SetField(KeyStore.Data, docs)
+                    that.props.DocumentForCollection.SetField(KeyStore.Data, docs)
                 }
                 docs.Data.push(doc);
             }
@@ -148,7 +149,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
 
     @action
     bringToFront(doc: DocumentView) {
-        const { fieldKey, Document: Document } = this.props;
+        const { CollectionFieldKey: fieldKey, DocumentForCollection: Document } = this.props;
 
         const value: Document[] = Document.GetListField<Document>(fieldKey, []);
         var topmost = value.reduce((topmost, d) => Math.max(d.GetNumberField(KeyStore.ZIndex, 0), topmost), -1000);
@@ -165,7 +166,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
     }
 
     render() {
-        const { fieldKey, Document: Document } = this.props;
+        const { CollectionFieldKey: fieldKey, DocumentForCollection: Document } = this.props;
         const value: Document[] = Document.GetListField<Document>(fieldKey, []);
         const panx: number = Document.GetNumberField(KeyStore.PanX, 0);
         const pany: number = Document.GetNumberField(KeyStore.PanY, 0);
@@ -186,7 +187,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
 
                         <div className="node-container" ref={this._nodeContainerRef}>
                             {value.map(doc => {
-                                return (<DocumentView key={doc.Id} ContainingCollectionView={this} Document={doc} ContainingDocumentView={this.props.ContainingDocumentView} />);
+                                return (<DocumentView key={doc.Id} ContainingCollectionView={this} Document={doc} ContainingDocumentContentsView={this.props.DocumentContentsContainingCollection} />);
                             })}
                         </div>
                     </div>
-- 
cgit v1.2.3-70-g09d2


From 58c7742c18f82fe854784b083dfa723a8f256b72 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 5 Feb 2019 11:22:10 -0500
Subject: lots of reorganization

---
 src/Main.tsx                                       |  14 +-
 src/util/DragManager.ts                            |   2 +-
 src/util/SelectionManager.ts                       |  12 +-
 src/views/collections/CollectionDockingView.tsx    |  12 +-
 src/views/collections/CollectionFreeFormView.tsx   |  37 +--
 src/views/collections/CollectionSchemaView.tsx     |  12 +-
 src/views/nodes/CollectionFreeFormDocumentView.tsx | 222 ++++++++++++++++++
 src/views/nodes/DocumentView.tsx                   | 257 ++-------------------
 src/views/nodes/FieldTextBox.tsx                   |   6 +-
 src/views/nodes/FieldView.tsx                      |   4 +-
 src/views/nodes/ImageBox.tsx                       |   8 +-
 11 files changed, 306 insertions(+), 280 deletions(-)
 create mode 100644 src/views/nodes/CollectionFreeFormDocumentView.tsx

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

diff --git a/src/Main.tsx b/src/Main.tsx
index cbdf0ae98..7618630f8 100644
--- a/src/Main.tsx
+++ b/src/Main.tsx
@@ -11,7 +11,7 @@ import { NumberField } from './fields/NumberField';
 import { TextField } from './fields/TextField';
 import "./Main.scss";
 import { ContextMenu } from './views/ContextMenu';
-import { DocumentView, DocumentContentsView } from './views/nodes/DocumentView';
+import { DocumentView } from './views/nodes/DocumentView';
 
 configure({
     enforceActions: "observed"
@@ -51,14 +51,14 @@ document.addEventListener("pointerdown", action(function (e: PointerEvent) {
     schemaDocs[4].SetFieldValue(KS.Author, "Bob", TextField);
     schemaDocs.push(doc2);
     const doc7 = Documents.SchemaDocument(schemaDocs)
-    const docset = [doc3];//[doc1, doc2, doc3, doc7];
+    const docset = [doc1, doc2, doc3, doc7];
     let doc4 = Documents.CollectionDocument(docset, {
         x: 0, y: 400, title: "mini collection"
     });
     let doc5 = Documents.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", {
         x: 650, y: 500, width: 600, height: 600, title: "cat 2"
     });
-    let docset2 = new Array<Document>(doc4, doc1, doc3);
+    let docset2 = new Array<Document>(doc4);//, doc1, doc3);
     let doc6 = Documents.CollectionDocument(docset2, {
         x: 350, y: 100, width: 600, height: 600, title: "docking collection"
     });
@@ -66,21 +66,21 @@ document.addEventListener("pointerdown", action(function (e: PointerEvent) {
     if (!mainNodes) {
         mainNodes = new ListField<Document>();
     }
-    // mainNodes.Data.push(doc1);
+    mainNodes.Data.push(doc1);
     // mainNodes.Data.push(doc2);
     mainNodes.Data.push(doc4);
     // mainNodes.Data.push(doc3);
-    //mainNodes.Data.push(doc5);
+    // mainNodes.Data.push(doc5);
     // mainNodes.Data.push(doc1);
     //mainNodes.Data.push(doc2);
-    //mainNodes.Data.push(doc6);
+    mainNodes.Data.push(doc7);
     mainContainer.SetField(KeyStore.Data, mainNodes);
 }
 //);
 
 ReactDOM.render((
     <div style={{ position: "absolute", width: "100%", height: "100%" }}>
-        <DocumentContentsView Document={mainContainer} ContainingCollectionView={undefined} ContainingDocumentContentsView={undefined} />
+        <DocumentView Document={mainContainer} ContainingCollectionView={undefined} DocumentContentsView={undefined} />
         <DocumentDecorations />
         <ContextMenu />
     </div>),
diff --git a/src/util/DragManager.ts b/src/util/DragManager.ts
index b4132a222..63d6a88f8 100644
--- a/src/util/DragManager.ts
+++ b/src/util/DragManager.ts
@@ -1,5 +1,5 @@
 import { Opt } from "../fields/Field";
-import { DocumentView } from "../views/nodes/DocumentView";
+import { CollectionFreeFormDocumentView } from "../views/nodes/CollectionFreeFormDocumentView";
 import { DocumentDecorations } from "../DocumentDecorations";
 import { SelectionManager } from "./SelectionManager";
 import { CollectionDockingView } from "../views/collections/CollectionDockingView";
diff --git a/src/util/SelectionManager.ts b/src/util/SelectionManager.ts
index 2a63248c4..0759ae110 100644
--- a/src/util/SelectionManager.ts
+++ b/src/util/SelectionManager.ts
@@ -1,13 +1,13 @@
-import { DocumentView } from "../views/nodes/DocumentView";
+import { CollectionFreeFormDocumentView } from "../views/nodes/CollectionFreeFormDocumentView";
 import { observable, action } from "mobx";
 
 export namespace SelectionManager {
     class Manager {
         @observable
-        SelectedDocuments: Array<DocumentView> = [];
+        SelectedDocuments: Array<CollectionFreeFormDocumentView> = [];
 
         @action
-        SelectDoc(doc: DocumentView, ctrlPressed: boolean): void {
+        SelectDoc(doc: CollectionFreeFormDocumentView, ctrlPressed: boolean): void {
             // if doc is not in SelectedDocuments, add it
             if (!ctrlPressed) {
                 manager.SelectedDocuments = [];
@@ -21,11 +21,11 @@ export namespace SelectionManager {
 
     const manager = new Manager;
 
-    export function SelectDoc(doc: DocumentView, ctrlPressed: boolean): void {
+    export function SelectDoc(doc: CollectionFreeFormDocumentView, ctrlPressed: boolean): void {
         manager.SelectDoc(doc, ctrlPressed)
     }
 
-    export function IsSelected(doc: DocumentView): boolean {
+    export function IsSelected(doc: CollectionFreeFormDocumentView): boolean {
         return manager.SelectedDocuments.indexOf(doc) !== -1;
     }
 
@@ -33,7 +33,7 @@ export namespace SelectionManager {
         manager.SelectedDocuments = []
     }
 
-    export function SelectedDocuments(): Array<DocumentView> {
+    export function SelectedDocuments(): Array<CollectionFreeFormDocumentView> {
         return manager.SelectedDocuments;
     }
 }
\ No newline at end of file
diff --git a/src/views/collections/CollectionDockingView.tsx b/src/views/collections/CollectionDockingView.tsx
index 197b7df46..1a523e1bf 100644
--- a/src/views/collections/CollectionDockingView.tsx
+++ b/src/views/collections/CollectionDockingView.tsx
@@ -4,7 +4,7 @@ import React = require("react");
 import FlexLayout from "flexlayout-react";
 import { action, observable, computed } from "mobx";
 import { Document } from "../../fields/Document";
-import { DocumentView, DocumentContentsView } from "../nodes/DocumentView";
+import { DocumentView } from "../nodes/DocumentView";
 import { ListField } from "../../fields/ListField";
 import { NumberField } from "../../fields/NumberField";
 import { SSL_OP_SINGLE_DH_USE } from "constants";
@@ -20,7 +20,7 @@ import { CollectionViewBase, CollectionViewProps, COLLECTION_BORDER_WIDTH } from
 export class CollectionDockingView extends CollectionViewBase {
 
     private static UseGoldenLayout = true;
-    public static LayoutString() { return '<CollectionDockingView DocumentForCollection={Document} CollectionFieldKey={DataKey} DocumentContentsContainingCollection={ContainingDocumentContentsView}/>'; }
+    public static LayoutString() { return CollectionViewBase.LayoutString("CollectionDockingView"); }
     private _containerRef = React.createRef<HTMLDivElement>();
     @computed
     private get modelForFlexLayout() {
@@ -69,7 +69,7 @@ export class CollectionDockingView extends CollectionViewBase {
 
     @action
     onResize = (event: any) => {
-        var cur = this.props.DocumentContentsContainingCollection!.MainContent.current;
+        var cur = this.props.DocumentContentsOfCollection!.MainContent.current;
 
         // bcz: since GoldenLayout isn't a React component itself, we need to notify it to resize when its document container's size has changed
         CollectionDockingView.myLayout.updateSize(cur!.getBoundingClientRect().width, cur!.getBoundingClientRect().height);
@@ -96,7 +96,7 @@ export class CollectionDockingView extends CollectionViewBase {
         const value: Document[] = Document.GetFieldValue(fieldKey, ListField, []);
         for (var i: number = 0; i < value.length; i++) {
             if (value[i].Id === component) {
-                return (<DocumentView key={value[i].Id} ContainingCollectionView={this} Document={value[i]} ContainingDocumentContentsView={this.props.DocumentContentsContainingCollection} />);
+                return (<DocumentView key={value[i].Id} ContainingCollectionView={this} Document={value[i]} DocumentContentsView={undefined} />);
             }
         }
         if (component === "text") {
@@ -237,7 +237,7 @@ export class CollectionDockingView extends CollectionViewBase {
             container.getElement().html("<div id='" + containingDiv + "'></div>");
             setTimeout(function () {
                 ReactDOM.render((
-                    <DocumentContentsView key={state.doc.Id} Document={state.doc} ContainingCollectionView={me} ContainingDocumentContentsView={me.props.DocumentContentsContainingCollection} /> // bcz: need to fill in containingdoccontnents with value of DocumentContents when created...
+                    <DocumentView key={state.doc.Id} Document={state.doc} ContainingCollectionView={me} DocumentContentsView={undefined} /> // bcz: need to fill in DocumentContentsView with value of DocumentContents when created...
                 ),
                     document.getElementById(containingDiv)
                 );
@@ -255,7 +255,7 @@ export class CollectionDockingView extends CollectionViewBase {
         const { CollectionFieldKey: fieldKey, DocumentForCollection: Document } = this.props;
         const value: Document[] = Document.GetFieldValue(fieldKey, ListField, []);
         // bcz: not sure why, but I need these to force the flexlayout to update when the collection size changes.
-        var s = this.props.DocumentContentsContainingCollection != undefined ? this.props.DocumentContentsContainingCollection!.ScalingToScreenSpace : 1;
+        var s = this.props.DocumentContentsOfCollection != undefined ? this.props.DocumentContentsOfCollection!.ScalingToScreenSpace : 1;
         var w = Document.GetFieldValue(KeyStore.Width, NumberField, Number(0)) / s;
         var h = Document.GetFieldValue(KeyStore.Height, NumberField, Number(0)) / s;
 
diff --git a/src/views/collections/CollectionFreeFormView.tsx b/src/views/collections/CollectionFreeFormView.tsx
index d0dea7a79..c91946475 100644
--- a/src/views/collections/CollectionFreeFormView.tsx
+++ b/src/views/collections/CollectionFreeFormView.tsx
@@ -3,7 +3,7 @@ import { Key, KeyStore } from "../../fields/Key";
 import React = require("react");
 import { action, observable, computed } from "mobx";
 import { Document } from "../../fields/Document";
-import { DocumentView } from "../nodes/DocumentView";
+import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView";
 import { ListField } from "../../fields/ListField";
 import { NumberField } from "../../fields/NumberField";
 import { SSL_OP_SINGLE_DH_USE } from "constants";
@@ -12,10 +12,11 @@ import { DragManager } from "../../util/DragManager";
 import "./CollectionFreeFormView.scss";
 import { Utils } from "../../Utils";
 import { CollectionViewBase, CollectionViewProps, COLLECTION_BORDER_WIDTH } from "./CollectionViewBase";
+import { SelectionManager } from "../../util/SelectionManager";
 
 @observer
 export class CollectionFreeFormView extends CollectionViewBase {
-    public static LayoutString() { return '<CollectionFreeFormView DocumentForCollection={Document} CollectionFieldKey={DataKey} DocumentContentsContainingCollection={ContainingDocumentContentsView}/>'; }
+    public static LayoutString() { return CollectionViewBase.LayoutString("CollectionFreeFormView"); }
     private _containerRef = React.createRef<HTMLDivElement>();
     private _canvasRef = React.createRef<HTMLDivElement>();
     private _nodeContainerRef = React.createRef<HTMLDivElement>();
@@ -29,7 +30,8 @@ export class CollectionFreeFormView extends CollectionViewBase {
     @action
     drop = (e: Event, de: DragManager.DropEvent) => {
         const doc = de.data["document"];
-        if (doc instanceof DocumentView) {
+        var me = this;
+        if (doc instanceof CollectionFreeFormDocumentView) {
             if (doc.props.ContainingCollectionView && doc.props.ContainingCollectionView !== this) {
                 doc.props.ContainingCollectionView.removeDocument(doc.props.Document);
                 this.addDocument(doc.props.Document);
@@ -37,14 +39,14 @@ export class CollectionFreeFormView extends CollectionViewBase {
             const xOffset = de.data["xOffset"] as number || 0;
             const yOffset = de.data["yOffset"] as number || 0;
             const { scale, translateX, translateY } = Utils.GetScreenTransform(this._canvasRef.current!);
-            let sscale = this.props.DocumentContentsContainingCollection!.props.Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1))
+            let sscale = this.props.DocumentContentsOfCollection!.props.Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1))
             const screenX = de.x - xOffset;
             const screenY = de.y - yOffset;
             const docX = (screenX - translateX) / sscale / scale;
             const docY = (screenY - translateY) / sscale / scale;
             doc.x = docX;
             doc.y = docY;
-            //this.bringToFront(doc);
+            this.bringToFront(doc);
         }
         e.stopPropagation();
     }
@@ -59,9 +61,14 @@ export class CollectionFreeFormView extends CollectionViewBase {
         }
     }
 
+    downactive: boolean = false;
     @action
     onPointerDown = (e: React.PointerEvent): void => {
-        if (e.button === 2 && this.active) {
+        var me = this;
+        me.downactive = this.active;
+        var title = this.props.DocumentForCollection.Title;
+        if ((e.button === 2 && this.active) ||
+            !e.defaultPrevented) {
             document.removeEventListener("pointermove", this.onPointerMove);
             document.addEventListener("pointermove", this.onPointerMove);
             document.removeEventListener("pointerup", this.onPointerUp);
@@ -76,28 +83,32 @@ export class CollectionFreeFormView extends CollectionViewBase {
         document.removeEventListener("pointermove", this.onPointerMove);
         document.removeEventListener("pointerup", this.onPointerUp);
         e.stopPropagation();
+        SelectionManager.DeselectAll();
     }
 
     @action
     onPointerMove = (e: PointerEvent): void => {
-        if (!e.cancelBubble) {
+        var me = this;
+        var act = me.active;
+        var title = me.props.DocumentForCollection.Title;
+        if (!e.cancelBubble && this.active) {
             e.preventDefault();
             e.stopPropagation();
-            let currScale: number = this.props.DocumentContentsContainingCollection!.ScalingToScreenSpace;
+            let currScale: number = this.props.DocumentContentsOfCollection!.ScalingToScreenSpace;
             let x = this.props.DocumentForCollection.GetFieldValue(KeyStore.PanX, NumberField, Number(0));
             let y = this.props.DocumentForCollection.GetFieldValue(KeyStore.PanY, NumberField, Number(0));
             this.props.DocumentForCollection.SetFieldValue(KeyStore.PanX, x + (e.pageX - this._lastX) / currScale, NumberField);
             this.props.DocumentForCollection.SetFieldValue(KeyStore.PanY, y + (e.pageY - this._lastY) / currScale, NumberField);
-            this._lastX = e.pageX;
-            this._lastY = e.pageY;
         }
+        this._lastX = e.pageX;
+        this._lastY = e.pageY;
     }
 
     @action
     onPointerWheel = (e: React.WheelEvent): void => {
         e.stopPropagation();
 
-        let { LocalX, Ss, Panxx, Xx, LocalY, Panyy, Yy, ContainerX, ContainerY } = this.props.DocumentContentsContainingCollection!.TransformToLocalPoint(e.pageX, e.pageY);
+        let { LocalX, Ss, Panxx, Xx, LocalY, Panyy, Yy, ContainerX, ContainerY } = this.props.DocumentContentsOfCollection!.TransformToLocalPoint(e.pageX, e.pageY);
 
         var deltaScale = (1 - (e.deltaY / 1000)) * Ss;
 
@@ -148,7 +159,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
     }
 
     @action
-    bringToFront(doc: DocumentView) {
+    bringToFront(doc: CollectionFreeFormDocumentView) {
         const { CollectionFieldKey: fieldKey, DocumentForCollection: Document } = this.props;
 
         const value: Document[] = Document.GetListField<Document>(fieldKey, []);
@@ -187,7 +198,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
 
                         <div className="node-container" ref={this._nodeContainerRef}>
                             {value.map(doc => {
-                                return (<DocumentView key={doc.Id} ContainingCollectionView={this} Document={doc} ContainingDocumentContentsView={this.props.DocumentContentsContainingCollection} />);
+                                return (<CollectionFreeFormDocumentView key={doc.Id} ContainingCollectionView={this} Document={doc} DocumentContentsView={this.props.DocumentContentsOfCollection} />);
                             })}
                         </div>
                     </div>
diff --git a/src/views/collections/CollectionSchemaView.tsx b/src/views/collections/CollectionSchemaView.tsx
index f625b39c5..8c79c9189 100644
--- a/src/views/collections/CollectionSchemaView.tsx
+++ b/src/views/collections/CollectionSchemaView.tsx
@@ -1,4 +1,3 @@
-import { DocumentContentsView } from "../nodes/DocumentView";
 import React = require("react")
 import ReactTable, { ReactTableDefaults, CellInfo, ComponentPropsGetterRC, ComponentPropsGetterR } from "react-table";
 import { observer } from "mobx-react";
@@ -11,22 +10,23 @@ import SplitPane from "react-split-pane"
 import "./CollectionSchemaView.scss"
 import { ScrollBox } from "../../util/ScrollBox";
 import { CollectionViewBase } from "./CollectionViewBase";
+import { DocumentView } from "../nodes/DocumentView";
 
 @observer
 export class CollectionSchemaView extends CollectionViewBase {
-    public static LayoutString() { return '<CollectionSchemaView DocumentForCollection={Document} CollectionFieldKey={DataKey} ContainingDocumentView={ContainingDocumentContentsView}/>'; }
+    public static LayoutString() { return CollectionViewBase.LayoutString("CollectionSchemaView"); }
 
     @observable
     selectedIndex = 0;
 
     renderCell = (rowProps: CellInfo) => {
-        if (!this.props.DocumentContentsContainingCollection) {
+        if (!this.props.DocumentContentsOfCollection) {
             return <div></div>
         }
         let props: FieldViewProps = {
             doc: rowProps.value[0],
             fieldKey: rowProps.value[1],
-            documentViewContainer: this.props.DocumentContentsContainingCollection
+            documentViewContainer: this.props.DocumentContentsOfCollection
         }
         return (
             <FieldView {...props} />
@@ -77,8 +77,8 @@ export class CollectionSchemaView extends CollectionViewBase {
             [KS.Title, KS.Data, KS.Author])
         let content;
         if (this.selectedIndex != -1) {
-            content = (<DocumentContentsView Document={children[this.selectedIndex]}
-                ContainingDocumentContentsView={this.props.DocumentContentsContainingCollection}
+            content = (<DocumentView Document={children[this.selectedIndex]}
+                DocumentContentsView={this.props.DocumentContentsOfCollection}
                 ContainingCollectionView={this} />)
         } else {
             content = <div />
diff --git a/src/views/nodes/CollectionFreeFormDocumentView.tsx b/src/views/nodes/CollectionFreeFormDocumentView.tsx
new file mode 100644
index 000000000..78e3325ab
--- /dev/null
+++ b/src/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -0,0 +1,222 @@
+import { action, computed } from "mobx";
+import { observer } from "mobx-react";
+import { Key, KeyStore } from "../../fields/Key";
+import { NumberField } from "../../fields/NumberField";
+import { DragManager } from "../../util/DragManager";
+import { SelectionManager } from "../../util/SelectionManager";
+import { CollectionDockingView } from "../collections/CollectionDockingView";
+import { CollectionFreeFormView } from "../collections/CollectionFreeFormView";
+import { ContextMenu } from "../ContextMenu";
+import "./NodeView.scss";
+import React = require("react");
+import { DocumentView, DocumentViewProps } from "./DocumentView";
+
+
+@observer
+export class CollectionFreeFormDocumentView extends DocumentView {
+    private _contextMenuCanOpen = false;
+    private _downX: number = 0;
+    private _downY: number = 0;
+
+    constructor(props: DocumentViewProps) {
+        super(props);
+    }
+    get screenRect(): ClientRect | DOMRect {
+        if (this._mainCont.current) {
+            return this._mainCont.current.getBoundingClientRect();
+        }
+        return new DOMRect();
+    }
+
+    @computed
+    get x(): number {
+        return this.props.Document.GetFieldValue(KeyStore.X, NumberField, Number(0));
+    }
+
+    @computed
+    get y(): number {
+        return this.props.Document.GetFieldValue(KeyStore.Y, NumberField, Number(0));
+    }
+
+    set x(x: number) {
+        this.props.Document.SetFieldValue(KeyStore.X, x, NumberField)
+    }
+
+    set y(y: number) {
+        this.props.Document.SetFieldValue(KeyStore.Y, y, NumberField)
+    }
+
+    @computed
+    get transform(): string {
+        return `translate(${this.x}px, ${this.y}px)`;
+    }
+
+    @computed
+    get width(): number {
+        return this.props.Document.GetFieldValue(KeyStore.Width, NumberField, Number(0));
+    }
+
+    set width(w: number) {
+        this.props.Document.SetFieldValue(KeyStore.Width, w, NumberField)
+    }
+
+    @computed
+    get height(): number {
+        return this.props.Document.GetFieldValue(KeyStore.Height, NumberField, Number(0));
+    }
+
+    set height(h: number) {
+        this.props.Document.SetFieldValue(KeyStore.Height, h, NumberField)
+    }
+
+    @computed
+    get zIndex(): number {
+        return this.props.Document.GetFieldValue(KeyStore.ZIndex, NumberField, Number(0));
+    }
+
+    set zIndex(h: number) {
+        this.props.Document.SetFieldValue(KeyStore.ZIndex, h, NumberField)
+    }
+
+    @action
+    dragComplete = (e: DragManager.DragCompleteEvent) => {
+    }
+
+    @computed
+    get active(): boolean {
+        return SelectionManager.IsSelected(this) || this.props.ContainingCollectionView === undefined || this.props.ContainingCollectionView!.active;
+    }
+
+    @computed
+    get topMost(): boolean {
+        return this.props.ContainingCollectionView == undefined || this.props.ContainingCollectionView instanceof CollectionDockingView;
+    }
+
+    onPointerDown = (e: React.PointerEvent): void => {
+        this._downX = e.clientX;
+        this._downY = e.clientY;
+        var me = this;
+        if (e.shiftKey && e.buttons === 1) {
+            CollectionDockingView.StartOtherDrag(this._mainCont.current!, this.props.Document);
+            e.stopPropagation();
+            return;
+        }
+        this._contextMenuCanOpen = e.button == 2;
+        if (this.active && !e.isDefaultPrevented()) {
+            e.stopPropagation();
+            if (e.buttons === 2) {
+                e.preventDefault();
+            }
+            document.removeEventListener("pointermove", this.onPointerMove)
+            document.addEventListener("pointermove", this.onPointerMove);
+            document.removeEventListener("pointerup", this.onPointerUp)
+            document.addEventListener("pointerup", this.onPointerUp);
+        }
+    }
+
+    onPointerMove = (e: PointerEvent): void => {
+        if (e.cancelBubble) {
+            this._contextMenuCanOpen = false;
+            return;
+        }
+        if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) {
+            this._contextMenuCanOpen = false;
+            if (this._mainCont.current != null && !this.topMost) {
+                this._contextMenuCanOpen = false;
+                const rect = this.screenRect;
+                let dragData: { [id: string]: any } = {};
+                dragData["document"] = this;
+                dragData["xOffset"] = e.x - rect.left;
+                dragData["yOffset"] = e.y - rect.top;
+                DragManager.StartDrag(this._mainCont.current, dragData, {
+                    handlers: {
+                        dragComplete: this.dragComplete,
+                    },
+                    hideSource: true
+                })
+            }
+        }
+        e.stopPropagation();
+        e.preventDefault();
+    }
+
+    onPointerUp = (e: PointerEvent): void => {
+        document.removeEventListener("pointermove", this.onPointerMove)
+        document.removeEventListener("pointerup", this.onPointerUp)
+        e.stopPropagation();
+        if (Math.abs(e.clientX - this._downX) < 4 && Math.abs(e.clientY - this._downY) < 4) {
+            SelectionManager.SelectDoc(this, e.ctrlKey);
+        }
+    }
+
+    openRight = (e: React.MouseEvent): void => {
+        CollectionDockingView.AddRightSplit(this.props.Document);
+    }
+
+    deleteClicked = (e: React.MouseEvent): void => {
+        if (this.props.ContainingCollectionView instanceof CollectionFreeFormView) {
+            this.props.ContainingCollectionView.removeDocument(this.props.Document)
+        }
+    }
+    @action
+    fullScreenClicked = (e: React.MouseEvent): void => {
+        CollectionDockingView.OpenFullScreen(this.props.Document);
+        ContextMenu.Instance.clearItems();
+        ContextMenu.Instance.addItem({ description: "Close Full Screen", event: this.closeFullScreenClicked });
+        ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15)
+    }
+    @action
+    closeFullScreenClicked = (e: React.MouseEvent): void => {
+        CollectionDockingView.CloseFullScreen();
+        ContextMenu.Instance.clearItems();
+        ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked })
+        ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15)
+    }
+
+    @action
+    onContextMenu = (e: React.MouseEvent): void => {
+        if (!SelectionManager.IsSelected(this)) {
+            return;
+        }
+        e.preventDefault()
+
+        if (!this._contextMenuCanOpen) {
+            return;
+        }
+
+        if (this.topMost) {
+            ContextMenu.Instance.clearItems()
+            ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked })
+            ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15)
+        }
+        else {
+            // DocumentViews should stop propogation of this event
+            e.stopPropagation();
+
+            ContextMenu.Instance.clearItems();
+            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.displayMenu(e.pageX - 15, e.pageY - 15)
+            SelectionManager.SelectDoc(this, e.ctrlKey);
+        }
+    }
+
+    render() {
+        var freestyling = this.props.ContainingCollectionView instanceof CollectionFreeFormView;
+        return (
+            <div className="node" ref={this._mainCont} style={{
+                transform: freestyling ? this.transform : "",
+                width: freestyling ? this.width : "100%",
+                height: freestyling ? this.height : "100%",
+                position: freestyling ? "absolute" : "relative",
+                zIndex: freestyling ? this.zIndex : 0,
+            }}
+                onContextMenu={this.onContextMenu}
+                onPointerDown={this.onPointerDown}>
+
+                <DocumentView {...this.props} DocumentContentsView={this} />
+            </div>
+        );
+    }
+}
\ No newline at end of file
diff --git a/src/views/nodes/DocumentView.tsx b/src/views/nodes/DocumentView.tsx
index 3cc0f3bf6..fd5ffeb61 100644
--- a/src/views/nodes/DocumentView.tsx
+++ b/src/views/nodes/DocumentView.tsx
@@ -6,28 +6,24 @@ import { Key, KeyStore } from "../../fields/Key";
 import { ListField } from "../../fields/ListField";
 import { NumberField } from "../../fields/NumberField";
 import { TextField } from "../../fields/TextField";
-import { DragManager } from "../../util/DragManager";
-import { SelectionManager } from "../../util/SelectionManager";
 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 { ContextMenu } from "../ContextMenu";
 import { FieldTextBox } from "../nodes/FieldTextBox";
 import { ImageBox } from "../nodes/ImageBox";
 import "./NodeView.scss";
 import React = require("react");
-import { baseKeymap } from "prosemirror-commands";
 const JsxParser = require('react-jsx-parser').default;//TODO Why does this need to be imported like this?
 
-interface DocumentViewProps {
+export interface DocumentViewProps {
     Document: Document;
     ContainingCollectionView: Opt<CollectionViewBase>;
-    ContainingDocumentContentsView: Opt<DocumentContentsView>;
+    DocumentContentsView: Opt<DocumentView>
 }
 @observer
-export class DocumentContentsView extends React.Component<DocumentViewProps> {
+export class DocumentView extends React.Component<DocumentViewProps> {
 
     protected _mainCont = React.createRef<any>();
     get MainContent() {
@@ -53,9 +49,9 @@ export class DocumentContentsView extends React.Component<DocumentViewProps> {
     //
     @computed
     public get ScalingToScreenSpace(): number {
-        if (this.props.ContainingDocumentContentsView != undefined) {
-            let ss = this.props.ContainingDocumentContentsView.props.Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1));
-            return this.props.ContainingDocumentContentsView.ScalingToScreenSpace * ss;
+        if (this.props.ContainingCollectionView != undefined && this.props.ContainingCollectionView.props.DocumentContentsOfCollection != undefined) {
+            let ss = this.props.ContainingCollectionView.props.DocumentForCollection.GetFieldValue(KeyStore.Scale, NumberField, Number(1));
+            return this.props.ContainingCollectionView.props.DocumentContentsOfCollection.ScalingToScreenSpace * ss;
         }
         return 1;
     }
@@ -66,8 +62,8 @@ export class DocumentContentsView extends React.Component<DocumentViewProps> {
     public TransformToLocalPoint(screenX: number, screenY: number) {
         // if this collection view is nested within another collection view, then 
         // first transform the screen point into the parent collection's coordinate space.
-        let { LocalX: parentX, LocalY: parentY } = this.props.ContainingDocumentContentsView != undefined ?
-            this.props.ContainingDocumentContentsView!.TransformToLocalPoint(screenX, screenY) :
+        let { LocalX: parentX, LocalY: parentY } = this.props.ContainingCollectionView != undefined && this.props.ContainingCollectionView.props.DocumentContentsOfCollection != undefined ?
+            this.props.ContainingCollectionView.props.DocumentContentsOfCollection.TransformToLocalPoint(screenX, screenY) :
             { LocalX: screenX, LocalY: screenY };
         let ContainerX: number = parentX - COLLECTION_BORDER_WIDTH;
         let ContainerY: number = parentY - COLLECTION_BORDER_WIDTH;
@@ -115,7 +111,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps> {
 
         // if this collection view is nested within another collection view, then 
         // first transform the local point into the parent collection's coordinate space.
-        let containingDocView = this.props.ContainingDocumentContentsView;
+        let containingDocView = this.props.ContainingCollectionView != undefined ? this.props.ContainingCollectionView.props.DocumentContentsOfCollection : undefined;//.ContainingDocumentContentsView;
         if (containingDocView != undefined) {
             let ss = containingDocView.props.Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1));
             let panxx = containingDocView.props.Document.GetFieldValue(KeyStore.PanX, NumberField, Number(0)) + COLLECTION_BORDER_WIDTH * ss;
@@ -126,238 +122,35 @@ export class DocumentContentsView extends React.Component<DocumentViewProps> {
         }
         return { ScreenX: parentX, ScreenY: parentY };
     }
+
+
     render() {
         let doc = this.props.Document;
         let bindings = { ...this.props } as any;
         for (const key of this.layoutKeys) {
             bindings[key.Name + "Key"] = key;
         }
-        bindings.ContainingDocumentContentsView = this;
+        if (this.props.DocumentContentsView == undefined)
+            bindings.DocumentContentsView = this;
         for (const key of this.layoutFields) {
             let field = doc.GetField(key);
             if (field) {
                 bindings[key.Name] = field.GetValue();
             }
         }
-        return (
-            //<div ref={this._mainCont}>
-            <JsxParser ref={this._mainCont}
-                components={{ FieldTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView }}
-                bindings={bindings}
-                jsx={this.layout}
-                showWarnings={true}
-                onError={(test: any) => { console.log(test) }}
-            />
-            //</div>
-        )
-    }
-}
-
-@observer
-export class DocumentView extends DocumentContentsView {
-    private _contextMenuCanOpen = false;
-    private _downX: number = 0;
-    private _downY: number = 0;
-
-    constructor(props: DocumentViewProps) {
-        super(props);
-    }
-    get screenRect(): ClientRect | DOMRect {
-        if (this._mainCont.current) {
-            return this._mainCont.current.getBoundingClientRect();
-        }
-        return new DOMRect();
-    }
-
-    @computed
-    get x(): number {
-        return this.props.Document.GetFieldValue(KeyStore.X, NumberField, Number(0));
-    }
-
-    @computed
-    get y(): number {
-        return this.props.Document.GetFieldValue(KeyStore.Y, NumberField, Number(0));
-    }
-
-    set x(x: number) {
-        this.props.Document.SetFieldValue(KeyStore.X, x, NumberField)
-    }
-
-    set y(y: number) {
-        this.props.Document.SetFieldValue(KeyStore.Y, y, NumberField)
-    }
-
-    @computed
-    get transform(): string {
-        return `translate(${this.x}px, ${this.y}px)`;
-    }
-
-    @computed
-    get width(): number {
-        return this.props.Document.GetFieldValue(KeyStore.Width, NumberField, Number(0));
-    }
-
-    set width(w: number) {
-        this.props.Document.SetFieldValue(KeyStore.Width, w, NumberField)
-    }
-
-    @computed
-    get height(): number {
-        return this.props.Document.GetFieldValue(KeyStore.Height, NumberField, Number(0));
-    }
-
-    set height(h: number) {
-        this.props.Document.SetFieldValue(KeyStore.Height, h, NumberField)
-    }
-
-    @computed
-    get zIndex(): number {
-        return this.props.Document.GetFieldValue(KeyStore.ZIndex, NumberField, Number(0));
-    }
-
-    set zIndex(h: number) {
-        this.props.Document.SetFieldValue(KeyStore.ZIndex, h, NumberField)
-    }
-
-    @action
-    dragComplete = (e: DragManager.DragCompleteEvent) => {
-    }
-
-    @computed
-    get active(): boolean {
-        return SelectionManager.IsSelected(this) || this.props.ContainingCollectionView === undefined || this.props.ContainingCollectionView!.active;
-    }
-
-    @computed
-    get topMost(): boolean {
-        return this.props.ContainingCollectionView == undefined || this.props.ContainingCollectionView instanceof CollectionDockingView;
-    }
-
-    onPointerDown = (e: React.PointerEvent): void => {
-        this._downX = e.clientX;
-        this._downY = e.clientY;
-        var me = this;
-        if (e.shiftKey && e.buttons === 1) {
-            CollectionDockingView.StartOtherDrag(this._mainCont.current!, this.props.Document);
-            e.stopPropagation();
-            return;
-        }
-        this._contextMenuCanOpen = e.button == 2;
-        if (this.active && !e.isDefaultPrevented()) {
-            e.stopPropagation();
-            if (e.buttons === 2) {
-                e.preventDefault();
-            }
-            document.removeEventListener("pointermove", this.onPointerMove)
-            document.addEventListener("pointermove", this.onPointerMove);
-            document.removeEventListener("pointerup", this.onPointerUp)
-            document.addEventListener("pointerup", this.onPointerUp);
-        }
-    }
-
-    onPointerMove = (e: PointerEvent): void => {
-        if (e.cancelBubble) {
-            this._contextMenuCanOpen = false;
-            return;
-        }
-        if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) {
-            this._contextMenuCanOpen = false;
-            if (this._mainCont.current != null && !this.topMost) {
-                this._contextMenuCanOpen = false;
-                const rect = this.screenRect;
-                let dragData: { [id: string]: any } = {};
-                dragData["document"] = this;
-                dragData["xOffset"] = e.x - rect.left;
-                dragData["yOffset"] = e.y - rect.top;
-                DragManager.StartDrag(this._mainCont.current, dragData, {
-                    handlers: {
-                        dragComplete: this.dragComplete,
-                    },
-                    hideSource: true
-                })
-            }
-        }
-        e.stopPropagation();
-        e.preventDefault();
-    }
-
-    onPointerUp = (e: PointerEvent): void => {
-        document.removeEventListener("pointermove", this.onPointerMove)
-        document.removeEventListener("pointerup", this.onPointerUp)
-        e.stopPropagation();
-        if (Math.abs(e.clientX - this._downX) < 4 && Math.abs(e.clientY - this._downY) < 4) {
-            SelectionManager.SelectDoc(this, e.ctrlKey);
-        }
-    }
-
-    openRight = (e: React.MouseEvent): void => {
-        CollectionDockingView.AddRightSplit(this.props.Document);
-    }
-
-    deleteClicked = (e: React.MouseEvent): void => {
-        if (this.props.ContainingCollectionView instanceof CollectionFreeFormView) {
-            this.props.ContainingCollectionView.removeDocument(this.props.Document)
-        }
-    }
-    @action
-    fullScreenClicked = (e: React.MouseEvent): void => {
-        CollectionDockingView.OpenFullScreen(this.props.Document);
-        ContextMenu.Instance.clearItems();
-        ContextMenu.Instance.addItem({ description: "Close Full Screen", event: this.closeFullScreenClicked });
-        ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15)
-    }
-    @action
-    closeFullScreenClicked = (e: React.MouseEvent): void => {
-        CollectionDockingView.CloseFullScreen();
-        ContextMenu.Instance.clearItems();
-        ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked })
-        ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15)
-    }
-
-    @action
-    onContextMenu = (e: React.MouseEvent): void => {
-        if (!SelectionManager.IsSelected(this)) {
-            return;
-        }
-        e.preventDefault()
-
-        if (!this._contextMenuCanOpen) {
-            return;
-        }
-
-        if (this.topMost) {
-            ContextMenu.Instance.clearItems()
-            ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked })
-            ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15)
-        }
-        else {
-            // DocumentViews should stop propogation of this event
-            e.stopPropagation();
-
-            ContextMenu.Instance.clearItems();
-            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.displayMenu(e.pageX - 15, e.pageY - 15)
-            SelectionManager.SelectDoc(this, e.ctrlKey);
-        }
-    }
-
-    render() {
-        var freestyling = this.props.ContainingCollectionView instanceof CollectionFreeFormView;
         return (
             <div className="node" ref={this._mainCont} style={{
-                transform: freestyling ? this.transform : "",
-                width: freestyling ? this.width : "100%",
-                height: freestyling ? this.height : "100%",
-                position: freestyling ? "absolute" : "relative",
-                zIndex: freestyling ? this.zIndex : 0,
-            }}
-                onContextMenu={this.onContextMenu}
-                onPointerDown={this.onPointerDown}>
-
-                <DocumentContentsView {...this.props} />
+                width: "100%",
+                height: "100%",
+            }}>
+                <JsxParser
+                    components={{ FieldTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView }}
+                    bindings={bindings}
+                    jsx={this.layout}
+                    showWarnings={true}
+                    onError={(test: any) => { console.log(test) }}
+                />
             </div>
-        );
+        )
     }
-}
\ No newline at end of file
+}
diff --git a/src/views/nodes/FieldTextBox.tsx b/src/views/nodes/FieldTextBox.tsx
index 0a8706517..0e884a031 100644
--- a/src/views/nodes/FieldTextBox.tsx
+++ b/src/views/nodes/FieldTextBox.tsx
@@ -13,7 +13,7 @@ import "./FieldTextBox.scss";
 import React = require("react")
 import { RichTextField } from "../../fields/RichTextField";
 import { FieldViewProps } from "./FieldView";
-import { DocumentView } from "./DocumentView";
+import { CollectionFreeFormDocumentView } from "./CollectionFreeFormDocumentView";
 
 
 // FieldTextBox: Displays an editable plain text node that maps to a specified Key of a Document
@@ -34,7 +34,7 @@ import { DocumentView } from "./DocumentView";
 //
 export class FieldTextBox extends React.Component<FieldViewProps> {
 
-    public static LayoutString() { return "<FieldTextBox doc={Document} documentViewContainer={ContainingDocumentView} fieldKey={DataKey} />"; }
+    public static LayoutString() { return "<FieldTextBox doc={Document} documentViewContainer={DocumentContentsView} fieldKey={DataKey} />"; }
     private _ref: React.RefObject<HTMLDivElement>;
     private _editorView: Opt<EditorView>;
     private _reactionDisposer: Opt<IReactionDisposer>;
@@ -111,7 +111,7 @@ export class FieldTextBox extends React.Component<FieldViewProps> {
     }
     onPointerDown = (e: React.PointerEvent): void => {
         let me = this;
-        if (e.buttons === 1 && me.props.documentViewContainer instanceof DocumentView && SelectionManager.IsSelected(me.props.documentViewContainer)) {
+        if (e.buttons === 1 && me.props.documentViewContainer instanceof CollectionFreeFormDocumentView && SelectionManager.IsSelected(me.props.documentViewContainer)) {
             e.stopPropagation();
         }
     }
diff --git a/src/views/nodes/FieldView.tsx b/src/views/nodes/FieldView.tsx
index b7a1d0526..9f0404dbf 100644
--- a/src/views/nodes/FieldView.tsx
+++ b/src/views/nodes/FieldView.tsx
@@ -1,5 +1,4 @@
 import React = require("react")
-import { DocumentView, DocumentContentsView } from "./DocumentView";
 import { Document } from "../../fields/Document";
 import { observer } from "mobx-react";
 import { computed } from "mobx";
@@ -11,6 +10,7 @@ import { FieldTextBox } from "./FieldTextBox";
 import { ImageField } from "../../fields/ImageField";
 import { ImageBox } from "./ImageBox";
 import { Key } from "../../fields/Key";
+import { DocumentView } from "./DocumentView";
 
 //
 // these properties get assigned through the render() method of the DocumentView when it creates this node.
@@ -20,7 +20,7 @@ import { Key } from "../../fields/Key";
 export interface FieldViewProps {
     fieldKey: Key;
     doc: Document;
-    documentViewContainer: DocumentContentsView
+    documentViewContainer: DocumentView
 }
 
 @observer
diff --git a/src/views/nodes/ImageBox.tsx b/src/views/nodes/ImageBox.tsx
index d2f567423..a4254ce39 100644
--- a/src/views/nodes/ImageBox.tsx
+++ b/src/views/nodes/ImageBox.tsx
@@ -6,7 +6,7 @@ import "./ImageBox.scss";
 import React = require("react")
 import { ImageField } from '../../fields/ImageField';
 import { FieldViewProps } from './FieldView';
-import { DocumentView } from './DocumentView';
+import { CollectionFreeFormDocumentView } from './CollectionFreeFormDocumentView';
 
 interface ImageBoxState {
     photoIndex: number,
@@ -15,7 +15,7 @@ interface ImageBoxState {
 
 export class ImageBox extends React.Component<FieldViewProps, ImageBoxState> {
 
-    public static LayoutString() { return "<ImageBox doc={Document} documentViewContainer={ContainingDocumentView} fieldKey={DataKey} />"; }
+    public static LayoutString() { return "<ImageBox doc={Document} documentViewContainer={DocumentContentsView} fieldKey={DataKey} />"; }
     private _ref: React.RefObject<HTMLDivElement>;
     private _downX: number = 0;
     private _downY: number = 0;
@@ -39,7 +39,7 @@ export class ImageBox extends React.Component<FieldViewProps, ImageBoxState> {
 
     onPointerDown = (e: React.PointerEvent): void => {
         if (Date.now() - this._lastTap < 300) {
-            if (e.buttons === 1 && this.props.documentViewContainer instanceof DocumentView && SelectionManager.IsSelected(this.props.documentViewContainer)) {
+            if (e.buttons === 1 && this.props.documentViewContainer instanceof CollectionFreeFormDocumentView && SelectionManager.IsSelected(this.props.documentViewContainer)) {
                 e.stopPropagation();
                 this._downX = e.clientX;
                 this._downY = e.clientY;
@@ -67,7 +67,7 @@ export class ImageBox extends React.Component<FieldViewProps, ImageBoxState> {
         const images = [path,];
         var lightbox = () => {
             const { photoIndex } = this.state;
-            if (this.state.isOpen && this.props.documentViewContainer instanceof DocumentView && SelectionManager.IsSelected(this.props.documentViewContainer)) {
+            if (this.state.isOpen && this.props.documentViewContainer instanceof CollectionFreeFormDocumentView && SelectionManager.IsSelected(this.props.documentViewContainer)) {
                 return (<Lightbox
                     mainSrc={images[photoIndex]}
                     nextSrc={photoIndex + 1 < images.length ? images[(photoIndex + 1) % images.length] : undefined}
-- 
cgit v1.2.3-70-g09d2


From 46a3ba510a02464b27b806af8fd1131dbc3da242 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 5 Feb 2019 11:33:30 -0500
Subject: more reorg

---
 src/documents/Documents.ts                       |   4 +-
 src/views/collections/CollectionDockingView.tsx  |   4 +-
 src/views/collections/CollectionFreeFormView.tsx |   8 +-
 src/views/collections/CollectionSchemaView.tsx   |   6 +-
 src/views/nodes/DocumentView.tsx                 |  14 +--
 src/views/nodes/FieldTextBox.scss                |  14 ---
 src/views/nodes/FieldTextBox.tsx                 | 127 -----------------------
 src/views/nodes/FieldView.tsx                    |   7 +-
 src/views/nodes/FormattedTextBox.scss            |  14 +++
 src/views/nodes/FormattedTextBox.tsx             | 125 ++++++++++++++++++++++
 src/views/nodes/ImageBox.tsx                     |   4 +-
 11 files changed, 163 insertions(+), 164 deletions(-)
 delete mode 100644 src/views/nodes/FieldTextBox.scss
 delete mode 100644 src/views/nodes/FieldTextBox.tsx
 create mode 100644 src/views/nodes/FormattedTextBox.scss
 create mode 100644 src/views/nodes/FormattedTextBox.tsx

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

diff --git a/src/documents/Documents.ts b/src/documents/Documents.ts
index 29ef32966..b69b79dd3 100644
--- a/src/documents/Documents.ts
+++ b/src/documents/Documents.ts
@@ -3,7 +3,7 @@ import { KeyStore } from "../fields/Key";
 import { TextField } from "../fields/TextField";
 import { NumberField } from "../fields/NumberField";
 import { ListField } from "../fields/ListField";
-import { FieldTextBox } from "../views/nodes/FieldTextBox";
+import { FormattedTextBox } from "../views/nodes/FormattedTextBox";
 import { CollectionDockingView } from "../views/collections/CollectionDockingView";
 import { CollectionSchemaView } from "../views/collections/CollectionSchemaView";
 import { ImageField } from "../fields/ImageField";
@@ -49,7 +49,7 @@ export namespace Documents {
             textProto.SetField(KeyStore.Y, new NumberField(0));
             textProto.SetField(KeyStore.Width, new NumberField(300));
             textProto.SetField(KeyStore.Height, new NumberField(150));
-            textProto.SetField(KeyStore.Layout, new TextField(FieldTextBox.LayoutString()));
+            textProto.SetField(KeyStore.Layout, new TextField(FormattedTextBox.LayoutString()));
             textProto.SetField(KeyStore.LayoutKeys, new ListField([KeyStore.Data]));
         }
         return textProto;
diff --git a/src/views/collections/CollectionDockingView.tsx b/src/views/collections/CollectionDockingView.tsx
index 1a523e1bf..49f1a0bf0 100644
--- a/src/views/collections/CollectionDockingView.tsx
+++ b/src/views/collections/CollectionDockingView.tsx
@@ -69,7 +69,7 @@ export class CollectionDockingView extends CollectionViewBase {
 
     @action
     onResize = (event: any) => {
-        var cur = this.props.DocumentContentsOfCollection!.MainContent.current;
+        var cur = this.props.DocumentViewForCollection!.MainContent.current;
 
         // bcz: since GoldenLayout isn't a React component itself, we need to notify it to resize when its document container's size has changed
         CollectionDockingView.myLayout.updateSize(cur!.getBoundingClientRect().width, cur!.getBoundingClientRect().height);
@@ -255,7 +255,7 @@ export class CollectionDockingView extends CollectionViewBase {
         const { CollectionFieldKey: fieldKey, DocumentForCollection: Document } = this.props;
         const value: Document[] = Document.GetFieldValue(fieldKey, ListField, []);
         // bcz: not sure why, but I need these to force the flexlayout to update when the collection size changes.
-        var s = this.props.DocumentContentsOfCollection != undefined ? this.props.DocumentContentsOfCollection!.ScalingToScreenSpace : 1;
+        var s = this.props.DocumentViewForCollection != undefined ? this.props.DocumentViewForCollection!.ScalingToScreenSpace : 1;
         var w = Document.GetFieldValue(KeyStore.Width, NumberField, Number(0)) / s;
         var h = Document.GetFieldValue(KeyStore.Height, NumberField, Number(0)) / s;
 
diff --git a/src/views/collections/CollectionFreeFormView.tsx b/src/views/collections/CollectionFreeFormView.tsx
index c91946475..d266a55d9 100644
--- a/src/views/collections/CollectionFreeFormView.tsx
+++ b/src/views/collections/CollectionFreeFormView.tsx
@@ -39,7 +39,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
             const xOffset = de.data["xOffset"] as number || 0;
             const yOffset = de.data["yOffset"] as number || 0;
             const { scale, translateX, translateY } = Utils.GetScreenTransform(this._canvasRef.current!);
-            let sscale = this.props.DocumentContentsOfCollection!.props.Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1))
+            let sscale = this.props.DocumentViewForCollection!.props.Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1))
             const screenX = de.x - xOffset;
             const screenY = de.y - yOffset;
             const docX = (screenX - translateX) / sscale / scale;
@@ -94,7 +94,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
         if (!e.cancelBubble && this.active) {
             e.preventDefault();
             e.stopPropagation();
-            let currScale: number = this.props.DocumentContentsOfCollection!.ScalingToScreenSpace;
+            let currScale: number = this.props.DocumentViewForCollection!.ScalingToScreenSpace;
             let x = this.props.DocumentForCollection.GetFieldValue(KeyStore.PanX, NumberField, Number(0));
             let y = this.props.DocumentForCollection.GetFieldValue(KeyStore.PanY, NumberField, Number(0));
             this.props.DocumentForCollection.SetFieldValue(KeyStore.PanX, x + (e.pageX - this._lastX) / currScale, NumberField);
@@ -108,7 +108,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
     onPointerWheel = (e: React.WheelEvent): void => {
         e.stopPropagation();
 
-        let { LocalX, Ss, Panxx, Xx, LocalY, Panyy, Yy, ContainerX, ContainerY } = this.props.DocumentContentsOfCollection!.TransformToLocalPoint(e.pageX, e.pageY);
+        let { LocalX, Ss, Panxx, Xx, LocalY, Panyy, Yy, ContainerX, ContainerY } = this.props.DocumentViewForCollection!.TransformToLocalPoint(e.pageX, e.pageY);
 
         var deltaScale = (1 - (e.deltaY / 1000)) * Ss;
 
@@ -198,7 +198,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
 
                         <div className="node-container" ref={this._nodeContainerRef}>
                             {value.map(doc => {
-                                return (<CollectionFreeFormDocumentView key={doc.Id} ContainingCollectionView={this} Document={doc} DocumentContentsView={this.props.DocumentContentsOfCollection} />);
+                                return (<CollectionFreeFormDocumentView key={doc.Id} ContainingCollectionView={this} Document={doc} DocumentContentsView={this.props.DocumentViewForCollection} />);
                             })}
                         </div>
                     </div>
diff --git a/src/views/collections/CollectionSchemaView.tsx b/src/views/collections/CollectionSchemaView.tsx
index 8c79c9189..b2ff95329 100644
--- a/src/views/collections/CollectionSchemaView.tsx
+++ b/src/views/collections/CollectionSchemaView.tsx
@@ -20,13 +20,13 @@ export class CollectionSchemaView extends CollectionViewBase {
     selectedIndex = 0;
 
     renderCell = (rowProps: CellInfo) => {
-        if (!this.props.DocumentContentsOfCollection) {
+        if (!this.props.DocumentViewForCollection) {
             return <div></div>
         }
         let props: FieldViewProps = {
             doc: rowProps.value[0],
             fieldKey: rowProps.value[1],
-            documentViewContainer: this.props.DocumentContentsOfCollection
+            documentViewContainer: this.props.DocumentViewForCollection
         }
         return (
             <FieldView {...props} />
@@ -78,7 +78,7 @@ export class CollectionSchemaView extends CollectionViewBase {
         let content;
         if (this.selectedIndex != -1) {
             content = (<DocumentView Document={children[this.selectedIndex]}
-                DocumentContentsView={this.props.DocumentContentsOfCollection}
+                DocumentContentsView={this.props.DocumentViewForCollection}
                 ContainingCollectionView={this} />)
         } else {
             content = <div />
diff --git a/src/views/nodes/DocumentView.tsx b/src/views/nodes/DocumentView.tsx
index fd5ffeb61..7ff1ef5cc 100644
--- a/src/views/nodes/DocumentView.tsx
+++ b/src/views/nodes/DocumentView.tsx
@@ -11,7 +11,7 @@ import { CollectionDockingView } from "../collections/CollectionDockingView";
 import { CollectionFreeFormView } from "../collections/CollectionFreeFormView";
 import { CollectionSchemaView } from "../collections/CollectionSchemaView";
 import { CollectionViewBase, COLLECTION_BORDER_WIDTH } from "../collections/CollectionViewBase";
-import { FieldTextBox } from "../nodes/FieldTextBox";
+import { FormattedTextBox } from "../nodes/FormattedTextBox";
 import { ImageBox } from "../nodes/ImageBox";
 import "./NodeView.scss";
 import React = require("react");
@@ -49,9 +49,9 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     //
     @computed
     public get ScalingToScreenSpace(): number {
-        if (this.props.ContainingCollectionView != undefined && this.props.ContainingCollectionView.props.DocumentContentsOfCollection != undefined) {
+        if (this.props.ContainingCollectionView != undefined && this.props.ContainingCollectionView.props.DocumentViewForCollection != undefined) {
             let ss = this.props.ContainingCollectionView.props.DocumentForCollection.GetFieldValue(KeyStore.Scale, NumberField, Number(1));
-            return this.props.ContainingCollectionView.props.DocumentContentsOfCollection.ScalingToScreenSpace * ss;
+            return this.props.ContainingCollectionView.props.DocumentViewForCollection.ScalingToScreenSpace * ss;
         }
         return 1;
     }
@@ -62,8 +62,8 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     public TransformToLocalPoint(screenX: number, screenY: number) {
         // if this collection view is nested within another collection view, then 
         // first transform the screen point into the parent collection's coordinate space.
-        let { LocalX: parentX, LocalY: parentY } = this.props.ContainingCollectionView != undefined && this.props.ContainingCollectionView.props.DocumentContentsOfCollection != undefined ?
-            this.props.ContainingCollectionView.props.DocumentContentsOfCollection.TransformToLocalPoint(screenX, screenY) :
+        let { LocalX: parentX, LocalY: parentY } = this.props.ContainingCollectionView != undefined && this.props.ContainingCollectionView.props.DocumentViewForCollection != undefined ?
+            this.props.ContainingCollectionView.props.DocumentViewForCollection.TransformToLocalPoint(screenX, screenY) :
             { LocalX: screenX, LocalY: screenY };
         let ContainerX: number = parentX - COLLECTION_BORDER_WIDTH;
         let ContainerY: number = parentY - COLLECTION_BORDER_WIDTH;
@@ -111,7 +111,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
 
         // if this collection view is nested within another collection view, then 
         // first transform the local point into the parent collection's coordinate space.
-        let containingDocView = this.props.ContainingCollectionView != undefined ? this.props.ContainingCollectionView.props.DocumentContentsOfCollection : undefined;//.ContainingDocumentContentsView;
+        let containingDocView = this.props.ContainingCollectionView != undefined ? this.props.ContainingCollectionView.props.DocumentViewForCollection : undefined;//.ContainingDocumentContentsView;
         if (containingDocView != undefined) {
             let ss = containingDocView.props.Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1));
             let panxx = containingDocView.props.Document.GetFieldValue(KeyStore.PanX, NumberField, Number(0)) + COLLECTION_BORDER_WIDTH * ss;
@@ -144,7 +144,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
                 height: "100%",
             }}>
                 <JsxParser
-                    components={{ FieldTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView }}
+                    components={{ FormattedTextBox: FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView }}
                     bindings={bindings}
                     jsx={this.layout}
                     showWarnings={true}
diff --git a/src/views/nodes/FieldTextBox.scss b/src/views/nodes/FieldTextBox.scss
deleted file mode 100644
index b6ce2fabc..000000000
--- a/src/views/nodes/FieldTextBox.scss
+++ /dev/null
@@ -1,14 +0,0 @@
-.ProseMirror {
-    margin-top: -1em;
-    width: 100%;
-    height: 100%;
-}
-
-.ProseMirror:focus {
-    outline: none !important
-}
-
-.fieldTextBox-cont {
-    background: white;
-    padding: 1vw;
-}
\ No newline at end of file
diff --git a/src/views/nodes/FieldTextBox.tsx b/src/views/nodes/FieldTextBox.tsx
deleted file mode 100644
index 0e884a031..000000000
--- a/src/views/nodes/FieldTextBox.tsx
+++ /dev/null
@@ -1,127 +0,0 @@
-import { action, IReactionDisposer, reaction } from "mobx";
-import { baseKeymap } from "prosemirror-commands";
-import { history, redo, undo } from "prosemirror-history";
-import { keymap } from "prosemirror-keymap";
-import { schema } from "prosemirror-schema-basic";
-import { EditorState, Transaction } from "prosemirror-state";
-import { EditorView } from "prosemirror-view";
-import { Document } from "../../fields/Document";
-import { Opt } from "../../fields/Field";
-import { Key } from "../../fields/Key";
-import { SelectionManager } from "../../util/SelectionManager";
-import "./FieldTextBox.scss";
-import React = require("react")
-import { RichTextField } from "../../fields/RichTextField";
-import { FieldViewProps } from "./FieldView";
-import { CollectionFreeFormDocumentView } from "./CollectionFreeFormDocumentView";
-
-
-// FieldTextBox: Displays an editable plain text node that maps to a specified Key of a Document
-//
-//  HTML Markup:  <FieldTextBox Doc={Document's ID} FieldKey={Key's name + "Key"}
-// 
-//  In Code, the node's HTML is specified in the document's parameterized structure as:
-//        document.SetField(KeyStore.Layout,  "<FieldTextBox doc={doc} fieldKey={<KEYNAME>Key} />");
-//  and the node's binding to the specified document KEYNAME as:
-//        document.SetField(KeyStore.LayoutKeys, new ListField([KeyStore.<KEYNAME>]));
-//  The Jsx parser at run time will bind:
-//        'fieldKey' property to the Key stored in LayoutKeys
-//    and 'doc' property to the document that is being rendered
-//
-//  When rendered() by React, this extracts the TextController from the Document stored at the 
-//  specified Key and assigns it to an HTML input node.  When changes are made tot his node, 
-//  this will edit the document and assign the new value to that field.
-//
-export class FieldTextBox extends React.Component<FieldViewProps> {
-
-    public static LayoutString() { return "<FieldTextBox doc={Document} documentViewContainer={DocumentContentsView} fieldKey={DataKey} />"; }
-    private _ref: React.RefObject<HTMLDivElement>;
-    private _editorView: Opt<EditorView>;
-    private _reactionDisposer: Opt<IReactionDisposer>;
-
-    constructor(props: FieldViewProps) {
-        super(props);
-
-        this._ref = React.createRef();
-
-        this.onChange = this.onChange.bind(this);
-    }
-
-    dispatchTransaction = (tx: Transaction) => {
-        if (this._editorView) {
-            const state = this._editorView.state.apply(tx);
-            this._editorView.updateState(state);
-            const { doc, fieldKey } = this.props;
-            doc.SetFieldValue(fieldKey, JSON.stringify(state.toJSON()), RichTextField);
-        }
-    }
-
-    componentDidMount() {
-        let state: EditorState;
-        const { doc, fieldKey } = this.props;
-        const config = {
-            schema,
-            plugins: [
-                history(),
-                keymap({ "Mod-z": undo, "Mod-y": redo }),
-                keymap(baseKeymap)
-            ]
-        };
-
-        let field = doc.GetFieldT(fieldKey, RichTextField);
-        if (field) {
-            state = EditorState.fromJSON(config, JSON.parse(field.Data));
-        } else {
-            state = EditorState.create(config);
-        }
-        if (this._ref.current) {
-            this._editorView = new EditorView(this._ref.current, {
-                state,
-                dispatchTransaction: this.dispatchTransaction
-            });
-        }
-
-        this._reactionDisposer = reaction(() => {
-            const field = this.props.doc.GetFieldT(this.props.fieldKey, RichTextField);
-            return field ? field.Data : undefined;
-        }, (field) => {
-            if (field && this._editorView) {
-                this._editorView.updateState(EditorState.fromJSON(config, JSON.parse(field)));
-            }
-        })
-    }
-
-    componentWillUnmount() {
-        if (this._editorView) {
-            this._editorView.destroy();
-        }
-        if (this._reactionDisposer) {
-            this._reactionDisposer();
-        }
-    }
-
-    shouldComponentUpdate() {
-        return false;
-    }
-
-    @action
-    onChange(e: React.ChangeEvent<HTMLInputElement>) {
-        const { fieldKey, doc } = this.props;
-        doc.SetFieldValue(fieldKey, e.target.value, RichTextField);
-    }
-    onPointerDown = (e: React.PointerEvent): void => {
-        let me = this;
-        if (e.buttons === 1 && me.props.documentViewContainer instanceof CollectionFreeFormDocumentView && SelectionManager.IsSelected(me.props.documentViewContainer)) {
-            e.stopPropagation();
-        }
-    }
-    render() {
-        return (<div className="fieldTextBox-cont"
-            style={{
-                color: "initial",
-                whiteSpace: "initial"
-            }}
-            onPointerDown={this.onPointerDown}
-            ref={this._ref} />)
-    }
-}
\ No newline at end of file
diff --git a/src/views/nodes/FieldView.tsx b/src/views/nodes/FieldView.tsx
index 9f0404dbf..370f6d324 100644
--- a/src/views/nodes/FieldView.tsx
+++ b/src/views/nodes/FieldView.tsx
@@ -6,7 +6,7 @@ import { Field, Opt } from "../../fields/Field";
 import { TextField } from "../../fields/TextField";
 import { NumberField } from "../../fields/NumberField";
 import { RichTextField } from "../../fields/RichTextField";
-import { FieldTextBox } from "./FieldTextBox";
+import { FormattedTextBox } from "./FormattedTextBox";
 import { ImageField } from "../../fields/ImageField";
 import { ImageBox } from "./ImageBox";
 import { Key } from "../../fields/Key";
@@ -15,7 +15,7 @@ import { DocumentView } from "./DocumentView";
 //
 // these properties get assigned through the render() method of the DocumentView when it creates this node.
 // However, that only happens because the properties are "defined" in the markup for the field view.
-// See the LayoutString method on each field view :   ImageBox, FieldTextBox, etc. 
+// See the LayoutString method on each field view :   ImageBox, FormattedTextBox, etc. 
 //
 export interface FieldViewProps {
     fieldKey: Key;
@@ -25,6 +25,7 @@ export interface FieldViewProps {
 
 @observer
 export class FieldView extends React.Component<FieldViewProps> {
+    public static LayoutString(fieldType: string) { return `<${fieldType} doc={Document} documentViewContainer={DocumentContentsView} fieldKey={DataKey} />`; }
     @computed
     get field(): Opt<Field> {
         const { doc, fieldKey } = this.props;
@@ -39,7 +40,7 @@ export class FieldView extends React.Component<FieldViewProps> {
             return <p>{field.Data}</p>
         }
         else if (field instanceof RichTextField) {
-            return <FieldTextBox {...this.props} />
+            return <FormattedTextBox {...this.props} />
         }
         else if (field instanceof ImageField) {
             return <ImageBox {...this.props} />
diff --git a/src/views/nodes/FormattedTextBox.scss b/src/views/nodes/FormattedTextBox.scss
new file mode 100644
index 000000000..492367fce
--- /dev/null
+++ b/src/views/nodes/FormattedTextBox.scss
@@ -0,0 +1,14 @@
+.ProseMirror {
+    margin-top: -1em;
+    width: 100%;
+    height: 100%;
+}
+
+.ProseMirror:focus {
+    outline: none !important
+}
+
+.formattedTextBox-cont {
+    background: white;
+    padding: 1vw;
+}
\ No newline at end of file
diff --git a/src/views/nodes/FormattedTextBox.tsx b/src/views/nodes/FormattedTextBox.tsx
new file mode 100644
index 000000000..d51e91315
--- /dev/null
+++ b/src/views/nodes/FormattedTextBox.tsx
@@ -0,0 +1,125 @@
+import { action, IReactionDisposer, reaction } from "mobx";
+import { baseKeymap } from "prosemirror-commands";
+import { history, redo, undo } from "prosemirror-history";
+import { keymap } from "prosemirror-keymap";
+import { schema } from "prosemirror-schema-basic";
+import { EditorState, Transaction } from "prosemirror-state";
+import { EditorView } from "prosemirror-view";
+import { Opt } from "../../fields/Field";
+import { SelectionManager } from "../../util/SelectionManager";
+import "./FormattedTextBox.scss";
+import React = require("react")
+import { RichTextField } from "../../fields/RichTextField";
+import { FieldViewProps, FieldView } from "./FieldView";
+import { CollectionFreeFormDocumentView } from "./CollectionFreeFormDocumentView";
+
+
+// FormattedTextBox: Displays an editable plain text node that maps to a specified Key of a Document
+//
+//  HTML Markup:  <FormattedTextBox Doc={Document's ID} FieldKey={Key's name + "Key"}
+// 
+//  In Code, the node's HTML is specified in the document's parameterized structure as:
+//        document.SetField(KeyStore.Layout,  "<FormattedTextBox doc={doc} fieldKey={<KEYNAME>Key} />");
+//  and the node's binding to the specified document KEYNAME as:
+//        document.SetField(KeyStore.LayoutKeys, new ListField([KeyStore.<KEYNAME>]));
+//  The Jsx parser at run time will bind:
+//        'fieldKey' property to the Key stored in LayoutKeys
+//    and 'doc' property to the document that is being rendered
+//
+//  When rendered() by React, this extracts the TextController from the Document stored at the 
+//  specified Key and assigns it to an HTML input node.  When changes are made tot his node, 
+//  this will edit the document and assign the new value to that field.
+//
+export class FormattedTextBox extends React.Component<FieldViewProps> {
+
+    public static LayoutString() { return FieldView.LayoutString("FormattedTextBox"); }
+    private _ref: React.RefObject<HTMLDivElement>;
+    private _editorView: Opt<EditorView>;
+    private _reactionDisposer: Opt<IReactionDisposer>;
+
+    constructor(props: FieldViewProps) {
+        super(props);
+
+        this._ref = React.createRef();
+
+        this.onChange = this.onChange.bind(this);
+    }
+
+    dispatchTransaction = (tx: Transaction) => {
+        if (this._editorView) {
+            const state = this._editorView.state.apply(tx);
+            this._editorView.updateState(state);
+            const { doc, fieldKey } = this.props;
+            doc.SetFieldValue(fieldKey, JSON.stringify(state.toJSON()), RichTextField);
+        }
+    }
+
+    componentDidMount() {
+        let state: EditorState;
+        const { doc, fieldKey } = this.props;
+        const config = {
+            schema,
+            plugins: [
+                history(),
+                keymap({ "Mod-z": undo, "Mod-y": redo }),
+                keymap(baseKeymap)
+            ]
+        };
+
+        let field = doc.GetFieldT(fieldKey, RichTextField);
+        if (field) {
+            state = EditorState.fromJSON(config, JSON.parse(field.Data));
+        } else {
+            state = EditorState.create(config);
+        }
+        if (this._ref.current) {
+            this._editorView = new EditorView(this._ref.current, {
+                state,
+                dispatchTransaction: this.dispatchTransaction
+            });
+        }
+
+        this._reactionDisposer = reaction(() => {
+            const field = this.props.doc.GetFieldT(this.props.fieldKey, RichTextField);
+            return field ? field.Data : undefined;
+        }, (field) => {
+            if (field && this._editorView) {
+                this._editorView.updateState(EditorState.fromJSON(config, JSON.parse(field)));
+            }
+        })
+    }
+
+    componentWillUnmount() {
+        if (this._editorView) {
+            this._editorView.destroy();
+        }
+        if (this._reactionDisposer) {
+            this._reactionDisposer();
+        }
+    }
+
+    shouldComponentUpdate() {
+        return false;
+    }
+
+    @action
+    onChange(e: React.ChangeEvent<HTMLInputElement>) {
+        const { fieldKey, doc } = this.props;
+        doc.SetFieldValue(fieldKey, e.target.value, RichTextField);
+    }
+    onPointerDown = (e: React.PointerEvent): void => {
+        let me = this;
+        if (e.buttons === 1 && me.props.documentViewContainer instanceof CollectionFreeFormDocumentView && SelectionManager.IsSelected(me.props.documentViewContainer)) {
+            e.stopPropagation();
+        }
+    }
+    render() {
+        return (<div className="formattedTextBox-cont"
+            style={{
+                color: "initial",
+                whiteSpace: "initial"
+            }}
+            onPointerDown={this.onPointerDown}
+            ref={this._ref} />)
+    }
+}
\ No newline at end of file
diff --git a/src/views/nodes/ImageBox.tsx b/src/views/nodes/ImageBox.tsx
index a4254ce39..cced95c89 100644
--- a/src/views/nodes/ImageBox.tsx
+++ b/src/views/nodes/ImageBox.tsx
@@ -5,7 +5,7 @@ import { SelectionManager } from "../../util/SelectionManager";
 import "./ImageBox.scss";
 import React = require("react")
 import { ImageField } from '../../fields/ImageField';
-import { FieldViewProps } from './FieldView';
+import { FieldViewProps, FieldView } from './FieldView';
 import { CollectionFreeFormDocumentView } from './CollectionFreeFormDocumentView';
 
 interface ImageBoxState {
@@ -15,7 +15,7 @@ interface ImageBoxState {
 
 export class ImageBox extends React.Component<FieldViewProps, ImageBoxState> {
 
-    public static LayoutString() { return "<ImageBox doc={Document} documentViewContainer={DocumentContentsView} fieldKey={DataKey} />"; }
+    public static LayoutString() { return FieldView.LayoutString("ImageBox"); }
     private _ref: React.RefObject<HTMLDivElement>;
     private _downX: number = 0;
     private _downY: number = 0;
-- 
cgit v1.2.3-70-g09d2


From ea9f41a84a307343593245e6de0c721704dc60fa Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 5 Feb 2019 11:51:59 -0500
Subject: more

---
 src/Main.tsx                                       | 2 +-
 src/views/collections/CollectionDockingView.tsx    | 4 ++--
 src/views/collections/CollectionFreeFormView.tsx   | 2 +-
 src/views/collections/CollectionSchemaView.tsx     | 7 ++-----
 src/views/nodes/CollectionFreeFormDocumentView.tsx | 2 +-
 src/views/nodes/DocumentView.tsx                   | 8 ++++----
 src/views/nodes/FieldView.tsx                      | 4 ++--
 src/views/nodes/FormattedTextBox.tsx               | 2 +-
 src/views/nodes/ImageBox.tsx                       | 4 ++--
 9 files changed, 16 insertions(+), 19 deletions(-)

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

diff --git a/src/Main.tsx b/src/Main.tsx
index 7618630f8..b72083ee6 100644
--- a/src/Main.tsx
+++ b/src/Main.tsx
@@ -80,7 +80,7 @@ document.addEventListener("pointerdown", action(function (e: PointerEvent) {
 
 ReactDOM.render((
     <div style={{ position: "absolute", width: "100%", height: "100%" }}>
-        <DocumentView Document={mainContainer} ContainingCollectionView={undefined} DocumentContentsView={undefined} />
+        <DocumentView Document={mainContainer} ContainingCollectionView={undefined} DocumentView={undefined} />
         <DocumentDecorations />
         <ContextMenu />
     </div>),
diff --git a/src/views/collections/CollectionDockingView.tsx b/src/views/collections/CollectionDockingView.tsx
index 49f1a0bf0..2e8d5a514 100644
--- a/src/views/collections/CollectionDockingView.tsx
+++ b/src/views/collections/CollectionDockingView.tsx
@@ -96,7 +96,7 @@ export class CollectionDockingView extends CollectionViewBase {
         const value: Document[] = Document.GetFieldValue(fieldKey, ListField, []);
         for (var i: number = 0; i < value.length; i++) {
             if (value[i].Id === component) {
-                return (<DocumentView key={value[i].Id} ContainingCollectionView={this} Document={value[i]} DocumentContentsView={undefined} />);
+                return (<DocumentView key={value[i].Id} ContainingCollectionView={this} Document={value[i]} DocumentView={undefined} />);
             }
         }
         if (component === "text") {
@@ -237,7 +237,7 @@ export class CollectionDockingView extends CollectionViewBase {
             container.getElement().html("<div id='" + containingDiv + "'></div>");
             setTimeout(function () {
                 ReactDOM.render((
-                    <DocumentView key={state.doc.Id} Document={state.doc} ContainingCollectionView={me} DocumentContentsView={undefined} /> // bcz: need to fill in DocumentContentsView with value of DocumentContents when created...
+                    <DocumentView key={state.doc.Id} Document={state.doc} ContainingCollectionView={me} DocumentView={undefined} />
                 ),
                     document.getElementById(containingDiv)
                 );
diff --git a/src/views/collections/CollectionFreeFormView.tsx b/src/views/collections/CollectionFreeFormView.tsx
index d266a55d9..abc811642 100644
--- a/src/views/collections/CollectionFreeFormView.tsx
+++ b/src/views/collections/CollectionFreeFormView.tsx
@@ -198,7 +198,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
 
                         <div className="node-container" ref={this._nodeContainerRef}>
                             {value.map(doc => {
-                                return (<CollectionFreeFormDocumentView key={doc.Id} ContainingCollectionView={this} Document={doc} DocumentContentsView={this.props.DocumentViewForCollection} />);
+                                return (<CollectionFreeFormDocumentView key={doc.Id} ContainingCollectionView={this} Document={doc} DocumentView={this.props.DocumentViewForCollection} />);
                             })}
                         </div>
                     </div>
diff --git a/src/views/collections/CollectionSchemaView.tsx b/src/views/collections/CollectionSchemaView.tsx
index b2ff95329..19b1434ef 100644
--- a/src/views/collections/CollectionSchemaView.tsx
+++ b/src/views/collections/CollectionSchemaView.tsx
@@ -20,13 +20,10 @@ export class CollectionSchemaView extends CollectionViewBase {
     selectedIndex = 0;
 
     renderCell = (rowProps: CellInfo) => {
-        if (!this.props.DocumentViewForCollection) {
-            return <div></div>
-        }
         let props: FieldViewProps = {
             doc: rowProps.value[0],
             fieldKey: rowProps.value[1],
-            documentViewContainer: this.props.DocumentViewForCollection
+            DocumentViewForField: undefined
         }
         return (
             <FieldView {...props} />
@@ -78,7 +75,7 @@ export class CollectionSchemaView extends CollectionViewBase {
         let content;
         if (this.selectedIndex != -1) {
             content = (<DocumentView Document={children[this.selectedIndex]}
-                DocumentContentsView={this.props.DocumentViewForCollection}
+                DocumentView={undefined}
                 ContainingCollectionView={this} />)
         } else {
             content = <div />
diff --git a/src/views/nodes/CollectionFreeFormDocumentView.tsx b/src/views/nodes/CollectionFreeFormDocumentView.tsx
index 78e3325ab..ebe6d411c 100644
--- a/src/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -215,7 +215,7 @@ export class CollectionFreeFormDocumentView extends DocumentView {
                 onContextMenu={this.onContextMenu}
                 onPointerDown={this.onPointerDown}>
 
-                <DocumentView {...this.props} DocumentContentsView={this} />
+                <DocumentView {...this.props} DocumentView={this} />
             </div>
         );
     }
diff --git a/src/views/nodes/DocumentView.tsx b/src/views/nodes/DocumentView.tsx
index 7ff1ef5cc..9a3783fdc 100644
--- a/src/views/nodes/DocumentView.tsx
+++ b/src/views/nodes/DocumentView.tsx
@@ -20,7 +20,7 @@ const JsxParser = require('react-jsx-parser').default;//TODO Why does this need
 export interface DocumentViewProps {
     Document: Document;
     ContainingCollectionView: Opt<CollectionViewBase>;
-    DocumentContentsView: Opt<DocumentView>
+    DocumentView: Opt<DocumentView>
 }
 @observer
 export class DocumentView extends React.Component<DocumentViewProps> {
@@ -111,7 +111,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
 
         // if this collection view is nested within another collection view, then 
         // first transform the local point into the parent collection's coordinate space.
-        let containingDocView = this.props.ContainingCollectionView != undefined ? this.props.ContainingCollectionView.props.DocumentViewForCollection : undefined;//.ContainingDocumentContentsView;
+        let containingDocView = this.props.ContainingCollectionView != undefined ? this.props.ContainingCollectionView.props.DocumentViewForCollection : undefined;
         if (containingDocView != undefined) {
             let ss = containingDocView.props.Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1));
             let panxx = containingDocView.props.Document.GetFieldValue(KeyStore.PanX, NumberField, Number(0)) + COLLECTION_BORDER_WIDTH * ss;
@@ -130,8 +130,8 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         for (const key of this.layoutKeys) {
             bindings[key.Name + "Key"] = key;
         }
-        if (this.props.DocumentContentsView == undefined)
-            bindings.DocumentContentsView = this;
+        if (this.props.DocumentView == undefined)
+            bindings.DocumentView = this;
         for (const key of this.layoutFields) {
             let field = doc.GetField(key);
             if (field) {
diff --git a/src/views/nodes/FieldView.tsx b/src/views/nodes/FieldView.tsx
index 370f6d324..2a2355a23 100644
--- a/src/views/nodes/FieldView.tsx
+++ b/src/views/nodes/FieldView.tsx
@@ -20,12 +20,12 @@ import { DocumentView } from "./DocumentView";
 export interface FieldViewProps {
     fieldKey: Key;
     doc: Document;
-    documentViewContainer: DocumentView
+    DocumentViewForField: Opt<DocumentView>
 }
 
 @observer
 export class FieldView extends React.Component<FieldViewProps> {
-    public static LayoutString(fieldType: string) { return `<${fieldType} doc={Document} documentViewContainer={DocumentContentsView} fieldKey={DataKey} />`; }
+    public static LayoutString(fieldType: string) { return `<${fieldType} doc={Document} DocumentViewForField={DocumentView} fieldKey={DataKey} />`; }
     @computed
     get field(): Opt<Field> {
         const { doc, fieldKey } = this.props;
diff --git a/src/views/nodes/FormattedTextBox.tsx b/src/views/nodes/FormattedTextBox.tsx
index d51e91315..9c4b24226 100644
--- a/src/views/nodes/FormattedTextBox.tsx
+++ b/src/views/nodes/FormattedTextBox.tsx
@@ -109,7 +109,7 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
     }
     onPointerDown = (e: React.PointerEvent): void => {
         let me = this;
-        if (e.buttons === 1 && me.props.documentViewContainer instanceof CollectionFreeFormDocumentView && SelectionManager.IsSelected(me.props.documentViewContainer)) {
+        if (e.buttons === 1 && me.props.DocumentViewForField instanceof CollectionFreeFormDocumentView && SelectionManager.IsSelected(me.props.DocumentViewForField)) {
             e.stopPropagation();
         }
     }
diff --git a/src/views/nodes/ImageBox.tsx b/src/views/nodes/ImageBox.tsx
index cced95c89..dd201f20f 100644
--- a/src/views/nodes/ImageBox.tsx
+++ b/src/views/nodes/ImageBox.tsx
@@ -39,7 +39,7 @@ export class ImageBox extends React.Component<FieldViewProps, ImageBoxState> {
 
     onPointerDown = (e: React.PointerEvent): void => {
         if (Date.now() - this._lastTap < 300) {
-            if (e.buttons === 1 && this.props.documentViewContainer instanceof CollectionFreeFormDocumentView && SelectionManager.IsSelected(this.props.documentViewContainer)) {
+            if (e.buttons === 1 && this.props.DocumentViewForField instanceof CollectionFreeFormDocumentView && SelectionManager.IsSelected(this.props.DocumentViewForField)) {
                 e.stopPropagation();
                 this._downX = e.clientX;
                 this._downY = e.clientY;
@@ -67,7 +67,7 @@ export class ImageBox extends React.Component<FieldViewProps, ImageBoxState> {
         const images = [path,];
         var lightbox = () => {
             const { photoIndex } = this.state;
-            if (this.state.isOpen && this.props.documentViewContainer instanceof CollectionFreeFormDocumentView && SelectionManager.IsSelected(this.props.documentViewContainer)) {
+            if (this.state.isOpen && this.props.DocumentViewForField instanceof CollectionFreeFormDocumentView && SelectionManager.IsSelected(this.props.DocumentViewForField)) {
                 return (<Lightbox
                     mainSrc={images[photoIndex]}
                     nextSrc={photoIndex + 1 < images.length ? images[(photoIndex + 1) % images.length] : undefined}
-- 
cgit v1.2.3-70-g09d2


From 7740c0010944cfa215c9b21b113f030199ffab82 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 5 Feb 2019 12:18:52 -0500
Subject: naming changes

---
 src/views/collections/CollectionDockingView.tsx  |  4 ++--
 src/views/collections/CollectionFreeFormView.tsx |  8 ++++----
 src/views/collections/CollectionSchemaView.tsx   |  4 +---
 src/views/collections/CollectionViewBase.tsx     | 14 +++++++++-----
 src/views/nodes/DocumentView.tsx                 | 15 +++++++--------
 5 files changed, 23 insertions(+), 22 deletions(-)

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

diff --git a/src/views/collections/CollectionDockingView.tsx b/src/views/collections/CollectionDockingView.tsx
index 2e8d5a514..92b5e563c 100644
--- a/src/views/collections/CollectionDockingView.tsx
+++ b/src/views/collections/CollectionDockingView.tsx
@@ -69,7 +69,7 @@ export class CollectionDockingView extends CollectionViewBase {
 
     @action
     onResize = (event: any) => {
-        var cur = this.props.DocumentViewForCollection!.MainContent.current;
+        var cur = this.props.ContainingDocumentView!.MainContent.current;
 
         // bcz: since GoldenLayout isn't a React component itself, we need to notify it to resize when its document container's size has changed
         CollectionDockingView.myLayout.updateSize(cur!.getBoundingClientRect().width, cur!.getBoundingClientRect().height);
@@ -255,7 +255,7 @@ export class CollectionDockingView extends CollectionViewBase {
         const { CollectionFieldKey: fieldKey, DocumentForCollection: Document } = this.props;
         const value: Document[] = Document.GetFieldValue(fieldKey, ListField, []);
         // bcz: not sure why, but I need these to force the flexlayout to update when the collection size changes.
-        var s = this.props.DocumentViewForCollection != undefined ? this.props.DocumentViewForCollection!.ScalingToScreenSpace : 1;
+        var s = this.props.ContainingDocumentView != undefined ? this.props.ContainingDocumentView!.ScalingToScreenSpace : 1;
         var w = Document.GetFieldValue(KeyStore.Width, NumberField, Number(0)) / s;
         var h = Document.GetFieldValue(KeyStore.Height, NumberField, Number(0)) / s;
 
diff --git a/src/views/collections/CollectionFreeFormView.tsx b/src/views/collections/CollectionFreeFormView.tsx
index abc811642..cc907b2cc 100644
--- a/src/views/collections/CollectionFreeFormView.tsx
+++ b/src/views/collections/CollectionFreeFormView.tsx
@@ -39,7 +39,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
             const xOffset = de.data["xOffset"] as number || 0;
             const yOffset = de.data["yOffset"] as number || 0;
             const { scale, translateX, translateY } = Utils.GetScreenTransform(this._canvasRef.current!);
-            let sscale = this.props.DocumentViewForCollection!.props.Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1))
+            let sscale = this.props.ContainingDocumentView!.props.Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1))
             const screenX = de.x - xOffset;
             const screenY = de.y - yOffset;
             const docX = (screenX - translateX) / sscale / scale;
@@ -94,7 +94,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
         if (!e.cancelBubble && this.active) {
             e.preventDefault();
             e.stopPropagation();
-            let currScale: number = this.props.DocumentViewForCollection!.ScalingToScreenSpace;
+            let currScale: number = this.props.ContainingDocumentView!.ScalingToScreenSpace;
             let x = this.props.DocumentForCollection.GetFieldValue(KeyStore.PanX, NumberField, Number(0));
             let y = this.props.DocumentForCollection.GetFieldValue(KeyStore.PanY, NumberField, Number(0));
             this.props.DocumentForCollection.SetFieldValue(KeyStore.PanX, x + (e.pageX - this._lastX) / currScale, NumberField);
@@ -108,7 +108,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
     onPointerWheel = (e: React.WheelEvent): void => {
         e.stopPropagation();
 
-        let { LocalX, Ss, Panxx, Xx, LocalY, Panyy, Yy, ContainerX, ContainerY } = this.props.DocumentViewForCollection!.TransformToLocalPoint(e.pageX, e.pageY);
+        let { LocalX, Ss, Panxx, Xx, LocalY, Panyy, Yy, ContainerX, ContainerY } = this.props.ContainingDocumentView!.TransformToLocalPoint(e.pageX, e.pageY);
 
         var deltaScale = (1 - (e.deltaY / 1000)) * Ss;
 
@@ -198,7 +198,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
 
                         <div className="node-container" ref={this._nodeContainerRef}>
                             {value.map(doc => {
-                                return (<CollectionFreeFormDocumentView key={doc.Id} ContainingCollectionView={this} Document={doc} DocumentView={this.props.DocumentViewForCollection} />);
+                                return (<CollectionFreeFormDocumentView key={doc.Id} ContainingCollectionView={this} Document={doc} DocumentView={undefined} />);
                             })}
                         </div>
                     </div>
diff --git a/src/views/collections/CollectionSchemaView.tsx b/src/views/collections/CollectionSchemaView.tsx
index 19b1434ef..8503aaf1e 100644
--- a/src/views/collections/CollectionSchemaView.tsx
+++ b/src/views/collections/CollectionSchemaView.tsx
@@ -74,9 +74,7 @@ export class CollectionSchemaView extends CollectionViewBase {
             [KS.Title, KS.Data, KS.Author])
         let content;
         if (this.selectedIndex != -1) {
-            content = (<DocumentView Document={children[this.selectedIndex]}
-                DocumentView={undefined}
-                ContainingCollectionView={this} />)
+            content = (<DocumentView Document={children[this.selectedIndex]} DocumentView={undefined} ContainingCollectionView={this} />)
         } else {
             content = <div />
         }
diff --git a/src/views/collections/CollectionViewBase.tsx b/src/views/collections/CollectionViewBase.tsx
index bfded71d9..76145f12b 100644
--- a/src/views/collections/CollectionViewBase.tsx
+++ b/src/views/collections/CollectionViewBase.tsx
@@ -9,11 +9,12 @@ import { ContextMenu } from "../ContextMenu";
 import React = require("react");
 import { DocumentView } from "../nodes/DocumentView";
 import { CollectionDockingView } from "./CollectionDockingView";
+import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView";
 
 
 export interface CollectionViewProps {
-    fieldKey: Key;
-    Document: Document;
+    CollectionFieldKey: Key;
+    DocumentForCollection: Document;
     ContainingDocumentView: Opt<DocumentView>;
 }
 
@@ -22,9 +23,12 @@ export const COLLECTION_BORDER_WIDTH = 2;
 @observer
 export class CollectionViewBase extends React.Component<CollectionViewProps> {
 
+    public static LayoutString(collectionType: string) {
+        return `<${collectionType} DocumentForCollection={Document} CollectionFieldKey={DataKey} ContainingDocumentView={DocumentView}/>`;
+    }
     @computed
     public get active(): boolean {
-        var isSelected = (this.props.ContainingDocumentView != undefined && SelectionManager.IsSelected(this.props.ContainingDocumentView));
+        var isSelected = (this.props.ContainingDocumentView instanceof CollectionFreeFormDocumentView && SelectionManager.IsSelected(this.props.ContainingDocumentView));
         var childSelected = SelectionManager.SelectedDocuments().some(view => view.props.ContainingCollectionView == this);
         var topMost = this.props.ContainingDocumentView != undefined && (
             this.props.ContainingDocumentView.props.ContainingCollectionView == undefined ||
@@ -34,14 +38,14 @@ export class CollectionViewBase extends React.Component<CollectionViewProps> {
     @action
     addDocument = (doc: Document): void => {
         //TODO This won't create the field if it doesn't already exist
-        const value = this.props.Document.GetFieldValue(this.props.fieldKey, ListField, new Array<Document>())
+        const value = this.props.DocumentForCollection.GetFieldValue(this.props.CollectionFieldKey, ListField, new Array<Document>())
         value.push(doc);
     }
 
     @action
     removeDocument = (doc: Document): void => {
         //TODO This won't create the field if it doesn't already exist
-        const value = this.props.Document.GetFieldValue(this.props.fieldKey, ListField, new Array<Document>())
+        const value = this.props.DocumentForCollection.GetFieldValue(this.props.CollectionFieldKey, ListField, new Array<Document>())
         if (value.indexOf(doc) !== -1) {
             value.splice(value.indexOf(doc), 1)
 
diff --git a/src/views/nodes/DocumentView.tsx b/src/views/nodes/DocumentView.tsx
index 9a3783fdc..7b81752ad 100644
--- a/src/views/nodes/DocumentView.tsx
+++ b/src/views/nodes/DocumentView.tsx
@@ -19,8 +19,8 @@ const JsxParser = require('react-jsx-parser').default;//TODO Why does this need
 
 export interface DocumentViewProps {
     Document: Document;
+    DocumentView: Opt<DocumentView>  // needed only to set ContainingDocumentView on CollectionViewProps when invoked from JsxParser -- is there a better way?
     ContainingCollectionView: Opt<CollectionViewBase>;
-    DocumentView: Opt<DocumentView>
 }
 @observer
 export class DocumentView extends React.Component<DocumentViewProps> {
@@ -49,9 +49,9 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     //
     @computed
     public get ScalingToScreenSpace(): number {
-        if (this.props.ContainingCollectionView != undefined && this.props.ContainingCollectionView.props.DocumentViewForCollection != undefined) {
+        if (this.props.ContainingCollectionView != undefined && this.props.ContainingCollectionView.props.ContainingDocumentView != undefined) {
             let ss = this.props.ContainingCollectionView.props.DocumentForCollection.GetFieldValue(KeyStore.Scale, NumberField, Number(1));
-            return this.props.ContainingCollectionView.props.DocumentViewForCollection.ScalingToScreenSpace * ss;
+            return this.props.ContainingCollectionView.props.ContainingDocumentView.ScalingToScreenSpace * ss;
         }
         return 1;
     }
@@ -62,8 +62,8 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     public TransformToLocalPoint(screenX: number, screenY: number) {
         // if this collection view is nested within another collection view, then 
         // first transform the screen point into the parent collection's coordinate space.
-        let { LocalX: parentX, LocalY: parentY } = this.props.ContainingCollectionView != undefined && this.props.ContainingCollectionView.props.DocumentViewForCollection != undefined ?
-            this.props.ContainingCollectionView.props.DocumentViewForCollection.TransformToLocalPoint(screenX, screenY) :
+        let { LocalX: parentX, LocalY: parentY } = this.props.ContainingCollectionView != undefined && this.props.ContainingCollectionView.props.ContainingDocumentView != undefined ?
+            this.props.ContainingCollectionView.props.ContainingDocumentView.TransformToLocalPoint(screenX, screenY) :
             { LocalX: screenX, LocalY: screenY };
         let ContainerX: number = parentX - COLLECTION_BORDER_WIDTH;
         let ContainerY: number = parentY - COLLECTION_BORDER_WIDTH;
@@ -111,7 +111,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
 
         // if this collection view is nested within another collection view, then 
         // first transform the local point into the parent collection's coordinate space.
-        let containingDocView = this.props.ContainingCollectionView != undefined ? this.props.ContainingCollectionView.props.DocumentViewForCollection : undefined;
+        let containingDocView = this.props.ContainingCollectionView != undefined ? this.props.ContainingCollectionView.props.ContainingDocumentView : undefined;
         if (containingDocView != undefined) {
             let ss = containingDocView.props.Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1));
             let panxx = containingDocView.props.Document.GetFieldValue(KeyStore.PanX, NumberField, Number(0)) + COLLECTION_BORDER_WIDTH * ss;
@@ -130,8 +130,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         for (const key of this.layoutKeys) {
             bindings[key.Name + "Key"] = key;
         }
-        if (this.props.DocumentView == undefined)
-            bindings.DocumentView = this;
+        bindings.DocumentView = this;
         for (const key of this.layoutFields) {
             let field = doc.GetField(key);
             if (field) {
-- 
cgit v1.2.3-70-g09d2

