From f80cddf158c6a43259d68ed0be9bfe084d464b4a 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

---
 .../views/collections/CollectionDockingView.tsx    | 79 ++++++----------------
 1 file changed, 22 insertions(+), 57 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 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 1f5cc996f5f64dc0e706a79ec3e0816fd9f895b1 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 c0d6dcb87743293fef10342c123c41390422595a 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

