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

---
 src/client/views/collections/CollectionDockingView.tsx | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

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

diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 1c1f6f8b4..05e1ea90a 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -25,7 +25,7 @@ export class CollectionDockingView extends CollectionViewBase {
     private _containerRef = React.createRef<HTMLDivElement>();
     @computed
     private get modelForFlexLayout() {
-        const { CollectionFieldKey: fieldKey, DocumentForCollection: Document } = this.props;
+        const { fieldKey: fieldKey, Document: Document } = this.props;
         const value: Document[] = Document.GetData(fieldKey, ListField, []);
         var docs = value.map(doc => {
             return { type: 'tabset', weight: 50, selected: 0, children: [{ type: "tab", name: doc.Title, component: doc.Id }] };
@@ -40,8 +40,8 @@ export class CollectionDockingView extends CollectionViewBase {
         });
     }
     @computed
-    private get modelForGoldenLayout(): any {
-        const { CollectionFieldKey: fieldKey, DocumentForCollection: Document } = this.props;
+    private get modelForGoldenLayout(): GoldenLayout {
+        const { fieldKey: fieldKey, Document: Document } = this.props;
         const value: Document[] = Document.GetData(fieldKey, ListField, []);
         var docs = value.map(doc => {
             return { type: 'component', componentName: 'documentViewComponent', componentState: { doc: doc, scaling: 1 } };
@@ -92,7 +92,7 @@ export class CollectionDockingView extends CollectionViewBase {
         if (component === "button") {
             return <button>{node.getName()}</button>;
         }
-        const { CollectionFieldKey: fieldKey, DocumentForCollection: Document } = this.props;
+        const { fieldKey: fieldKey, Document: Document } = this.props;
         const value: Document[] = Document.GetData(fieldKey, ListField, []);
         for (var i: number = 0; i < value.length; i++) {
             if (value[i].Id === component) {
@@ -101,7 +101,7 @@ export class CollectionDockingView extends CollectionViewBase {
                     ScreenToLocalTransform={() => Transform.Identity}
                     isTopMost={true}
                     Scaling={1}
-                    ContainingCollectionView={this} DocumentView={undefined} />);
+                    ContainingCollectionView={this} />);
             }
         }
         if (component === "text") {
@@ -262,9 +262,10 @@ export class CollectionDockingView extends CollectionViewBase {
 
 
     render() {
-        const { CollectionFieldKey: fieldKey, DocumentForCollection: Document } = this.props;
+        const { fieldKey: fieldKey, Document: Document } = this.props;
         const value: Document[] = Document.GetData(fieldKey, ListField, []);
         // bcz: not sure why, but I need these to force the flexlayout to update when the collection size changes.
+        // tfs: we should be able to use this.props.ScreenToLocalTransform to get s right?
         var s = this.props.ContainingDocumentView != undefined ? this.props.ContainingDocumentView!.ScalingToScreenSpace : 1;
         var w = Document.GetNumber(KeyStore.Width, 0) / s;
         var h = Document.GetNumber(KeyStore.Height, 0) / s;
@@ -314,7 +315,7 @@ export class RenderClass extends React.Component<DockingProps> {
                     return this.props.CollectionDockingView.props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(scale)
                 }}
                 isTopMost={true}
-                ContainingCollectionView={this.props.CollectionDockingView} DocumentView={undefined} />
+                ContainingCollectionView={this.props.CollectionDockingView} />
 
         if (nativeWidth > 0 && (layout.indexOf("CollectionFreeForm") == -1 || layout.indexOf("AnnotationsKey") != -1)) {
             return <Measure onResize={
-- 
cgit v1.2.3-70-g09d2


From 6d036e9d0a4b6ecbcf63404941e9b192135ffa41 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 19 Feb 2019 09:29:34 -0500
Subject: converted docking collection to use a GoldenLayout layout string for
 its data

---
 src/client/documents/Documents.ts                  |  1 +
 src/client/views/Main.tsx                          |  2 +
 .../views/collections/CollectionDockingView.tsx    | 79 ++++++----------------
 3 files changed, 25 insertions(+), 57 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 72fa608ad..36119e552 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -169,6 +169,7 @@ export namespace Documents {
 
     export function CollectionDocument(documents: Array<Document>, options: DocumentOptions = {}): Document {
         let doc = GetCollectionPrototype().MakeDelegate();
+        Server.AddDocument(doc);
         setupOptions(doc, options);
         doc.Set(KeyStore.Data, new ListField(documents));
         return doc;
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index c3a9f1906..933c904fb 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -76,6 +76,8 @@ document.addEventListener("pointerdown", action(function (e: PointerEvent) {
     // mainNodes.Data.push(doc1);
     // mainNodes.Data.push(doc2);
     mainNodes.Data.push(doc6);
+    var layoutstr = `{"settings":{"hasHeaders":true,"constrainDragToContainer":true,"reorderEnabled":true,"selectionEnabled":true,"popoutWholeStack":false,"blockedPopoutsThrowError":true,"closePopoutsOnUnload":true,"showPopoutIcon":true,"showMaximiseIcon":true,"showCloseIcon":true,"responsiveMode":"onload","tabOverlapAllowance":0,"reorderOnTabMenuClick":true,"tabControlOffset":10},"dimensions":{"borderWidth":5,"borderGrabWidth":15,"minItemHeight":10,"minItemWidth":10,"headerHeight":20,"dragProxyWidth":300,"dragProxyHeight":200},"labels":{"close":"close","maximise":"maximise","minimise":"minimise","popout":"open in new window","popin":"pop in","tabDropdown":"additional tabs"},"content":[{"type":"row","isClosable":true,"reorderEnabled":true,"title":"","content":[{"type":"stack","width":33.333333333333336,"isClosable":true,"reorderEnabled":true,"title":"","activeItemIndex":0,"content":[{"type":"component","componentName":"documentViewComponent","componentState":{"doc":"${doc3.Id}","title":"mini collection","scaling":1},"isClosable":true,"reorderEnabled":true,"title":"documentViewComponent"}]},{"type":"stack","width":33.333333333333336,"isClosable":true,"reorderEnabled":true,"title":"","activeItemIndex":0,"content":[{"type":"component","componentName":"documentViewComponent","componentState":{"doc":"${doc6.Id}","title":"<untitled>","scaling":1},"isClosable":true,"reorderEnabled":true,"title":"documentViewComponent"}]},{"type":"stack","width":16.666666666666668,"isClosable":true,"reorderEnabled":true,"title":"","activeItemIndex":0,"content":[{"type":"component","componentName":"documentViewComponent","componentState":{"doc":"${doc4.Id}","title":"docking collection","scaling":1},"isClosable":true,"reorderEnabled":true,"title":"documentViewComponent"}]},{"type":"stack","isClosable":true,"reorderEnabled":true,"title":"","width":16.666666666666668,"activeItemIndex":0,"content":[{"type":"component","componentName":"documentViewComponent","componentState":{"doc":"${doc4.Id}","title":"hello"},"isClosable":true,"reorderEnabled":true,"title":"documentViewComponent"}]}]}],"isClosable":true,"reorderEnabled":true,"title":"","openPopouts":[],"maximisedItemId":null}`
+    mainContainer.SetText(KeyStore.Data, layoutstr)
 }
 //}
 //);
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 05e1ea90a..4c83186f8 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -16,6 +16,8 @@ import React = require("react");
 import * as ReactDOM from 'react-dom';
 import Measure from "react-measure";
 import { Utils } from "../../../Utils";
+import { FieldId } from "../../../fields/Field";
+import { Server } from "../../Server";
 
 @observer
 export class CollectionDockingView extends CollectionViewBase {
@@ -24,27 +26,15 @@ export class CollectionDockingView extends CollectionViewBase {
     public static LayoutString() { return CollectionViewBase.LayoutString("CollectionDockingView"); }
     private _containerRef = React.createRef<HTMLDivElement>();
     @computed
-    private get modelForFlexLayout() {
-        const { fieldKey: fieldKey, Document: Document } = this.props;
-        const value: Document[] = Document.GetData(fieldKey, ListField, []);
-        var docs = value.map(doc => {
-            return { type: 'tabset', weight: 50, selected: 0, children: [{ type: "tab", name: doc.Title, component: doc.Id }] };
-        });
-        return FlexLayout.Model.fromJson({
-            global: {}, borders: [],
-            layout: {
-                "type": "row",
-                "weight": 100,
-                "children": docs
-            }
-        });
-    }
-    @computed
     private get modelForGoldenLayout(): GoldenLayout {
+        var json = this.props.Document.GetText(KeyStore.Data, "");
+        if (json != "") {
+            return new GoldenLayout(JSON.parse(json))
+        }
         const { fieldKey: fieldKey, Document: Document } = this.props;
         const value: Document[] = Document.GetData(fieldKey, ListField, []);
         var docs = value.map(doc => {
-            return { type: 'component', componentName: 'documentViewComponent', componentState: { doc: doc, scaling: 1 } };
+            return { type: 'component', componentName: 'documentViewComponent', componentState: { doc: doc.Id, title: doc.Title, scaling: 1 } };
         });
         return new GoldenLayout({
             settings: {
@@ -87,28 +77,6 @@ export class CollectionDockingView extends CollectionViewBase {
         }
     }
 
-    flexLayoutFactory = (node: any): any => {
-        var component = node.getComponent();
-        if (component === "button") {
-            return <button>{node.getName()}</button>;
-        }
-        const { fieldKey: fieldKey, Document: Document } = this.props;
-        const value: Document[] = Document.GetData(fieldKey, ListField, []);
-        for (var i: number = 0; i < value.length; i++) {
-            if (value[i].Id === component) {
-                return (<DocumentView key={value[i].Id} Document={value[i]}
-                    AddDocument={this.addDocument} RemoveDocument={this.removeDocument}
-                    ScreenToLocalTransform={() => Transform.Identity}
-                    isTopMost={true}
-                    Scaling={1}
-                    ContainingCollectionView={this} />);
-            }
-        }
-        if (component === "text") {
-            return (<div className="panel">Panel {node.getName()}</div>);
-        }
-    }
-
     public static myLayout: any = null;
 
     private static _dragDiv: any = null;
@@ -119,7 +87,7 @@ export class CollectionDockingView extends CollectionViewBase {
         var newItemConfig = {
             type: 'component',
             componentName: 'documentViewComponent',
-            componentState: { doc: dragDoc, scaling: 1 }
+            componentState: { doc: dragDoc.Id, title: dragDoc.Title, scaling: 1 }
         };
         this._dragElement = dragElement;
         this._dragParent = dragElement.parentElement;
@@ -149,7 +117,7 @@ export class CollectionDockingView extends CollectionViewBase {
         var newItemConfig = {
             type: 'component',
             componentName: 'documentViewComponent',
-            componentState: { doc: document }
+            componentState: { doc: document.Id, title: document.Title }
         };
         CollectionDockingView.myLayout._makeFullScreen = true;
         CollectionDockingView.myLayout.root.contentItems[0].addChild(newItemConfig);
@@ -167,7 +135,7 @@ export class CollectionDockingView extends CollectionViewBase {
         var newItemConfig = {
             type: 'component',
             componentName: 'documentViewComponent',
-            componentState: { doc: document }
+            componentState: { doc: document.Id, title: document.Title }
         }
         let newItemStackConfig = {
             type: 'stack',
@@ -196,6 +164,8 @@ export class CollectionDockingView extends CollectionViewBase {
             newContentItem.config["width"] = 50;
             collayout.parent.callDownwards('setSize');
         }
+        var state = JSON.stringify(CollectionDockingView.myLayout.toConfig());
+        console.log(state);
     }
     goldenLayoutFactory() {
         CollectionDockingView.myLayout = this.modelForGoldenLayout;
@@ -209,7 +179,7 @@ export class CollectionDockingView extends CollectionViewBase {
                 DragManager.Root().removeChild(CollectionDockingView._dragDiv);
                 CollectionDockingView._dragDiv = null;
             }
-            tab.setTitle(tab.contentItem.config.componentState.doc.Title);
+            tab.setTitle(tab.contentItem.config.componentState.title);
             tab.closeElement.off('click') //unbind the current click handler
                 .click(function () {
                     tab.contentItem.remove();
@@ -244,7 +214,7 @@ export class CollectionDockingView extends CollectionViewBase {
                 if (divContainer) {
                     let props: DockingProps = {
                         ContainingDiv: containingDiv,
-                        Document: state.doc,
+                        DocumentId: state.doc,
                         Container: container,
                         CollectionDockingView: me,
                         HtmlElement: divContainer,
@@ -269,12 +239,6 @@ export class CollectionDockingView extends CollectionViewBase {
         var s = this.props.ContainingDocumentView != undefined ? this.props.ContainingDocumentView!.ScalingToScreenSpace : 1;
         var w = Document.GetNumber(KeyStore.Width, 0) / s;
         var h = Document.GetNumber(KeyStore.Height, 0) / s;
-
-        var chooseLayout = () => {
-            if (!CollectionDockingView.UseGoldenLayout)
-                return <FlexLayout.Layout model={this.modelForFlexLayout} factory={this.flexLayoutFactory} />;
-        }
-
         return (
             <div className="collectiondockingview-container" id="menuContainer"
                 onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()} ref={this._containerRef}
@@ -283,16 +247,14 @@ export class CollectionDockingView extends CollectionViewBase {
                     height: CollectionDockingView.UseGoldenLayout || s > 1 ? "100%" : h - 2 * COLLECTION_BORDER_WIDTH,
                     borderStyle: "solid",
                     borderWidth: `${COLLECTION_BORDER_WIDTH}px`,
-                }} >
-                {chooseLayout()}
-            </div>
+                }} />
         );
     }
 }
 
 interface DockingProps {
     ContainingDiv: string,
-    Document: Document,
+    DocumentId: FieldId,
     Container: any,
     HtmlElement: HTMLElement,
     CollectionDockingView: CollectionDockingView,
@@ -302,11 +264,14 @@ export class RenderClass extends React.Component<DockingProps> {
     @observable
     private _parentScaling = 1; // used to transfer the dimensions of the content pane in the DOM to the ParentScaling prop of the DocumentView
 
+    @computed
+    private get Document() { return Server.GetField(this.props.DocumentId) as Document }
+
     render() {
-        let nativeWidth = this.props.Document.GetNumber(KeyStore.NativeWidth, 0);
-        var layout = this.props.Document.GetText(KeyStore.Layout, "");
+        let nativeWidth = this.Document.GetNumber(KeyStore.NativeWidth, 0);
+        var layout = this.Document.GetText(KeyStore.Layout, "");
         var content =
-            <DocumentView key={this.props.Document.Id} Document={this.props.Document}
+            <DocumentView key={this.Document.Id} Document={this.Document}
                 AddDocument={this.props.CollectionDockingView.addDocument}
                 RemoveDocument={this.props.CollectionDockingView.removeDocument}
                 Scaling={this._parentScaling}
-- 
cgit v1.2.3-70-g09d2


From 49e946d57c5dc0f21a6d6a98436429a353c96907 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 19 Feb 2019 11:13:22 -0500
Subject: added layout saving/loading to collectiondockingview & cleaned up to
 use react-component

---
 src/client/documents/Documents.ts                  |   4 +-
 src/client/views/Main.tsx                          |  82 +++---
 .../views/collections/CollectionDockingView.tsx    | 303 +++++++++------------
 src/client/views/nodes/DocumentView.tsx            |   8 +-
 4 files changed, 174 insertions(+), 223 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 36119e552..f954b37a8 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -107,10 +107,10 @@ export namespace Documents {
         return dockProto;
     }
 
-    export function DockDocument(documents: Array<Document>, options: DocumentOptions = {}): Document {
+    export function DockDocument(config: string, options: DocumentOptions = {}): Document {
         let doc = GetDockPrototype().MakeDelegate();
         setupOptions(doc, options);
-        doc.Set(KeyStore.Data, new ListField(documents));
+        doc.SetText(KeyStore.Data, config);
         return doc;
     }
 
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 933c904fb..a86fdb9b0 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -14,6 +14,7 @@ import { ContextMenu } from './ContextMenu';
 import { DocumentView } from './nodes/DocumentView';
 import { ImageField } from '../../fields/ImageField';
 import { Transform } from '../util/Transform';
+import { CollectionDockingView } from './collections/CollectionDockingView';
 
 
 configure({
@@ -21,9 +22,6 @@ configure({
 });
 
 const mainNodeCollection = new Array<Document>();
-let mainContainer = Documents.DockDocument(mainNodeCollection, {
-    x: 0, y: 0, title: "main container"
-})
 
 window.addEventListener("drop", function (e) {
     e.preventDefault();
@@ -38,49 +36,41 @@ document.addEventListener("pointerdown", action(function (e: PointerEvent) {
 }), true)
 
 
-//runInAction(() => 
-{
-    let doc1 = Documents.TextDocument({ title: "hello", width: 400, height: 300 });
-    let doc2 = doc1.MakeDelegate();
-    doc2.Set(KS.X, new NumberField(150));
-    doc2.Set(KS.Y, new NumberField(20));
-    let doc3 = Documents.ImageDocument("https://psmag.com/.image/t_share/MTMyNzc2NzM1MDY1MjgzMDM4/shutterstock_151341212jpg.jpg", {
-        x: 450, y: 100, title: "dog", width: 606, height: 386, nativeWidth: 606, nativeHeight: 386
-    });
-    //doc3.Set(KeyStore.Data, new ImageField);
-    const schemaDocs = Array.from(Array(5).keys()).map(v => Documents.ImageDocument("https://psmag.com/.image/t_share/MTMyNzc2NzM1MDY1MjgzMDM4/shutterstock_151341212jpg.jpg", {
-        x: 50 + 100 * v, y: 50, width: 100, height: 100, title: "cat" + v, nativeWidth: 606, nativeHeight: 386
-    }));
-    schemaDocs.push(doc3);
-    schemaDocs[0].SetData(KS.Author, "Tyler", TextField);
-    schemaDocs[4].SetData(KS.Author, "Bob", TextField);
-    schemaDocs.push(doc2);
-    const doc7 = Documents.SchemaDocument(schemaDocs)
-    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 = [doc3, doc4, doc2];
-    let doc6 = Documents.CollectionDocument(docset2, {
-        x: 350, y: 100, width: 600, height: 600, title: "docking collection"
-    });
-    let mainNodes = mainContainer.GetOrCreate<ListField<Document>>(KeyStore.Data, ListField);
-    // mainNodes.Data.push(doc6);
-    // mainNodes.Data.push(doc2);
-    mainNodes.Data.push(doc4);
-    mainNodes.Data.push(doc3);
-    // mainNodes.Data.push(doc5);
-    // mainNodes.Data.push(doc1);
-    // mainNodes.Data.push(doc2);
-    mainNodes.Data.push(doc6);
-    var layoutstr = `{"settings":{"hasHeaders":true,"constrainDragToContainer":true,"reorderEnabled":true,"selectionEnabled":true,"popoutWholeStack":false,"blockedPopoutsThrowError":true,"closePopoutsOnUnload":true,"showPopoutIcon":true,"showMaximiseIcon":true,"showCloseIcon":true,"responsiveMode":"onload","tabOverlapAllowance":0,"reorderOnTabMenuClick":true,"tabControlOffset":10},"dimensions":{"borderWidth":5,"borderGrabWidth":15,"minItemHeight":10,"minItemWidth":10,"headerHeight":20,"dragProxyWidth":300,"dragProxyHeight":200},"labels":{"close":"close","maximise":"maximise","minimise":"minimise","popout":"open in new window","popin":"pop in","tabDropdown":"additional tabs"},"content":[{"type":"row","isClosable":true,"reorderEnabled":true,"title":"","content":[{"type":"stack","width":33.333333333333336,"isClosable":true,"reorderEnabled":true,"title":"","activeItemIndex":0,"content":[{"type":"component","componentName":"documentViewComponent","componentState":{"doc":"${doc3.Id}","title":"mini collection","scaling":1},"isClosable":true,"reorderEnabled":true,"title":"documentViewComponent"}]},{"type":"stack","width":33.333333333333336,"isClosable":true,"reorderEnabled":true,"title":"","activeItemIndex":0,"content":[{"type":"component","componentName":"documentViewComponent","componentState":{"doc":"${doc6.Id}","title":"<untitled>","scaling":1},"isClosable":true,"reorderEnabled":true,"title":"documentViewComponent"}]},{"type":"stack","width":16.666666666666668,"isClosable":true,"reorderEnabled":true,"title":"","activeItemIndex":0,"content":[{"type":"component","componentName":"documentViewComponent","componentState":{"doc":"${doc4.Id}","title":"docking collection","scaling":1},"isClosable":true,"reorderEnabled":true,"title":"documentViewComponent"}]},{"type":"stack","isClosable":true,"reorderEnabled":true,"title":"","width":16.666666666666668,"activeItemIndex":0,"content":[{"type":"component","componentName":"documentViewComponent","componentState":{"doc":"${doc4.Id}","title":"hello"},"isClosable":true,"reorderEnabled":true,"title":"documentViewComponent"}]}]}],"isClosable":true,"reorderEnabled":true,"title":"","openPopouts":[],"maximisedItemId":null}`
-    mainContainer.SetText(KeyStore.Data, layoutstr)
-}
-//}
-//);
+let doc1 = Documents.TextDocument({ title: "hello", width: 400, height: 300 });
+let doc2 = doc1.MakeDelegate();
+doc2.Set(KS.X, new NumberField(150));
+doc2.Set(KS.Y, new NumberField(20));
+let doc3 = Documents.ImageDocument("https://psmag.com/.image/t_share/MTMyNzc2NzM1MDY1MjgzMDM4/shutterstock_151341212jpg.jpg", {
+    x: 450, y: 100, title: "dog", width: 606, height: 386, nativeWidth: 606, nativeHeight: 386
+});
+//doc3.Set(KeyStore.Data, new ImageField);
+const schemaDocs = Array.from(Array(5).keys()).map(v => Documents.ImageDocument("https://psmag.com/.image/t_share/MTMyNzc2NzM1MDY1MjgzMDM4/shutterstock_151341212jpg.jpg", {
+    x: 50 + 100 * v, y: 50, width: 100, height: 100, title: "cat" + v, nativeWidth: 606, nativeHeight: 386
+}));
+schemaDocs.push(doc3);
+schemaDocs[0].SetData(KS.Author, "Tyler", TextField);
+schemaDocs[4].SetData(KS.Author, "Bob", TextField);
+schemaDocs.push(doc2);
+const doc7 = Documents.SchemaDocument(schemaDocs)
+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 = [doc3, doc4, doc2];
+let doc6 = Documents.CollectionDocument(docset2, {
+    x: 350, y: 100, width: 600, height: 600, title: "docking collection"
+});
+
+var docs = [doc4, doc3, doc6].map(doc => CollectionDockingView.makeDocumentConfig(doc));
+var config = {
+    settings: { selectionEnabled: false }, content: [{ type: 'row', content: docs }]
+};
+let mainContainer = Documents.DockDocument(JSON.stringify(config), {
+    x: 0, y: 0, title: "main container"
+})
 
 ReactDOM.render((
     <div style={{ position: "absolute", width: "100%", height: "100%" }}>
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 4c83186f8..9cc92712e 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -1,4 +1,3 @@
-import FlexLayout from "flexlayout-react";
 import * as GoldenLayout from "golden-layout";
 import 'golden-layout/src/css/goldenlayout-base.css';
 import 'golden-layout/src/css/goldenlayout-dark-theme.css';
@@ -8,7 +7,6 @@ import { Document } from "../../../fields/Document";
 import { KeyStore } from "../../../fields/Key";
 import { ListField } from "../../../fields/ListField";
 import { DragManager } from "../../util/DragManager";
-import { Transform } from "../../util/Transform";
 import { DocumentView } from "../nodes/DocumentView";
 import "./CollectionDockingView.scss";
 import { CollectionViewBase, CollectionViewProps, COLLECTION_BORDER_WIDTH } from "./CollectionViewBase";
@@ -22,73 +20,37 @@ import { Server } from "../../Server";
 @observer
 export class CollectionDockingView extends CollectionViewBase {
 
-    private static UseGoldenLayout = true;
+    public static Instance: CollectionDockingView;
     public static LayoutString() { return CollectionViewBase.LayoutString("CollectionDockingView"); }
-    private _containerRef = React.createRef<HTMLDivElement>();
-    @computed
-    private get modelForGoldenLayout(): GoldenLayout {
-        var json = this.props.Document.GetText(KeyStore.Data, "");
-        if (json != "") {
-            return new GoldenLayout(JSON.parse(json))
-        }
-        const { fieldKey: fieldKey, Document: Document } = this.props;
-        const value: Document[] = Document.GetData(fieldKey, ListField, []);
-        var docs = value.map(doc => {
-            return { type: 'component', componentName: 'documentViewComponent', componentState: { doc: doc.Id, title: doc.Title, scaling: 1 } };
-        });
-        return new GoldenLayout({
-            settings: {
-                selectionEnabled: true
-            }, content: [{ type: 'row', content: docs }]
-        });
-    }
-    constructor(props: CollectionViewProps) {
-        super(props);
-    }
-
-    componentDidMount: () => void = () => {
-        if (this._containerRef.current && CollectionDockingView.UseGoldenLayout) {
-            this.goldenLayoutFactory();
-            window.addEventListener('resize', this.onResize); // bcz: would rather add this event to the parent node, but resize events only come from Window
+    public static makeDocumentConfig(document: Document) {
+        return {
+            type: 'react-component',
+            component: 'DocumentFrameRenderer',
+            title: document.Title,
+            props: {
+                documentId: document.Id,
+                CollectionDockingView: CollectionDockingView.Instance,
+            }
         }
     }
-    componentWillUnmount: () => void = () => {
-        window.removeEventListener('resize', this.onResize);
-    }
-    private nextId = (function () { var _next_id = 0; return function () { return _next_id++; } })();
-
-    @action
-    onResize = (event: any) => {
-        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);
-    }
+    private _goldenLayout: any = null;
+    private _dragDiv: any = null;
+    private _dragParent: HTMLElement | null = null;
+    private _dragElement: HTMLDivElement | undefined;
+    private _dragFakeElement: HTMLDivElement | undefined;
+    private _containerRef = React.createRef<HTMLDivElement>();
+    private _makeFullScreen: boolean = false;
+    private _maximizedStack: any = null;
 
-    @action
-    onPointerDown = (e: React.PointerEvent): void => {
-        if (e.button === 2 && this.active) {
-            e.stopPropagation();
-            e.preventDefault();
-        } else {
-            if (e.buttons === 1 && this.active) {
-                e.stopPropagation();
-            }
-        }
+    constructor(props: CollectionViewProps) {
+        super(props);
+        CollectionDockingView.Instance = this;
+        (window as any).React = React;
+        (window as any).ReactDOM = ReactDOM;
     }
 
-    public static myLayout: any = null;
-
-    private static _dragDiv: any = null;
-    private static _dragParent: HTMLElement | null = null;
-    private static _dragElement: HTMLDivElement;
-    private static _dragFakeElement: HTMLDivElement;
-    public static StartOtherDrag(dragElement: HTMLDivElement, dragDoc: Document) {
-        var newItemConfig = {
-            type: 'component',
-            componentName: 'documentViewComponent',
-            componentState: { doc: dragDoc.Id, title: dragDoc.Title, scaling: 1 }
-        };
+    public StartOtherDrag(dragElement: HTMLDivElement, dragDoc: Document) {
         this._dragElement = dragElement;
         this._dragParent = dragElement.parentElement;
         // bcz: we want to copy this document into the header, not move it there.
@@ -98,7 +60,7 @@ export class CollectionDockingView extends CollectionViewBase {
         this._dragDiv = document.createElement("div");
         this._dragDiv.style.opacity = 0;
         DragManager.Root().appendChild(this._dragDiv);
-        CollectionDockingView.myLayout.createDragSource(this._dragDiv, newItemConfig);
+        this._goldenLayout.createDragSource(this._dragDiv, CollectionDockingView.makeDocumentConfig(dragDoc));
 
         //   - add our document to that div so that GoldenLayout will get the move events its listening for
         this._dragDiv.appendChild(this._dragElement);
@@ -111,40 +73,29 @@ export class CollectionDockingView extends CollectionViewBase {
         // all of this must be undone when the document has been dropped (see tabCreated)
     }
 
-    _makeFullScreen: boolean = false;
-    _maximizedStack: any = null;
-    public static OpenFullScreen(document: Document) {
-        var newItemConfig = {
-            type: 'component',
-            componentName: 'documentViewComponent',
-            componentState: { doc: document.Id, title: document.Title }
-        };
-        CollectionDockingView.myLayout._makeFullScreen = true;
-        CollectionDockingView.myLayout.root.contentItems[0].addChild(newItemConfig);
+    public OpenFullScreen(document: Document) {
+        this._makeFullScreen = true;
+        this._goldenLayout.root.contentItems[0].addChild(CollectionDockingView.makeDocumentConfig(document));
     }
-    public static CloseFullScreen() {
-        if (CollectionDockingView.myLayout._maximizedStack != null) {
-            CollectionDockingView.myLayout._maximizedStack.header.controlsContainer.find('.lm_close').click();
-            CollectionDockingView.myLayout._maximizedStack = null;
+    public CloseFullScreen() {
+        if (this._maximizedStack) {
+            this._maximizedStack.header.controlsContainer.find('.lm_close').click();
+            this._maximizedStack = null;
         }
     }
+
     //
     //  Creates a vertical split on the right side of the docking view, and then adds the Document to that split
     //
-    public static AddRightSplit(document: Document) {
-        var newItemConfig = {
-            type: 'component',
-            componentName: 'documentViewComponent',
-            componentState: { doc: document.Id, title: document.Title }
-        }
+    public AddRightSplit(document: Document) {
         let newItemStackConfig = {
             type: 'stack',
-            content: [newItemConfig]
+            content: [CollectionDockingView.makeDocumentConfig(document)]
         };
-        var newContentItem = new CollectionDockingView.myLayout._typeToItem[newItemStackConfig.type](CollectionDockingView.myLayout, newItemStackConfig, parent);
+        var newContentItem = new this._goldenLayout._typeToItem[newItemStackConfig.type](this._goldenLayout, newItemStackConfig, parent);
 
-        if (CollectionDockingView.myLayout.root.contentItems[0].isRow) {
-            var rowlayout = CollectionDockingView.myLayout.root.contentItems[0];
+        if (this._goldenLayout.root.contentItems[0].isRow) {
+            var rowlayout = this._goldenLayout.root.contentItems[0];
             var lastRowItem = rowlayout.contentItems[rowlayout.contentItems.length - 1];
 
             lastRowItem.config["width"] *= 0.5;
@@ -153,8 +104,8 @@ export class CollectionDockingView extends CollectionViewBase {
             rowlayout.callDownwards('setSize');
         }
         else {
-            var collayout = CollectionDockingView.myLayout.root.contentItems[0];
-            var newRow = collayout.layoutManager.createContentItem({ type: "row" }, CollectionDockingView.myLayout);
+            var collayout = this._goldenLayout.root.contentItems[0];
+            var newRow = collayout.layoutManager.createContentItem({ type: "row" }, this._goldenLayout);
             collayout.parent.replaceChild(collayout, newRow);
 
             newRow.addChild(newContentItem, undefined, true);
@@ -164,70 +115,75 @@ export class CollectionDockingView extends CollectionViewBase {
             newContentItem.config["width"] = 50;
             collayout.parent.callDownwards('setSize');
         }
-        var state = JSON.stringify(CollectionDockingView.myLayout.toConfig());
-        console.log(state);
     }
-    goldenLayoutFactory() {
-        CollectionDockingView.myLayout = this.modelForGoldenLayout;
 
-        var layout = CollectionDockingView.myLayout;
-        CollectionDockingView.myLayout.on('tabCreated', function (tab: any) {
-            if (CollectionDockingView._dragDiv) {
-                CollectionDockingView._dragDiv.removeChild(CollectionDockingView._dragElement);
-                CollectionDockingView._dragParent!.removeChild(CollectionDockingView._dragFakeElement);
-                CollectionDockingView._dragParent!.appendChild(CollectionDockingView._dragElement);
-                DragManager.Root().removeChild(CollectionDockingView._dragDiv);
-                CollectionDockingView._dragDiv = null;
+    componentDidMount: () => void = () => {
+        if (this._containerRef.current) {
+
+            this._goldenLayout = new GoldenLayout(JSON.parse(this.props.Document.GetText(KeyStore.Data, "")));
+            this._goldenLayout.on('tabCreated', this.tabCreated);
+            this._goldenLayout.on('stackCreated', this.stackCreated);
+            this._goldenLayout.registerComponent('DocumentFrameRenderer', DockedFrameRenderer);
+            this._goldenLayout.container = this._containerRef.current;
+            this._goldenLayout.init();
+
+            window.addEventListener('resize', this.onResize); // bcz: would rather add this event to the parent node, but resize events only come from Window
+        }
+    }
+    componentWillUnmount: () => void = () => {
+        window.removeEventListener('resize', this.onResize);
+    }
+    @action
+    onResize = (event: any) => {
+        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
+        this._goldenLayout.updateSize(cur!.getBoundingClientRect().width, cur!.getBoundingClientRect().height);
+    }
+
+    @action
+    onPointerDown = (e: React.PointerEvent): void => {
+        if (e.button === 2 && this.active) {
+            e.stopPropagation();
+            e.preventDefault();
+        } else {
+            if (e.buttons === 1 && this.active) {
+                e.stopPropagation();
             }
-            tab.setTitle(tab.contentItem.config.componentState.title);
-            tab.closeElement.off('click') //unbind the current click handler
-                .click(function () {
-                    tab.contentItem.remove();
-                });
-        });
+        }
+    }
 
-        CollectionDockingView.myLayout.on('stackCreated', function (stack: any) {
-            if (CollectionDockingView.myLayout._makeFullScreen) {
-                CollectionDockingView.myLayout._maximizedStack = stack;
-                CollectionDockingView.myLayout._maxstack = stack.header.controlsContainer.find('.lm_maximise');
+    tabCreated = (tab: any) => {
+        {
+            if (this._dragDiv) {
+                this._dragDiv.removeChild(this._dragElement);
+                this._dragParent!.removeChild(this._dragFakeElement!);
+                this._dragParent!.appendChild(this._dragElement!);
+                DragManager.Root().removeChild(this._dragDiv);
+                this._dragDiv = null;
             }
-            //stack.header.controlsContainer.find('.lm_popout').hide();
-            stack.header.controlsContainer.find('.lm_close') //get the close icon
-                .off('click') //unbind the current click handler
+            //tab.setTitle(tab.contentItem.config.componentState.title);
+            tab.closeElement.off('click') //unbind the current click handler
                 .click(function () {
-                    //if (confirm('really close this?')) {
-                    stack.remove();
-                    //}
+                    tab.contentItem.remove();
                 });
-        });
+        }
+    }
 
-        var me = this;
-        CollectionDockingView.myLayout.registerComponent('documentViewComponent', function (container: any, state: any) {
-            // bcz: this is crufty
-            // calling html() causes a div tag to be added in the DOM with id 'containingDiv'. 
-            // Apparently, we need to wait to allow a live html div element to actually be instantiated.
-            // After a timeout, we lookup the live html div element and add our React DocumentView to it.
-            var containingDiv = "component_" + me.nextId();
-            container.getElement().html("<div id='" + containingDiv + "'></div>");
-            setTimeout(function () {
-                let divContainer = document.getElementById(containingDiv) as HTMLDivElement;
-                if (divContainer) {
-                    let props: DockingProps = {
-                        ContainingDiv: containingDiv,
-                        DocumentId: state.doc,
-                        Container: container,
-                        CollectionDockingView: me,
-                        HtmlElement: divContainer,
-                    }
-                    ReactDOM.render((<RenderClass {...props} />), divContainer);
-                    if (CollectionDockingView.myLayout._maxstack) {
-                        CollectionDockingView.myLayout._maxstack.click();
-                    }
-                }
-            }, 0);
-        });
-        CollectionDockingView.myLayout.container = this._containerRef.current;
-        CollectionDockingView.myLayout.init();
+    stackCreated = (stack: any) => {
+        if (this._makeFullScreen) {
+            this._maximizedStack = stack;
+            setTimeout(function () { stack.header.controlsContainer.find('.lm_maximise').click() }, 10);
+            this._makeFullScreen = false;
+        }
+        //stack.header.controlsContainer.find('.lm_popout').hide();
+        stack.header.controlsContainer.find('.lm_close') //get the close icon
+            .off('click') //unbind the current click handler
+            .click(function () {
+                //if (confirm('really close this?')) {
+                stack.remove();
+                //}
+            });
     }
 
 
@@ -243,8 +199,8 @@ export class CollectionDockingView extends CollectionViewBase {
             <div className="collectiondockingview-container" id="menuContainer"
                 onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()} ref={this._containerRef}
                 style={{
-                    width: CollectionDockingView.UseGoldenLayout || s > 1 ? "100%" : w - 2 * COLLECTION_BORDER_WIDTH,
-                    height: CollectionDockingView.UseGoldenLayout || s > 1 ? "100%" : h - 2 * COLLECTION_BORDER_WIDTH,
+                    width: "100%",
+                    height: "100%",
                     borderStyle: "solid",
                     borderWidth: `${COLLECTION_BORDER_WIDTH}px`,
                 }} />
@@ -252,43 +208,48 @@ export class CollectionDockingView extends CollectionViewBase {
     }
 }
 
-interface DockingProps {
-    ContainingDiv: string,
-    DocumentId: FieldId,
-    Container: any,
-    HtmlElement: HTMLElement,
+interface DockedFrameProps {
+    documentId: FieldId,
     CollectionDockingView: CollectionDockingView,
 }
 @observer
-export class RenderClass extends React.Component<DockingProps> {
+export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
+
+    private _mainCont = React.createRef<HTMLDivElement>();
+    constructor(props: any) {
+        super(props);
+    }
+
     @observable
     private _parentScaling = 1; // used to transfer the dimensions of the content pane in the DOM to the ParentScaling prop of the DocumentView
 
     @computed
-    private get Document() { return Server.GetField(this.props.DocumentId) as Document }
+    private get Document() { return Server.GetField(this.props.documentId) as Document }
 
     render() {
         let nativeWidth = this.Document.GetNumber(KeyStore.NativeWidth, 0);
         var layout = this.Document.GetText(KeyStore.Layout, "");
         var content =
-            <DocumentView key={this.Document.Id} Document={this.Document}
-                AddDocument={this.props.CollectionDockingView.addDocument}
-                RemoveDocument={this.props.CollectionDockingView.removeDocument}
-                Scaling={this._parentScaling}
-                ScreenToLocalTransform={() => {
-                    let { scale, translateX, translateY } = Utils.GetScreenTransform(this.props.HtmlElement);
-                    return this.props.CollectionDockingView.props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(scale)
-                }}
-                isTopMost={true}
-                ContainingCollectionView={this.props.CollectionDockingView} />
-
-        if (nativeWidth > 0 && (layout.indexOf("CollectionFreeForm") == -1 || layout.indexOf("AnnotationsKey") != -1)) {
-            return <Measure onResize={
-                action((r: any) => this._parentScaling = nativeWidth > 0 ? r.entry.width / nativeWidth : 1)}
-            >
-                {({ measureRef }) => <div ref={measureRef}> {content} </div>}
+            <div ref={this._mainCont}>
+                <DocumentView key={this.Document.Id} Document={this.Document}
+                    AddDocument={undefined}
+                    RemoveDocument={undefined}
+                    Scaling={this._parentScaling}
+                    ScreenToLocalTransform={() => {
+                        let { scale, translateX, translateY } = Utils.GetScreenTransform(this._mainCont.current!);
+                        var props = this.props.CollectionDockingView ? this.props.CollectionDockingView.props : CollectionDockingView.Instance.props;
+                        return props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(scale)
+                    }}
+                    isTopMost={true}
+                    ContainingCollectionView={this.props.CollectionDockingView} />
+            </div>
+
+        if (nativeWidth > 0 &&
+            (layout.indexOf("CollectionFreeForm") == -1 || layout.indexOf("AnnotationsKey") != -1)) { // contents of documents should be scaled if document is not a freeform view, or if the freeformview is an annotation layer (presumably on a document that is not a freeformview)
+            return <Measure onResize={action((r: any) => this._parentScaling = nativeWidth > 0 ? r.entry.width / nativeWidth : 1)}>
+                {({ measureRef }) => <div ref={measureRef}>  {content} </div>}
             </Measure>
         }
-        return <div> {content} </div>
+        return content
     }
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 14268c644..d1fd6fb22 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -82,7 +82,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         this._downY = e.clientY;
         var me = this;
         if (e.shiftKey && e.buttons === 1) {
-            CollectionDockingView.StartOtherDrag(this._mainCont.current!, this.props.Document);
+            CollectionDockingView.Instance.StartOtherDrag(this._mainCont.current!, this.props.Document);
             e.stopPropagation();
             return;
         }
@@ -144,7 +144,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     }
 
     openRight = (e: React.MouseEvent): void => {
-        CollectionDockingView.AddRightSplit(this.props.Document);
+        CollectionDockingView.Instance.AddRightSplit(this.props.Document);
     }
 
     deleteClicked = (e: React.MouseEvent): void => {
@@ -154,14 +154,14 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     }
     @action
     fullScreenClicked = (e: React.MouseEvent): void => {
-        CollectionDockingView.OpenFullScreen(this.props.Document);
+        CollectionDockingView.Instance.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();
+        CollectionDockingView.Instance.CloseFullScreen();
         ContextMenu.Instance.clearItems();
         ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked })
         ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15)
-- 
cgit v1.2.3-70-g09d2


From 39c6ba3292467979e310f3b577041c2f5e38273f Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 19 Feb 2019 11:33:26 -0500
Subject: fixed selection problem

---
 src/client/views/collections/CollectionDockingView.tsx    | 2 +-
 src/client/views/collections/CollectionViewBase.tsx       | 2 +-
 src/client/views/nodes/CollectionFreeFormDocumentView.tsx | 2 +-
 src/client/views/nodes/DocumentView.tsx                   | 1 -
 4 files changed, 3 insertions(+), 4 deletions(-)

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

diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 9cc92712e..47ed25fa3 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -238,7 +238,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
                     ScreenToLocalTransform={() => {
                         let { scale, translateX, translateY } = Utils.GetScreenTransform(this._mainCont.current!);
                         var props = this.props.CollectionDockingView ? this.props.CollectionDockingView.props : CollectionDockingView.Instance.props;
-                        return props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(scale)
+                        return props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(scale / this._parentScaling)
                     }}
                     isTopMost={true}
                     ContainingCollectionView={this.props.CollectionDockingView} />
diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx
index 5dd10722d..1e20da8d2 100644
--- a/src/client/views/collections/CollectionViewBase.tsx
+++ b/src/client/views/collections/CollectionViewBase.tsx
@@ -37,7 +37,7 @@ export class CollectionViewBase extends React.Component<CollectionViewProps> {
     }
     @computed
     public get active(): boolean {
-        var isSelected = (this.props.ContainingDocumentView instanceof CollectionFreeFormDocumentView && SelectionManager.IsSelected(this.props.ContainingDocumentView));
+        var isSelected = (this.props.ContainingDocumentView && SelectionManager.IsSelected(this.props.ContainingDocumentView));
         var childSelected = SelectionManager.SelectedDocuments().some(view => view.props.ContainingCollectionView == this);
         var topMost = this.props.isTopMost;
         return isSelected || childSelected || topMost;
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 57527076b..2eb0c5857 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -92,7 +92,7 @@ export class CollectionFreeFormDocumentView extends React.Component<DocumentView
                 backgroundColor: "transparent"
             }} >
 
-                <DocumentView {...this.props} Scaling={this.width / this.nativeWidth} ScreenToLocalTransform={this.getTransform} />
+                <DocumentView {...this.props} Scaling={parentScaling} ScreenToLocalTransform={this.getTransform} />
             </div>
         );
     }
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index d1fd6fb22..f8770f020 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -80,7 +80,6 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     onPointerDown = (e: React.PointerEvent): void => {
         this._downX = e.clientX;
         this._downY = e.clientY;
-        var me = this;
         if (e.shiftKey && e.buttons === 1) {
             CollectionDockingView.Instance.StartOtherDrag(this._mainCont.current!, this.props.Document);
             e.stopPropagation();
-- 
cgit v1.2.3-70-g09d2


From 02db8b435396f3b6ea605ce327828f02b41080ef Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 19 Feb 2019 13:10:56 -0500
Subject: fixed circular reference for json docking views

---
 src/client/views/collections/CollectionDockingView.tsx | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

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

diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 47ed25fa3..885a4bece 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -28,8 +28,7 @@ export class CollectionDockingView extends CollectionViewBase {
             component: 'DocumentFrameRenderer',
             title: document.Title,
             props: {
-                documentId: document.Id,
-                CollectionDockingView: CollectionDockingView.Instance,
+                documentId: document.Id
             }
         }
     }
@@ -210,7 +209,6 @@ export class CollectionDockingView extends CollectionViewBase {
 
 interface DockedFrameProps {
     documentId: FieldId,
-    CollectionDockingView: CollectionDockingView,
 }
 @observer
 export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
@@ -224,7 +222,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
     private _parentScaling = 1; // used to transfer the dimensions of the content pane in the DOM to the ParentScaling prop of the DocumentView
 
     @computed
-    private get Document() { return Server.GetField(this.props.documentId) as Document }
+    private get Document() { return Server.GetField(this.props.documentId, () => { }) as Document }
 
     render() {
         let nativeWidth = this.Document.GetNumber(KeyStore.NativeWidth, 0);
@@ -237,11 +235,11 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
                     Scaling={this._parentScaling}
                     ScreenToLocalTransform={() => {
                         let { scale, translateX, translateY } = Utils.GetScreenTransform(this._mainCont.current!);
-                        var props = this.props.CollectionDockingView ? this.props.CollectionDockingView.props : CollectionDockingView.Instance.props;
+                        var props = CollectionDockingView.Instance.props;
                         return props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(scale / this._parentScaling)
                     }}
                     isTopMost={true}
-                    ContainingCollectionView={this.props.CollectionDockingView} />
+                    ContainingCollectionView={undefined} />
             </div>
 
         if (nativeWidth > 0 &&
-- 
cgit v1.2.3-70-g09d2


From 9740d8e9879d95a984a842cf382260bb5572b8ef Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 19 Feb 2019 16:00:41 -0500
Subject: clean up a bit.

---
 src/client/Server.ts                               | 14 --------
 .../views/collections/CollectionDockingView.tsx    | 38 ++++++++++++----------
 src/client/views/nodes/DocumentView.tsx            | 17 ++--------
 src/fields/Document.ts                             |  4 +--
 4 files changed, 24 insertions(+), 49 deletions(-)

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

diff --git a/src/client/Server.ts b/src/client/Server.ts
index 76f182e41..3e61729ab 100644
--- a/src/client/Server.ts
+++ b/src/client/Server.ts
@@ -60,21 +60,7 @@ export class Server {
         });
     }
 
-    static times = 0; // hack for testing
     public static GetDocumentField(doc: Document, key: Key) {
-        // let keyId: string = element[0]
-        // let valueId: string = element[1]
-        // Server.GetField(keyId, (key: Field) => {
-        //     if (key instanceof Key) {
-        //         Server.GetField(valueId, (field: Field) => {
-        //             console.log(field)
-        //             doc.Set(key as Key, field)
-        //         })
-        //     }
-        //     else {
-        //         console.log("how did you get a key that isnt a key wtf")
-        //     }
-        // })
         let field = doc._proxies.get(key.Id);
         if (field) {
             this.GetField(field,
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 41fad9dac..abba0a6ae 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -1,7 +1,7 @@
 import * as GoldenLayout from "golden-layout";
 import 'golden-layout/src/css/goldenlayout-base.css';
 import 'golden-layout/src/css/goldenlayout-dark-theme.css';
-import { action, computed, observable, reaction } from "mobx";
+import { action, computed, observable, reaction, trace } from "mobx";
 import { DragManager } from "../../util/DragManager";
 import { DocumentView } from "../nodes/DocumentView";
 import { Document } from "../../../fields/Document";
@@ -43,6 +43,8 @@ export class CollectionDockingView extends CollectionViewBase {
     private _containerRef = React.createRef<HTMLDivElement>();
     private _makeFullScreen: boolean = false;
     private _maximizedStack: any = null;
+    private _pointerIsDown = false; // used to defer updating the document's layout state Data
+    private _deferredLayoutChange = ""; // the last deferred state change made that needs to be flushed on pointer up
 
     constructor(props: CollectionViewProps) {
         super(props);
@@ -131,13 +133,9 @@ export class CollectionDockingView extends CollectionViewBase {
     }
     componentDidMount: () => void = () => {
         if (this._containerRef.current) {
-            reaction(() => {
-                if (this.props.Document.Get(KeyStore.Data) as TextField) {
-                    return [(this.props.Document.Get(KeyStore.Data) as TextField).Data];
-                }
-                return [this.props.Document.Get(KeyStore.Data)];
-            }, () => this.setupGoldenLayout()); // should only react once when the Data field is retrieved from the sever .. after that, changes to the Data field will not trigger this reaction.
-            this.setupGoldenLayout();
+            reaction(
+                () => this.props.Document.GetText(KeyStore.Data, ""),
+                () => this.setupGoldenLayout(), { fireImmediately: true });
 
             window.addEventListener('resize', this.onResize); // bcz: would rather add this event to the parent node, but resize events only come from Window
         }
@@ -147,14 +145,21 @@ export class CollectionDockingView extends CollectionViewBase {
     }
     @action
     onResize = (event: any) => {
-        var cur = this.props.ContainingDocumentView!.MainContent.current;
+        var cur = this._containerRef.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
         this._goldenLayout.updateSize(cur!.getBoundingClientRect().width, cur!.getBoundingClientRect().height);
     }
 
+    @action
+    onPointerUp = (e: PointerEvent): void => {
+        window.removeEventListener("pointerup", this.onPointerUp)
+        this._pointerIsDown = false;
+    }
     @action
     onPointerDown = (e: React.PointerEvent): void => {
+        window.addEventListener("pointerup", this.onPointerUp)
+        this._pointerIsDown = true;
         if (e.button === 2 && this.active) {
             e.stopPropagation();
             e.preventDefault();
@@ -166,8 +171,10 @@ export class CollectionDockingView extends CollectionViewBase {
     }
 
     stateChanged = () => {
-        var json = JSON.stringify(this._goldenLayout.toConfig());
-        this.props.Document.SetText(KeyStore.Data, json)
+        if (!this._pointerIsDown) {
+            var json = JSON.stringify(this._goldenLayout.toConfig());
+            this.props.Document.SetText(KeyStore.Data, json)
+        }
     }
 
     tabCreated = (tab: any) => {
@@ -202,13 +209,8 @@ export class CollectionDockingView extends CollectionViewBase {
 
 
     render() {
-        const { fieldKey: fieldKey, Document: Document } = this.props;
-        const value: Document[] = Document.GetData(fieldKey, ListField, []);
-        // bcz: not sure why, but I need these to force the flexlayout to update when the collection size changes.
-        // tfs: we should be able to use this.props.ScreenToLocalTransform to get s right?
-        var s = this.props.ContainingDocumentView != undefined ? this.props.ContainingDocumentView!.ScalingToScreenSpace : 1;
-        var w = Document.GetNumber(KeyStore.Width, 0) / s;
-        var h = Document.GetNumber(KeyStore.Height, 0) / s;
+        this.props.Document.GetNumber(KeyStore.Width, 0); // bcz: needed to force render when window size changes
+        this.props.Document.GetNumber(KeyStore.Height, 0);
         return (
             <div className="collectiondockingview-container" id="menuContainer"
                 onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()} ref={this._containerRef}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index ee1a835f8..0ef8856b7 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -237,20 +237,6 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         }
     }
 
-    // 
-    // returns the cumulative scaling between the document and the screen
-    // tfs: I don't think this should be necessary
-    //
-    @computed
-    public get ScalingToScreenSpace(): number {
-        if (this.props.ContainingCollectionView != undefined &&
-            this.props.ContainingCollectionView.props.ContainingDocumentView != undefined) {
-            let ss = this.props.ContainingCollectionView.props.Document.GetNumber(KeyStore.Scale, 1);
-            return this.props.ContainingCollectionView.props.ContainingDocumentView.ScalingToScreenSpace * ss;
-        }
-        return 1;
-    }
-
     isSelected = () => {
         return SelectionManager.IsSelected(this);
     }
@@ -298,8 +284,9 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         var strwidth = width > 0 ? width.toString() + "px" : "100%";
         var height = this.props.Document.GetNumber(KeyStore.NativeHeight, 0);
         var strheight = height > 0 ? height.toString() + "px" : "100%";
+        var scaling = this.props.Scaling;// this.props.ScreenToLocalTransform().Scale;
         return (
-            <div className="documentView-node" ref={this._mainCont} style={{ width: strwidth, height: strheight, transformOrigin: "left top", transform: `scale(${this.props.Scaling},${this.props.Scaling})` }}
+            <div className="documentView-node" ref={this._mainCont} style={{ width: strwidth, height: strheight, transformOrigin: "left top", transform: `scale(${scaling},${scaling})` }}
                 onContextMenu={this.onContextMenu}
                 onPointerDown={this.onPointerDown} >
                 <JsxParser
diff --git a/src/fields/Document.ts b/src/fields/Document.ts
index fcc8adbcf..0c2ad0fdb 100644
--- a/src/fields/Document.ts
+++ b/src/fields/Document.ts
@@ -49,7 +49,7 @@ export class Document extends Field {
                 if (this.fields.has(key.Id)) {
                     field = this.fields.get(key.Id)!.field;
                 } else {
-                    field = "<Waiting>";
+                    field = FieldWaiting;
                 }
             }
         } else {
@@ -68,7 +68,7 @@ export class Document extends Field {
                         if (this.fields.has(key.Id)) {
                             field = this.fields.get(key.Id)!.field;
                         } else {
-                            field = "<Waiting>";
+                            field = FieldWaiting;
                         }
                         break;
                     }
-- 
cgit v1.2.3-70-g09d2


From 5074e854754ecb7ed9e2fa6b656f20edea38aff7 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 19 Feb 2019 16:35:39 -0500
Subject: fixed Dock View to avoid locking state

---
 .../views/collections/CollectionDockingView.tsx    | 23 ++++++++++------------
 1 file changed, 10 insertions(+), 13 deletions(-)

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

diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index abba0a6ae..9c396e412 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -43,8 +43,7 @@ export class CollectionDockingView extends CollectionViewBase {
     private _containerRef = React.createRef<HTMLDivElement>();
     private _makeFullScreen: boolean = false;
     private _maximizedStack: any = null;
-    private _pointerIsDown = false; // used to defer updating the document's layout state Data
-    private _deferredLayoutChange = ""; // the last deferred state change made that needs to be flushed on pointer up
+    private _forceRecreate: boolean = false;
 
     constructor(props: CollectionViewProps) {
         super(props);
@@ -99,6 +98,7 @@ export class CollectionDockingView extends CollectionViewBase {
 
         if (this._goldenLayout.root.contentItems[0].isRow) {
             this._goldenLayout.root.contentItems[0].addChild(newContentItem);
+            collayout.callDownwards('setSize');
         }
         else {
             var collayout = this._goldenLayout.root.contentItems[0];
@@ -112,6 +112,7 @@ export class CollectionDockingView extends CollectionViewBase {
             newContentItem.config["width"] = 50;
             collayout.parent.callDownwards('setSize');
         }
+        this._forceRecreate = true;
     }
 
     setupGoldenLayout() {
@@ -120,9 +121,12 @@ export class CollectionDockingView extends CollectionViewBase {
             if (!this._goldenLayout)
                 this._goldenLayout = new GoldenLayout(JSON.parse(config));
             else {
+                if (!this._forceRecreate && JSON.stringify(this._goldenLayout.toConfig()) == JSON.stringify(JSON.parse(config)))
+                    return;
                 this._goldenLayout.destroy();
                 this._goldenLayout = new GoldenLayout(JSON.parse(config));
             }
+            this._forceRecreate = false;
             this._goldenLayout.on('tabCreated', this.tabCreated);
             this._goldenLayout.on('stackCreated', this.stackCreated);
             this._goldenLayout.registerComponent('DocumentFrameRenderer', DockedFrameRenderer);
@@ -151,15 +155,8 @@ export class CollectionDockingView extends CollectionViewBase {
         this._goldenLayout.updateSize(cur!.getBoundingClientRect().width, cur!.getBoundingClientRect().height);
     }
 
-    @action
-    onPointerUp = (e: PointerEvent): void => {
-        window.removeEventListener("pointerup", this.onPointerUp)
-        this._pointerIsDown = false;
-    }
     @action
     onPointerDown = (e: React.PointerEvent): void => {
-        window.addEventListener("pointerup", this.onPointerUp)
-        this._pointerIsDown = true;
         if (e.button === 2 && this.active) {
             e.stopPropagation();
             e.preventDefault();
@@ -171,10 +168,10 @@ export class CollectionDockingView extends CollectionViewBase {
     }
 
     stateChanged = () => {
-        if (!this._pointerIsDown) {
-            var json = JSON.stringify(this._goldenLayout.toConfig());
-            this.props.Document.SetText(KeyStore.Data, json)
-        }
+        // if (!this._pointerIsDown) {
+        var json = JSON.stringify(this._goldenLayout.toConfig());
+        this.props.Document.SetText(KeyStore.Data, json)
+        //}
     }
 
     tabCreated = (tab: any) => {
-- 
cgit v1.2.3-70-g09d2


From 61c8c4baa4ead8be64b9f902075a0f3022aaef9e Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 19 Feb 2019 17:15:59 -0500
Subject: clean up and aspect resizing w/ doc dec.

---
 src/client/views/DocumentDecorations.tsx              | 19 ++++++++-----------
 .../views/collections/CollectionDockingView.tsx       | 12 +++++++-----
 2 files changed, 15 insertions(+), 16 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 48f5f01a1..7985b77dd 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -111,17 +111,6 @@ export class DocumentDecorations extends React.Component {
 
         SelectionManager.SelectedDocuments().forEach(element => {
             const rect = element.screenRect;
-            // if (rect.width !== 0) {
-            //     let scale = element.width / rect.width;
-            //     let actualdW = Math.max(element.width + (dW * scale), 20);
-            //     let actualdH = Math.max(element.height + (dH * scale), 20);
-            //     element.x += dX * (actualdW - element.width);
-            //     element.y += dY * (actualdH - element.height);
-            //     if (Math.abs(dW) > Math.abs(dH))
-            //         element.width = actualdW;
-            //     else
-            //         element.height = actualdH;
-            // }
             if (rect.width !== 0) {
                 let doc = element.props.Document;
                 let width = doc.GetOrCreate(KeyStore.Width, NumberField);
@@ -133,6 +122,14 @@ export class DocumentDecorations extends React.Component {
                 let actualdH = Math.max(height.Data + (dH * scale), 20);
                 x.Data += dX * (actualdW - width.Data);
                 y.Data += dY * (actualdH - height.Data);
+                var nativeWidth = doc.GetNumber(KeyStore.NativeWidth, 0);
+                var nativeHeight = doc.GetNumber(KeyStore.NativeHeight, 0);
+                if (nativeWidth > 0 && nativeHeight > 0) {
+                    if (Math.abs(dW) > Math.abs(dH))
+                        actualdH = nativeHeight / nativeWidth * actualdW;
+                    else
+                        actualdW = nativeWidth / nativeHeight * actualdH;
+                }
                 width.Data = actualdW;
                 height.Data = actualdH;
             }
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 9c396e412..842312faa 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -98,7 +98,6 @@ export class CollectionDockingView extends CollectionViewBase {
 
         if (this._goldenLayout.root.contentItems[0].isRow) {
             this._goldenLayout.root.contentItems[0].addChild(newContentItem);
-            collayout.callDownwards('setSize');
         }
         else {
             var collayout = this._goldenLayout.root.contentItems[0];
@@ -110,7 +109,6 @@ export class CollectionDockingView extends CollectionViewBase {
 
             collayout.config["width"] = 50;
             newContentItem.config["width"] = 50;
-            collayout.parent.callDownwards('setSize');
         }
         this._forceRecreate = true;
     }
@@ -227,12 +225,16 @@ interface DockedFrameProps {
 @observer
 export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
 
-    private _mainCont = React.createRef<HTMLDivElement>();
+    _mainCont: any = null;
     constructor(props: any) {
         super(props);
         Server.GetField(this.props.documentId, (f) => { this.Document = f as Document; })
     }
 
+    setMainCont: any = (element: any) => {
+        this._mainCont = element;
+    }
+
     @observable
     private _parentScaling = 1; // used to transfer the dimensions of the content pane in the DOM to the ParentScaling prop of the DocumentView
 
@@ -245,13 +247,13 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
         let nativeWidth = this.Document.GetNumber(KeyStore.NativeWidth, 0);
         var layout = this.Document.GetText(KeyStore.Layout, "");
         var content =
-            <div ref={this._mainCont}>
+            <div ref={this.setMainCont}>
                 <DocumentView key={this.Document.Id} Document={this.Document}
                     AddDocument={undefined}
                     RemoveDocument={undefined}
                     Scaling={this._parentScaling}
                     ScreenToLocalTransform={() => {
-                        let { scale, translateX, translateY } = Utils.GetScreenTransform(this._mainCont.current!);
+                        let { scale, translateX, translateY } = Utils.GetScreenTransform(this._mainCont);
                         var props = CollectionDockingView.Instance.props;
                         return props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(scale / this._parentScaling)
                     }}
-- 
cgit v1.2.3-70-g09d2


From cefcc726643f87f33ba5327cc7edd7f39d7d25c7 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 19 Feb 2019 17:36:48 -0500
Subject: not much

---
 src/client/views/collections/CollectionDockingView.tsx | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

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

diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 842312faa..6739416df 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -94,7 +94,7 @@ export class CollectionDockingView extends CollectionViewBase {
             type: 'stack',
             content: [CollectionDockingView.makeDocumentConfig(document)]
         };
-        var newContentItem = new this._goldenLayout._typeToItem[newItemStackConfig.type](this._goldenLayout, newItemStackConfig, parent);
+        var newContentItem = new this._goldenLayout._typeToItem[newItemStackConfig.type](this._goldenLayout, newItemStackConfig, null);
 
         if (this._goldenLayout.root.contentItems[0].isRow) {
             this._goldenLayout.root.contentItems[0].addChild(newContentItem);
@@ -110,21 +110,21 @@ export class CollectionDockingView extends CollectionViewBase {
             collayout.config["width"] = 50;
             newContentItem.config["width"] = 50;
         }
-        this._forceRecreate = true;
+        this.stateChanged();              // shouldn't need to do either of these ... but our react component doesn't render when we add it manually like this.
+        this.setupGoldenLayout(true);     // this forces it to render by the brute force method of recreating the whole golden layout
     }
 
-    setupGoldenLayout() {
+    setupGoldenLayout(force: boolean = false) {
         var config = this.props.Document.GetText(KeyStore.Data, "");
         if (config) {
             if (!this._goldenLayout)
                 this._goldenLayout = new GoldenLayout(JSON.parse(config));
             else {
-                if (!this._forceRecreate && JSON.stringify(this._goldenLayout.toConfig()) == JSON.stringify(JSON.parse(config)))
+                if (!force && JSON.stringify(this._goldenLayout.toConfig()) == JSON.stringify(JSON.parse(config)))
                     return;
                 this._goldenLayout.destroy();
                 this._goldenLayout = new GoldenLayout(JSON.parse(config));
             }
-            this._forceRecreate = false;
             this._goldenLayout.on('tabCreated', this.tabCreated);
             this._goldenLayout.on('stackCreated', this.stackCreated);
             this._goldenLayout.registerComponent('DocumentFrameRenderer', DockedFrameRenderer);
-- 
cgit v1.2.3-70-g09d2


From 4e88373e968795ea2dd40db534dca57b885b8398 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 19 Feb 2019 20:26:41 -0500
Subject: fixed transforms and shift dragging docs to make a frame

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

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

diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 6739416df..ceb638ab4 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -179,6 +179,7 @@ export class CollectionDockingView extends CollectionViewBase {
             this._dragParent!.appendChild(this._dragElement!);
             DragManager.Root().removeChild(this._dragDiv);
             this._dragDiv = null;
+            this.stateChanged();
         }
         tab.closeElement.off('click') //unbind the current click handler
             .click(function () {
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index ac1996ac5..518add0fc 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -245,6 +245,10 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         SelectionManager.SelectDoc(this, ctrlPressed)
     }
 
+    screenToLocalTransform = () => {
+        var parentScrToLocalXf = this.props && this.props.ScreenToLocalTransform ? this.props.ScreenToLocalTransform() : new Transform(0, 0, 1);
+        return parentScrToLocalXf.transform(new Transform(0, 0, this.props ? 1 / this.props.Scaling : 1));
+    }
     render() {
         let lkeys = this.props.Document.GetT(KeyStore.LayoutKeys, ListField);
         if (!lkeys || lkeys === "<Waiting>") {
@@ -278,6 +282,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
             bindings.BackgroundView = backgroundView;
         }
 
+        bindings.ScreenToLocalTransform = this.screenToLocalTransform; // adds 'Scaling' to the screen to local Xf
         var width = this.props.Document.GetNumber(KeyStore.NativeWidth, 0);
         var strwidth = width > 0 ? width.toString() + "px" : "100%";
         var height = this.props.Document.GetNumber(KeyStore.NativeHeight, 0);
-- 
cgit v1.2.3-70-g09d2


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

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

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

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


From ea9d49813dac1df7f421a4ecd372f5bd7d9449c3 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 20 Feb 2019 17:54:12 -0500
Subject: more fixes for selection.

---
 src/client/views/collections/CollectionDockingView.tsx | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

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

diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index fc5b8dacd..5e30c0390 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -242,6 +242,20 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
     @observable
     private Document: Opt<Document>;
 
+    @action
+    setScaling = (r: any) => {
+        let nativeWidth = this.Document!.GetNumber(KeyStore.NativeWidth, 0);
+        let nativeHeight = this.Document!.GetNumber(KeyStore.NativeWidth, 0);
+        this._parentScaling = nativeWidth > 0 ? r.entry.width / nativeWidth : 1;
+        this._nativeWidth = r.entry.width ? r.entry.width : nativeWidth;
+        this._nativeHeight = nativeWidth ? r.entry.width / nativeWidth * nativeHeight : nativeHeight;
+    }
+
+    @observable
+    private _nativeWidth = 0;
+    @observable
+    private _nativeHeight = 0;
+
     render() {
         if (!this.Document)
             return <div></div>
@@ -253,7 +267,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
                     AddDocument={undefined}
                     RemoveDocument={undefined}
                     Scaling={this._parentScaling}
-                    PanelSize={[0, 0]}
+                    PanelSize={[this._nativeWidth, this._nativeHeight]}
                     ScreenToLocalTransform={() => {
                         let { scale, translateX, translateY } = Utils.GetScreenTransform(this._mainCont);
                         var props = CollectionDockingView.Instance.props;
@@ -265,7 +279,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
 
         if (nativeWidth > 0 &&
             (layout.indexOf("CollectionFreeForm") == -1 || layout.indexOf("AnnotationsKey") != -1)) { // contents of documents should be scaled if document is not a freeform view, or if the freeformview is an annotation layer (presumably on a document that is not a freeformview)
-            return <Measure onResize={action((r: any) => this._parentScaling = nativeWidth > 0 ? r.entry.width / nativeWidth : 1)}>
+            return <Measure onResize={this.setScaling}>
                 {({ measureRef }) => <div ref={measureRef}>  {content} </div>}
             </Measure>
         }
-- 
cgit v1.2.3-70-g09d2


From c4a9eed08fbab61c295ec97ca1ffd7048afac3ac Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 20 Feb 2019 21:02:14 -0500
Subject: cleaning up docking

---
 src/Utils.ts                                       | 12 ++---
 .../views/collections/CollectionDockingView.tsx    | 57 ++++++++--------------
 2 files changed, 24 insertions(+), 45 deletions(-)

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

diff --git a/src/Utils.ts b/src/Utils.ts
index c9c006aa8..d4b7da52c 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -2,15 +2,6 @@ import v4 = require('uuid/v4');
 import v5 = require("uuid/v5");
 import { Socket } from 'socket.io';
 import { Message, Types } from './server/Message';
-import { Field } from './fields/Field';
-import { TextField } from './fields/TextField';
-import { NumberField } from './fields/NumberField';
-import { RichTextField } from './fields/RichTextField';
-import { Key } from './fields/Key';
-import { ImageField } from './fields/ImageField';
-import { ListField } from './fields/ListField';
-import { Document } from './fields/Document';
-import { Server } from './client/Server';
 
 export class Utils {
 
@@ -23,6 +14,9 @@ export class Utils {
     }
 
     public static GetScreenTransform(ele: HTMLElement): { scale: number, translateX: number, translateY: number } {
+        if (!ele) {
+            return { scale: 1, translateX: 1, translateY: 1 }
+        }
         const rect = ele.getBoundingClientRect();
         const scale = ele.offsetWidth == 0 && rect.width == 0 ? 1 : rect.width / ele.offsetWidth;
         const translateX = rect.left;
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 5e30c0390..4416460f1 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -17,7 +17,6 @@ import { observer } from "mobx-react";
 import { ListField } from "../../../fields/ListField";
 import { KeyStore } from "../../../fields/KeyStore";
 import { Opt } from "../../../fields/Field";
-import { TextField } from "../../../fields/TextField";
 
 @observer
 export class CollectionDockingView extends CollectionViewBase {
@@ -76,6 +75,7 @@ export class CollectionDockingView extends CollectionViewBase {
     }
 
     public OpenFullScreen(document: Document) {
+        console.log("OPEN FULL");
         this._makeFullScreen = true;
         this._goldenLayout.root.contentItems[0].addChild(CollectionDockingView.makeDocumentConfig(document));
     }
@@ -90,6 +90,7 @@ export class CollectionDockingView extends CollectionViewBase {
     //  Creates a vertical split on the right side of the docking view, and then adds the Document to that split
     //
     public AddRightSplit(document: Document) {
+        console.log("ADD RIGHT");
         let newItemStackConfig = {
             type: 'stack',
             content: [CollectionDockingView.makeDocumentConfig(document)]
@@ -166,10 +167,9 @@ export class CollectionDockingView extends CollectionViewBase {
     }
 
     stateChanged = () => {
-        // if (!this._pointerIsDown) {
+        console.log("STATE CHANGED");
         var json = JSON.stringify(this._goldenLayout.toConfig());
         this.props.Document.SetText(KeyStore.Data, json)
-        //}
     }
 
     tabCreated = (tab: any) => {
@@ -203,7 +203,6 @@ export class CollectionDockingView extends CollectionViewBase {
             });
     }
 
-
     render() {
         this.props.Document.GetNumber(KeyStore.Width, 0); // bcz: needed to force render when window size changes
         this.props.Document.GetNumber(KeyStore.Height, 0);
@@ -226,22 +225,17 @@ interface DockedFrameProps {
 @observer
 export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
 
-    _mainCont: any = null;
+    private _mainCont = React.createRef<HTMLDivElement>();
+    @observable private _nativeWidth = 0;
+    @observable private _nativeHeight = 0;
+    @observable private _parentScaling = 1; // used to transfer the dimensions of the content pane in the DOM to the ParentScaling prop of the DocumentView
+    @observable private Document: Opt<Document>;
+
     constructor(props: any) {
         super(props);
-        Server.GetField(this.props.documentId, (f) => { this.Document = f as Document; })
-    }
-
-    setMainCont: any = (element: any) => {
-        this._mainCont = element;
+        Server.GetField(this.props.documentId, f => this.Document = f as Document)
     }
 
-    @observable
-    private _parentScaling = 1; // used to transfer the dimensions of the content pane in the DOM to the ParentScaling prop of the DocumentView
-
-    @observable
-    private Document: Opt<Document>;
-
     @action
     setScaling = (r: any) => {
         let nativeWidth = this.Document!.GetNumber(KeyStore.NativeWidth, 0);
@@ -251,38 +245,29 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
         this._nativeHeight = nativeWidth ? r.entry.width / nativeWidth * nativeHeight : nativeHeight;
     }
 
-    @observable
-    private _nativeWidth = 0;
-    @observable
-    private _nativeHeight = 0;
+    ScreenToLocalTransform = () => {
+        let { scale, translateX, translateY } = Utils.GetScreenTransform(this._mainCont.current!);
+        var props = CollectionDockingView.Instance.props;
+        return props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(scale / this._parentScaling)
+    }
 
     render() {
         if (!this.Document)
-            return <div></div>
-        let nativeWidth = this.Document.GetNumber(KeyStore.NativeWidth, 0);
-        var layout = this.Document.GetText(KeyStore.Layout, "");
+            return (null)
         var content =
-            <div ref={this.setMainCont}>
+            <div ref={this._mainCont}>
                 <DocumentView key={this.Document.Id} Document={this.Document}
                     AddDocument={undefined}
                     RemoveDocument={undefined}
                     Scaling={this._parentScaling}
                     PanelSize={[this._nativeWidth, this._nativeHeight]}
-                    ScreenToLocalTransform={() => {
-                        let { scale, translateX, translateY } = Utils.GetScreenTransform(this._mainCont);
-                        var props = CollectionDockingView.Instance.props;
-                        return props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(scale / this._parentScaling)
-                    }}
+                    ScreenToLocalTransform={this.ScreenToLocalTransform}
                     isTopMost={true}
                     ContainingCollectionView={undefined} />
             </div>
 
-        if (nativeWidth > 0 &&
-            (layout.indexOf("CollectionFreeForm") == -1 || layout.indexOf("AnnotationsKey") != -1)) { // contents of documents should be scaled if document is not a freeform view, or if the freeformview is an annotation layer (presumably on a document that is not a freeformview)
-            return <Measure onResize={this.setScaling}>
-                {({ measureRef }) => <div ref={measureRef}>  {content} </div>}
-            </Measure>
-        }
-        return content
+        return <Measure onResize={this.setScaling}>
+            {({ measureRef }) => <div ref={measureRef}>  {content} </div>}
+        </Measure>
     }
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 4d729451e21082063759d6d61e7df7c540514a1d Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Thu, 21 Feb 2019 01:22:13 -0500
Subject: cleaned up a bit, but async editing is a problem.

---
 .../views/collections/CollectionDockingView.tsx    | 69 ++++++++++++++--------
 1 file changed, 46 insertions(+), 23 deletions(-)

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

diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 4416460f1..444f9e9d2 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -1,7 +1,7 @@
 import * as GoldenLayout from "golden-layout";
 import 'golden-layout/src/css/goldenlayout-base.css';
 import 'golden-layout/src/css/goldenlayout-dark-theme.css';
-import { action, computed, observable, reaction, trace } from "mobx";
+import { action, computed, observable, reaction, trace, untracked } from "mobx";
 import { DragManager } from "../../util/DragManager";
 import { DocumentView } from "../nodes/DocumentView";
 import { Document } from "../../../fields/Document";
@@ -20,7 +20,7 @@ import { Opt } from "../../../fields/Field";
 
 @observer
 export class CollectionDockingView extends CollectionViewBase {
-
+    public static ID = Utils.GenerateGuid();
     public static Instance: CollectionDockingView;
     public static LayoutString() { return CollectionViewBase.LayoutString("CollectionDockingView"); }
     public static makeDocumentConfig(document: Document) {
@@ -40,9 +40,7 @@ export class CollectionDockingView extends CollectionViewBase {
     private _dragElement: HTMLDivElement | undefined;
     private _dragFakeElement: HTMLDivElement | undefined;
     private _containerRef = React.createRef<HTMLDivElement>();
-    private _makeFullScreen: boolean = false;
-    private _maximizedStack: any = null;
-    private _forceRecreate: boolean = false;
+    private _fullScreen: any = null;
 
     constructor(props: CollectionViewProps) {
         super(props);
@@ -74,28 +72,41 @@ export class CollectionDockingView extends CollectionViewBase {
         // all of this must be undone when the document has been dropped (see tabCreated)
     }
 
+    @action
     public OpenFullScreen(document: Document) {
         console.log("OPEN FULL");
-        this._makeFullScreen = true;
-        this._goldenLayout.root.contentItems[0].addChild(CollectionDockingView.makeDocumentConfig(document));
+        let newItemStackConfig = {
+            type: 'stack',
+            content: [CollectionDockingView.makeDocumentConfig(document)]
+        }
+        var docconfig = this._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, this._goldenLayout);
+        this._goldenLayout.root.contentItems[0].addChild(docconfig);
+        docconfig.callDownwards('_$init');
+        this._goldenLayout._$maximiseItem(docconfig);
+        this._fullScreen = docconfig;
     }
+    @action
     public CloseFullScreen() {
-        if (this._maximizedStack) {
-            this._maximizedStack.header.controlsContainer.find('.lm_close').click();
-            this._maximizedStack = null;
+        if (this._fullScreen) {
+            this._goldenLayout._$minimiseItem(this._fullScreen);
+            this._goldenLayout.root.contentItems[0].removeChild(this._fullScreen);
+            this._fullScreen = null;
         }
     }
 
     //
     //  Creates a vertical split on the right side of the docking view, and then adds the Document to that split
     //
+    @action
     public AddRightSplit(document: Document) {
         console.log("ADD RIGHT");
+        this._goldenLayout.emit('stateChanged');
         let newItemStackConfig = {
             type: 'stack',
             content: [CollectionDockingView.makeDocumentConfig(document)]
-        };
-        var newContentItem = new this._goldenLayout._typeToItem[newItemStackConfig.type](this._goldenLayout, newItemStackConfig, null);
+        }
+
+        var newContentItem = this._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, this._goldenLayout);
 
         if (this._goldenLayout.root.contentItems[0].isRow) {
             this._goldenLayout.root.contentItems[0].addChild(newContentItem);
@@ -111,29 +122,40 @@ export class CollectionDockingView extends CollectionViewBase {
             collayout.config["width"] = 50;
             newContentItem.config["width"] = 50;
         }
-        this.stateChanged();              // shouldn't need to do either of these ... but our react component doesn't render when we add it manually like this.
-        this.setupGoldenLayout(true);     // this forces it to render by the brute force method of recreating the whole golden layout
+        newContentItem.callDownwards('_$init');
+        this._goldenLayout.root.callDownwards('setSize', [this._goldenLayout.width, this._goldenLayout.height]);
+        this._goldenLayout.emit('stateChanged');
     }
 
-    setupGoldenLayout(force: boolean = false) {
+    setupGoldenLayout() {
         var config = this.props.Document.GetText(KeyStore.Data, "");
         if (config) {
             if (!this._goldenLayout)
                 this._goldenLayout = new GoldenLayout(JSON.parse(config));
             else {
-                if (!force && JSON.stringify(this._goldenLayout.toConfig()) == JSON.stringify(JSON.parse(config)))
-                    return;
+                return;
+                try {
+                    this._goldenLayout.unbind('tabCreated', this.tabCreated);
+                    this._goldenLayout.unbind('stackCreated', this.stackCreated);
+                    this._goldenLayout.unbind('stateChanged', this.stateChanged);
+                    this._goldenLayout.unbind('initialised', this.stateChanged);
+                } catch (e) {
+
+                }
                 this._goldenLayout.destroy();
                 this._goldenLayout = new GoldenLayout(JSON.parse(config));
             }
             this._goldenLayout.on('tabCreated', this.tabCreated);
             this._goldenLayout.on('stackCreated', this.stackCreated);
+            this._goldenLayout.on('initialised', this.onOpened);
             this._goldenLayout.registerComponent('DocumentFrameRenderer', DockedFrameRenderer);
             this._goldenLayout.container = this._containerRef.current;
             this._goldenLayout.init();
-            this._goldenLayout.on('stateChanged', this.stateChanged);
         }
     }
+    onOpened = () => {
+        this._goldenLayout.on('stateChanged', this.stateChanged);
+    }
     componentDidMount: () => void = () => {
         if (this._containerRef.current) {
             reaction(
@@ -144,6 +166,12 @@ export class CollectionDockingView extends CollectionViewBase {
         }
     }
     componentWillUnmount: () => void = () => {
+        this._goldenLayout.unbind('tabCreated', this.tabCreated);
+        this._goldenLayout.unbind('stackCreated', this.stackCreated);
+        this._goldenLayout.unbind('stateChanged', this.stateChanged);
+        this._goldenLayout.unbind('initialised', this.stateChanged);
+        this._goldenLayout.destroy();
+        this._goldenLayout = null;
         window.removeEventListener('resize', this.onResize);
     }
     @action
@@ -188,11 +216,6 @@ export class CollectionDockingView extends CollectionViewBase {
     }
 
     stackCreated = (stack: any) => {
-        if (this._makeFullScreen) {
-            this._maximizedStack = stack;
-            setTimeout(function () { stack.header.controlsContainer.find('.lm_maximise').click() }, 10);
-            this._makeFullScreen = false;
-        }
         //stack.header.controlsContainer.find('.lm_popout').hide();
         stack.header.controlsContainer.find('.lm_close') //get the close icon
             .off('click') //unbind the current click handler
-- 
cgit v1.2.3-70-g09d2


From 8f8cfc60098fbb87e791a86d76d7c312b28de276 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Thu, 21 Feb 2019 11:49:23 -0500
Subject: working version of docking view for synchronous users

---
 src/client/views/Main.tsx                          | 25 +++----
 .../views/collections/CollectionDockingView.tsx    | 87 +++++++++++-----------
 2 files changed, 55 insertions(+), 57 deletions(-)

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

diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 2f8337d8e..f35362fd4 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -61,23 +61,22 @@ Documents.initProtos(() => {
         let mainfreeform: Document;
         if (res) {
             mainContainer = ServerUtils.FromJson(res) as Document;
-            var mainfreeformid = mainContainer._proxies.get(KeyStore.ActiveFrame.Id)!;
-            Server.GetField(mainfreeformid, (field) => {
-                if (field) {
-                    mainfreeform = field as Document;
-                }
-            })
             mainfreeform = mainContainer.Get(KeyStore.ActiveFrame) as Document;
+            if (!mainfreeform)
+                Server.GetField(mainContainer._proxies.get(KeyStore.ActiveFrame.Id)!, (field) => mainfreeform = field as Document);
         }
         else {
-            mainfreeform = Documents.CollectionDocument([], { x: 0, y: 400, title: "mini collection" });
-            Utils.Emit(Server.Socket, MessageStore.AddDocument, new DocumentTransfer(mainfreeform.ToJson()));
-
-            var docs = [mainfreeform].map(doc => CollectionDockingView.makeDocumentConfig(doc));
-            var config = { settings: { selectionEnabled: false }, content: [{ type: 'row', content: docs }] };
-            mainContainer = Documents.DockDocument(JSON.stringify(config), { title: "main container" }, mainDocId);
+            mainContainer = Documents.DockDocument(JSON.stringify({ content: [{ type: 'row', content: [] }] }), { title: "main container" }, mainDocId);
             Utils.Emit(Server.Socket, MessageStore.AddDocument, new DocumentTransfer(mainContainer.ToJson()))
-            mainContainer.Set(KeyStore.ActiveFrame, mainfreeform);
+
+            setTimeout(() => {
+                mainfreeform = Documents.CollectionDocument([], { x: 0, y: 400, title: "mini collection" });
+                Utils.Emit(Server.Socket, MessageStore.AddDocument, new DocumentTransfer(mainfreeform.ToJson()));
+
+                var docs = [mainfreeform].map(doc => CollectionDockingView.makeDocumentConfig(doc));
+                mainContainer.SetText(KeyStore.Data, JSON.stringify({ content: [{ type: 'row', content: docs }] }));
+                mainContainer.Set(KeyStore.ActiveFrame, mainfreeform);
+            }, 25);
         }
 
         let addImageNode = action(() => {
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 444f9e9d2..e8a1eaf92 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -11,16 +11,14 @@ import React = require("react");
 import * as ReactDOM from 'react-dom';
 import Measure from "react-measure";
 import { Utils } from "../../../Utils";
-import { FieldId, FieldWaiting, Field } from "../../../fields/Field";
+import { FieldId } from "../../../fields/Field";
 import { Server } from "../../Server";
 import { observer } from "mobx-react";
-import { ListField } from "../../../fields/ListField";
 import { KeyStore } from "../../../fields/KeyStore";
 import { Opt } from "../../../fields/Field";
 
 @observer
 export class CollectionDockingView extends CollectionViewBase {
-    public static ID = Utils.GenerateGuid();
     public static Instance: CollectionDockingView;
     public static LayoutString() { return CollectionViewBase.LayoutString("CollectionDockingView"); }
     public static makeDocumentConfig(document: Document) {
@@ -29,7 +27,8 @@ export class CollectionDockingView extends CollectionViewBase {
             component: 'DocumentFrameRenderer',
             title: document.Title,
             props: {
-                documentId: document.Id
+                documentId: document.Id,
+                //collectionDockingView: CollectionDockingView.Instance
             }
         }
     }
@@ -74,7 +73,6 @@ export class CollectionDockingView extends CollectionViewBase {
 
     @action
     public OpenFullScreen(document: Document) {
-        console.log("OPEN FULL");
         let newItemStackConfig = {
             type: 'stack',
             content: [CollectionDockingView.makeDocumentConfig(document)]
@@ -84,6 +82,7 @@ export class CollectionDockingView extends CollectionViewBase {
         docconfig.callDownwards('_$init');
         this._goldenLayout._$maximiseItem(docconfig);
         this._fullScreen = docconfig;
+        this.stateChanged();
     }
     @action
     public CloseFullScreen() {
@@ -91,6 +90,7 @@ export class CollectionDockingView extends CollectionViewBase {
             this._goldenLayout._$minimiseItem(this._fullScreen);
             this._goldenLayout.root.contentItems[0].removeChild(this._fullScreen);
             this._fullScreen = null;
+            this.stateChanged();
         }
     }
 
@@ -99,7 +99,6 @@ export class CollectionDockingView extends CollectionViewBase {
     //
     @action
     public AddRightSplit(document: Document) {
-        console.log("ADD RIGHT");
         this._goldenLayout.emit('stateChanged');
         let newItemStackConfig = {
             type: 'stack',
@@ -125,37 +124,34 @@ export class CollectionDockingView extends CollectionViewBase {
         newContentItem.callDownwards('_$init');
         this._goldenLayout.root.callDownwards('setSize', [this._goldenLayout.width, this._goldenLayout.height]);
         this._goldenLayout.emit('stateChanged');
+        this.stateChanged();
     }
 
     setupGoldenLayout() {
         var config = this.props.Document.GetText(KeyStore.Data, "");
         if (config) {
-            if (!this._goldenLayout)
+            if (!this._goldenLayout) {
                 this._goldenLayout = new GoldenLayout(JSON.parse(config));
+            }
             else {
-                return;
+                if (config == JSON.stringify(this._goldenLayout.toConfig()))
+                    return;
                 try {
+                    this._goldenLayout.unbind('itemDropped', this.itemDropped);
                     this._goldenLayout.unbind('tabCreated', this.tabCreated);
                     this._goldenLayout.unbind('stackCreated', this.stackCreated);
-                    this._goldenLayout.unbind('stateChanged', this.stateChanged);
-                    this._goldenLayout.unbind('initialised', this.stateChanged);
-                } catch (e) {
-
-                }
+                } catch (e) { }
                 this._goldenLayout.destroy();
                 this._goldenLayout = new GoldenLayout(JSON.parse(config));
             }
+            this._goldenLayout.on('itemDropped', this.itemDropped);
             this._goldenLayout.on('tabCreated', this.tabCreated);
             this._goldenLayout.on('stackCreated', this.stackCreated);
-            this._goldenLayout.on('initialised', this.onOpened);
             this._goldenLayout.registerComponent('DocumentFrameRenderer', DockedFrameRenderer);
             this._goldenLayout.container = this._containerRef.current;
             this._goldenLayout.init();
         }
     }
-    onOpened = () => {
-        this._goldenLayout.on('stateChanged', this.stateChanged);
-    }
     componentDidMount: () => void = () => {
         if (this._containerRef.current) {
             reaction(
@@ -166,10 +162,9 @@ export class CollectionDockingView extends CollectionViewBase {
         }
     }
     componentWillUnmount: () => void = () => {
+        this._goldenLayout.unbind('itemDropped', this.itemDropped);
         this._goldenLayout.unbind('tabCreated', this.tabCreated);
         this._goldenLayout.unbind('stackCreated', this.stackCreated);
-        this._goldenLayout.unbind('stateChanged', this.stateChanged);
-        this._goldenLayout.unbind('initialised', this.stateChanged);
         this._goldenLayout.destroy();
         this._goldenLayout = null;
         window.removeEventListener('resize', this.onResize);
@@ -182,12 +177,24 @@ export class CollectionDockingView extends CollectionViewBase {
         this._goldenLayout.updateSize(cur!.getBoundingClientRect().width, cur!.getBoundingClientRect().height);
     }
 
+    _flush: boolean = false;
+    @action
+    onPointerUp = (e: React.PointerEvent): void => {
+        if (this._flush) {
+            this._flush = false;
+            setTimeout(() => this.stateChanged(), 10);
+        }
+    }
     @action
     onPointerDown = (e: React.PointerEvent): void => {
         if (e.button === 2 && this.active) {
             e.stopPropagation();
             e.preventDefault();
         } else {
+            var className = (e.target as any).className;
+            if (className == "lm_drag_handle" || className == "lm_close" || className == "lm_maximise" || className == "lm_minimise" || className == "lm_close_tab") {
+                this._flush = true;
+            }
             if (e.buttons === 1 && this.active) {
                 e.stopPropagation();
             }
@@ -195,11 +202,13 @@ export class CollectionDockingView extends CollectionViewBase {
     }
 
     stateChanged = () => {
-        console.log("STATE CHANGED");
         var json = JSON.stringify(this._goldenLayout.toConfig());
         this.props.Document.SetText(KeyStore.Data, json)
     }
 
+    itemDropped = () => {
+        this.stateChanged();
+    }
     tabCreated = (tab: any) => {
         if (this._dragDiv) {
             this._dragDiv.removeChild(this._dragElement);
@@ -207,7 +216,6 @@ export class CollectionDockingView extends CollectionViewBase {
             this._dragParent!.appendChild(this._dragElement!);
             DragManager.Root().removeChild(this._dragDiv);
             this._dragDiv = null;
-            this.stateChanged();
         }
         tab.closeElement.off('click') //unbind the current click handler
             .click(function () {
@@ -227,11 +235,9 @@ export class CollectionDockingView extends CollectionViewBase {
     }
 
     render() {
-        this.props.Document.GetNumber(KeyStore.Width, 0); // bcz: needed to force render when window size changes
-        this.props.Document.GetNumber(KeyStore.Height, 0);
         return (
             <div className="collectiondockingview-container" id="menuContainer"
-                onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()} ref={this._containerRef}
+                onPointerDown={this.onPointerDown} onPointerUp={this.onPointerUp} onContextMenu={(e) => e.preventDefault()} ref={this._containerRef}
                 style={{
                     width: "100%",
                     height: "100%",
@@ -244,42 +250,35 @@ export class CollectionDockingView extends CollectionViewBase {
 
 interface DockedFrameProps {
     documentId: FieldId,
+    //collectionDockingView: CollectionDockingView
 }
 @observer
 export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
 
-    private _mainCont = React.createRef<HTMLDivElement>();
-    @observable private _nativeWidth = 0;
-    @observable private _nativeHeight = 0;
-    @observable private _parentScaling = 1; // used to transfer the dimensions of the content pane in the DOM to the ParentScaling prop of the DocumentView
-    @observable private Document: Opt<Document>;
+    @observable private _mainCont = React.createRef<HTMLDivElement>();
+    @observable private _panelWidth = 0;
+    @observable private _document: Opt<Document>;
 
     constructor(props: any) {
         super(props);
-        Server.GetField(this.props.documentId, f => this.Document = f as Document)
+        Server.GetField(this.props.documentId, f => this._document = f as Document)
     }
 
-    @action
-    setScaling = (r: any) => {
-        let nativeWidth = this.Document!.GetNumber(KeyStore.NativeWidth, 0);
-        let nativeHeight = this.Document!.GetNumber(KeyStore.NativeWidth, 0);
-        this._parentScaling = nativeWidth > 0 ? r.entry.width / nativeWidth : 1;
-        this._nativeWidth = r.entry.width ? r.entry.width : nativeWidth;
-        this._nativeHeight = nativeWidth ? r.entry.width / nativeWidth * nativeHeight : nativeHeight;
-    }
+    @computed private get _nativeWidth() { return this._document!.GetNumber(KeyStore.NativeWidth, 0); }
+    @computed private get _nativeHeight() { return this._document!.GetNumber(KeyStore.NativeHeight, 0); }
+    @computed private get _parentScaling() { return this._panelWidth / (this._nativeWidth ? this._nativeWidth : this._panelWidth); }; // used to transfer the dimensions of the content pane in the DOM to the ParentScaling prop of the DocumentView
 
     ScreenToLocalTransform = () => {
         let { scale, translateX, translateY } = Utils.GetScreenTransform(this._mainCont.current!);
-        var props = CollectionDockingView.Instance.props;
-        return props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(scale / this._parentScaling)
+        return CollectionDockingView.Instance.props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(scale / this._parentScaling)
     }
 
     render() {
-        if (!this.Document)
-            return (null)
+        if (!this._document)
+            return (null);
         var content =
             <div ref={this._mainCont}>
-                <DocumentView key={this.Document.Id} Document={this.Document}
+                <DocumentView key={this._document.Id} Document={this._document}
                     AddDocument={undefined}
                     RemoveDocument={undefined}
                     Scaling={this._parentScaling}
@@ -289,7 +288,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
                     ContainingCollectionView={undefined} />
             </div>
 
-        return <Measure onResize={this.setScaling}>
+        return <Measure onResize={action((r: any) => this._panelWidth = r.entry.width)}>
             {({ measureRef }) => <div ref={measureRef}>  {content} </div>}
         </Measure>
     }
-- 
cgit v1.2.3-70-g09d2


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

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

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

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


From 9e4403f9c14cdb7e05901af5f8509753269eeb07 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Thu, 21 Feb 2019 14:13:44 -0500
Subject: clean up

---
 src/client/util/UndoManager.ts                      |  1 -
 .../views/collections/CollectionDockingView.tsx     | 21 ++++++++++-----------
 .../views/collections/CollectionSchemaView.tsx      |  2 +-
 .../views/nodes/CollectionFreeFormDocumentView.tsx  | 12 +++---------
 src/fields/Document.ts                              |  5 -----
 src/fields/ListField.ts                             |  9 ++++-----
 6 files changed, 18 insertions(+), 32 deletions(-)

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

diff --git a/src/client/util/UndoManager.ts b/src/client/util/UndoManager.ts
index edb75b55f..46ad558f3 100644
--- a/src/client/util/UndoManager.ts
+++ b/src/client/util/UndoManager.ts
@@ -1,5 +1,4 @@
 import { observable, action } from "mobx";
-import { Opt } from "../../fields/Field";
 
 function propertyDecorator(target: any, key: string | symbol) {
     Object.defineProperty(target, key, {
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 35b130a9a..60dc24b5f 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -1,22 +1,21 @@
 import * as GoldenLayout from "golden-layout";
 import 'golden-layout/src/css/goldenlayout-base.css';
 import 'golden-layout/src/css/goldenlayout-dark-theme.css';
-import { action, computed, observable, reaction, trace, untracked } from "mobx";
-import { DragManager } from "../../util/DragManager";
-import { DocumentView } from "../nodes/DocumentView";
-import { Document } from "../../../fields/Document";
-import "./CollectionDockingView.scss";
-import { CollectionViewBase, COLLECTION_BORDER_WIDTH, CollectionViewProps } from "./CollectionViewBase";
-import React = require("react");
+import { action, computed, observable, reaction } from "mobx";
+import { observer } from "mobx-react";
 import * as ReactDOM from 'react-dom';
 import Measure from "react-measure";
+import { Document } from "../../../fields/Document";
+import { FieldId, Opt } from "../../../fields/Field";
+import { KeyStore } from "../../../fields/KeyStore";
 import { Utils } from "../../../Utils";
-import { FieldId } from "../../../fields/Field";
 import { Server } from "../../Server";
-import { observer } from "mobx-react";
-import { KeyStore } from "../../../fields/KeyStore";
-import { Opt } from "../../../fields/Field";
+import { DragManager } from "../../util/DragManager";
 import { undoBatch } from "../../util/UndoManager";
+import { DocumentView } from "../nodes/DocumentView";
+import "./CollectionDockingView.scss";
+import { CollectionViewBase, CollectionViewProps, COLLECTION_BORDER_WIDTH } from "./CollectionViewBase";
+import React = require("react");
 
 @observer
 export class CollectionDockingView extends CollectionViewBase {
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index f3217d55d..5ec288b13 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -1,5 +1,5 @@
 import React = require("react")
-import { action, computed, observable } from "mobx";
+import { action, observable } from "mobx";
 import { observer } from "mobx-react";
 import Measure from "react-measure";
 import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table";
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 7cad6ffc1..5568935fa 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -1,17 +1,11 @@
-import { action, computed } from "mobx";
+import { computed } from "mobx";
 import { observer } from "mobx-react";
 import { KeyStore } from "../../../fields/KeyStore";
 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 { Transform } from "../../util/Transform";
+import { DocumentView, DocumentViewProps } from "./DocumentView";
 import "./DocumentView.scss";
 import React = require("react");
-import { DocumentView, DocumentViewProps } from "./DocumentView";
-import { Utils } from "../../../Utils";
-import { Transform } from "../../util/Transform";
 
 
 @observer
diff --git a/src/fields/Document.ts b/src/fields/Document.ts
index d8522fb5b..6667485b6 100644
--- a/src/fields/Document.ts
+++ b/src/fields/Document.ts
@@ -152,16 +152,13 @@ export class Document extends Field {
     SetData<T, U extends Field & { Data: T }>(key: Key, value: T, ctor: { new(): U }, replaceWrongType = true) {
 
         let field = this.Get(key, true);
-        //if (field != WAITING) {  // do we want to wait for the field to come back from the server to set it, or do we overwrite?
         if (field instanceof ctor) {
             field.Data = value;
-            // Server.SetFieldValue(field, value);
         } else if (!field || replaceWrongType) {
             let newField = new ctor();
             newField.Data = value;
             this.Set(key, newField);
         }
-        //}
     }
 
     @action
@@ -213,14 +210,12 @@ export class Document extends Field {
     }
 
     ToJson(): { type: Types, data: [string, string][], _id: string } {
-        // console.log(this.fields)
         let fields: [string, string][] = []
         this._proxies.forEach((field, key) => {
             if (field) {
                 fields.push([key, field as string])
             }
         });
-        // console.log(fields)
 
         return {
             type: Types.Document,
diff --git a/src/fields/ListField.ts b/src/fields/ListField.ts
index ad5374dc9..75c2eb343 100644
--- a/src/fields/ListField.ts
+++ b/src/fields/ListField.ts
@@ -1,10 +1,9 @@
-import { Field, FieldId, FieldValue, Opt } from "./Field";
-import { BasicField } from "./BasicField";
-import { Types } from "../server/Message";
-import { observe, action, IArrayChange, IArraySplice, IObservableArray } from "mobx";
+import { action, IArrayChange, IArraySplice, IObservableArray, observe } from "mobx";
 import { Server } from "../client/Server";
-import { ServerUtils } from "../server/ServerUtil";
 import { UndoManager } from "../client/util/UndoManager";
+import { Types } from "../server/Message";
+import { BasicField } from "./BasicField";
+import { Field, FieldId } from "./Field";
 
 export class ListField<T extends Field> extends BasicField<T[]> {
     private _proxies: string[] = []
-- 
cgit v1.2.3-70-g09d2


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

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

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

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


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

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

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

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


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

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

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

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


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

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

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

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


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

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

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

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


From 43626b1c559bfe593bc86babf7a35115d72edd30 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 27 Feb 2019 17:24:07 -0500
Subject: fixed golden layout exception

---
 src/client/views/Main.tsx                              | 14 ++++++--------
 src/client/views/collections/CollectionDockingView.tsx |  2 +-
 2 files changed, 7 insertions(+), 9 deletions(-)

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

diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index b59a2a4f7..db7138965 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -91,14 +91,12 @@ function init(mainDocId: string) {
                 mainContainer = Documents.DockDocument(JSON.stringify({ content: [{ type: 'row', content: [] }] }), { title: "main container" }, mainDocId);
                 Utils.Emit(Server.Socket, MessageStore.AddDocument, new DocumentTransfer(mainContainer.ToJson()))
 
-                setTimeout(() => {
-                    mainfreeform = Documents.FreeformDocument([], { x: 0, y: 400, title: "mini collection" });
-                    Utils.Emit(Server.Socket, MessageStore.AddDocument, new DocumentTransfer(mainfreeform.ToJson()));
+                mainfreeform = Documents.FreeformDocument([], { x: 0, y: 400, title: "mini collection" });
+                Utils.Emit(Server.Socket, MessageStore.AddDocument, new DocumentTransfer(mainfreeform.ToJson()));
 
-                    var docs = [mainfreeform].map(doc => CollectionDockingView.makeDocumentConfig(doc));
-                    mainContainer.SetText(KeyStore.Data, JSON.stringify({ content: [{ type: 'row', content: docs }] }));
-                    mainContainer.Set(KeyStore.ActiveFrame, mainfreeform);
-                }, 0);
+                var docs = [mainfreeform].map(doc => CollectionDockingView.makeDocumentConfig(doc));
+                mainContainer.SetText(KeyStore.Data, JSON.stringify({ content: [{ type: 'row', content: docs }] }));
+                mainContainer.Set(KeyStore.ActiveFrame, mainfreeform);
             }
 
             let addImageNode = action(() => {
@@ -191,7 +189,7 @@ function init(mainDocId: string) {
                         left: '4px',
                         width: '150px'
                     }} onClick={() => WorkspacesMenu.Instance.toggle()}>Workspaces</button>
-                    <WorkspacesMenu load={init} new={getNewWorkspace} active={mainDocId}/>
+                    <WorkspacesMenu load={init} new={getNewWorkspace} active={mainDocId} />
                 </div>),
                 document.getElementById('root'));
         })
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 2230ec14f..ac8bac22e 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -163,7 +163,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
         if (this._containerRef.current) {
             reaction(
                 () => this.props.Document.GetText(KeyStore.Data, ""),
-                () => this.setupGoldenLayout(), { fireImmediately: true });
+                () => setTimeout(() => this.setupGoldenLayout(), 1), { fireImmediately: true });
 
             window.addEventListener('resize', this.onResize); // bcz: would rather add this event to the parent node, but resize events only come from Window
         }
-- 
cgit v1.2.3-70-g09d2

