From e0b3c759880639bf56f9b8b39ea2e38c5cbad8a6 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 10 Apr 2019 14:28:25 -0400
Subject: fixed extra rendering for collections.

---
 src/client/views/collections/CollectionSchemaView.tsx | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 587f60b3d..c67f8cd97 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -77,8 +77,8 @@ export class CollectionSchemaView extends CollectionSubView {
         let props: FieldViewProps = {
             Document: rowProps.value[0],
             fieldKey: rowProps.value[1],
-            isSelected: () => false,
-            select: () => { },
+            isSelected: returnFalse,
+            select: emptyFunction,
             isTopMost: false,
             selectOnLoad: false,
             ScreenToLocalTransform: Transform.Identity,
-- 
cgit v1.2.3-70-g09d2


From 354d65953cc6e29386b465ab2a12e85b443aad56 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 11 Apr 2019 08:57:23 -0400
Subject: fixed schema view context menu

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

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

diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index c67f8cd97..f1b3e1b8f 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -254,7 +254,7 @@ export class CollectionSchemaView extends CollectionSubView {
     focusDocument = (doc: Document) => { };
 
     onPointerDown = (e: React.PointerEvent): void => {
-        if (this.props.isSelected()) {
+        if (e.button === 1 && this.props.isSelected() && !e.altKey && !e.ctrlKey && !e.metaKey) {
             e.stopPropagation();
         }
     }
-- 
cgit v1.2.3-70-g09d2


From fd8e6bf2cacf8bed7c3363eeb777c731741266d5 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Thu, 11 Apr 2019 20:19:57 -0400
Subject: made COLLECTION_BORDER_WIDTH a CSS variable accessible from code. 
 changed global css variable file name

---
 src/client/util/DragManager.ts                     |  5 ++--
 src/client/util/TooltipTextMenu.scss               |  2 +-
 src/client/views/ContextMenu.scss                  |  2 +-
 src/client/views/DocumentDecorations.scss          |  2 +-
 src/client/views/InkingCanvas.scss                 |  2 +-
 src/client/views/InkingControl.scss                |  2 +-
 src/client/views/Main.scss                         |  2 +-
 src/client/views/_global_variables.scss            | 28 -------------------
 src/client/views/_global_variables.scss.d.ts       |  7 -----
 src/client/views/_global_variables.ts              |  8 ------
 .../views/collections/CollectionBaseView.tsx       |  1 -
 .../views/collections/CollectionDockingView.scss   |  6 +++++
 .../views/collections/CollectionDockingView.tsx    |  9 +------
 .../views/collections/CollectionSchemaView.scss    |  6 +++--
 .../views/collections/CollectionSchemaView.tsx     | 10 ++++---
 .../views/collections/CollectionTreeView.scss      |  6 +++--
 .../views/collections/CollectionTreeView.tsx       |  4 +--
 .../CollectionFreeFormRemoteCursors.scss           |  2 +-
 .../collectionFreeForm/CollectionFreeFormView.scss | 10 ++++---
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 31 ++++++++++++----------
 src/client/views/globalCssVariables.scss           | 29 ++++++++++++++++++++
 src/client/views/globalCssVariables.scss.d.ts      |  8 ++++++
 src/client/views/nodes/DocumentView.scss           |  2 +-
 src/client/views/nodes/FormattedTextBox.scss       |  2 +-
 src/client/views/nodes/KeyValueBox.scss            |  2 +-
 src/client/views/nodes/KeyValuePair.scss           |  2 +-
 src/client/views/nodes/LinkBox.scss                |  2 +-
 src/client/views/nodes/LinkEditor.scss             |  2 +-
 28 files changed, 99 insertions(+), 95 deletions(-)
 delete mode 100644 src/client/views/_global_variables.scss
 delete mode 100644 src/client/views/_global_variables.scss.d.ts
 delete mode 100644 src/client/views/_global_variables.ts
 create mode 100644 src/client/views/globalCssVariables.scss
 create mode 100644 src/client/views/globalCssVariables.scss.d.ts

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

diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 333c474c1..3d8bbb49c 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -5,8 +5,7 @@ import { CollectionDockingView } from "../views/collections/CollectionDockingVie
 import { DocumentDecorations } from "../views/DocumentDecorations";
 import { Main } from "../views/Main";
 import { DocumentView } from "../views/nodes/DocumentView";
-// import globalStyles from "../views/_global_variables";
-import * as globalStyles from "../views/_global_variables.scss"; // bcz: why doesn't this work?
+import * as globalCssVariables from "../views/globalCssVariables.scss";
 
 export function setupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc: () => Document, moveFunc?: DragManager.MoveFunction, copyOnDrop: boolean = false) {
     let onRowMove = action((e: PointerEvent): void => {
@@ -178,7 +177,7 @@ export namespace DragManager {
             dragElement.style.bottom = "";
             dragElement.style.left = "0";
             dragElement.style.transformOrigin = "0 0";
-            dragElement.style.zIndex = globalStyles.contextMenuZindex;// "1000";
+            dragElement.style.zIndex = globalCssVariables.contextMenuZindex;// "1000";
             dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`;
             dragElement.style.width = `${rect.width / scaleX}px`;
             dragElement.style.height = `${rect.height / scaleY}px`;
diff --git a/src/client/util/TooltipTextMenu.scss b/src/client/util/TooltipTextMenu.scss
index ea580d104..7deea3be6 100644
--- a/src/client/util/TooltipTextMenu.scss
+++ b/src/client/util/TooltipTextMenu.scss
@@ -1,4 +1,4 @@
-@import "../views/global_variables";
+@import "../views/globalCssVariables";
 
 .tooltipMenu {
     position: absolute;
diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss
index 5acf598cf..fe884ca85 100644
--- a/src/client/views/ContextMenu.scss
+++ b/src/client/views/ContextMenu.scss
@@ -1,4 +1,4 @@
-@import "global_variables";
+@import "globalCssVariables";
 .contextMenu-cont {
   position: absolute;
   display: flex;
diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss
index 321bda384..ce84b6106 100644
--- a/src/client/views/DocumentDecorations.scss
+++ b/src/client/views/DocumentDecorations.scss
@@ -1,4 +1,4 @@
-@import "global_variables";
+@import "globalCssVariables";
 
 .documentDecorations {
     position: absolute;
diff --git a/src/client/views/InkingCanvas.scss b/src/client/views/InkingCanvas.scss
index 42ae38c73..2c550051c 100644
--- a/src/client/views/InkingCanvas.scss
+++ b/src/client/views/InkingCanvas.scss
@@ -1,4 +1,4 @@
-@import "global_variables";
+@import "globalCssVariables";
 
 .inkingCanvas {
     opacity:0.99;
diff --git a/src/client/views/InkingControl.scss b/src/client/views/InkingControl.scss
index 0d8fd8784..ba4ec41af 100644
--- a/src/client/views/InkingControl.scss
+++ b/src/client/views/InkingControl.scss
@@ -1,4 +1,4 @@
-@import "global_variables";
+@import "globalCssVariables";
 .inking-control {
     position: absolute;
     left: 70px;
diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss
index 7329b8eb6..f3af26f37 100644
--- a/src/client/views/Main.scss
+++ b/src/client/views/Main.scss
@@ -1,4 +1,4 @@
-@import "global_variables";
+@import "globalCssVariables";
 @import "nodeModuleOverrides";
 html,
 body {
diff --git a/src/client/views/_global_variables.scss b/src/client/views/_global_variables.scss
deleted file mode 100644
index cd6af2dac..000000000
--- a/src/client/views/_global_variables.scss
+++ /dev/null
@@ -1,28 +0,0 @@
-@import url("https://fonts.googleapis.com/css?family=Noto+Sans:400,700|Crimson+Text:400,400i,700");
-// colors
-$light-color: #fcfbf7;
-$light-color-secondary: rgb(241, 239, 235);
-$main-accent: #61aaa3;
-// $alt-accent: #cdd5ec;
-// $alt-accent: #cdeceb;
-$alt-accent: #59dff7;
-$lighter-alt-accent: rgb(207, 220, 240);
-$intermediate-color: #9c9396;
-$dark-color: #121721;
-// fonts
-$sans-serif: "Noto Sans", sans-serif;
-// $sans-serif: "Roboto Slab", sans-serif;
-$serif: "Crimson Text", serif;
-// misc values
-$border-radius: 0.3em;
-//
-
-                            // dragged items
-$contextMenu-zindex: 1000;  // context menu shows up over everything
-$mainTextInput-zindex: 999; // then text input overlay so that it's context menu will appear over decorations, etc
-$docDecorations-zindex: 998; // then doc decorations appear over everything else
-$remoteCursors-zindex: 997; // ... not sure what level the remote cursors should go -- is this right?
-
-:export  {
-    contextMenuZindex: $contextMenu-zindex;
-}
\ No newline at end of file
diff --git a/src/client/views/_global_variables.scss.d.ts b/src/client/views/_global_variables.scss.d.ts
deleted file mode 100644
index ebee7dbce..000000000
--- a/src/client/views/_global_variables.scss.d.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-
-interface IGlobalScss {
-    contextMenuZindex: string;  // context menu shows up over everything
-}
-declare const globalStyleVariables: IGlobalScss;
-
-export = globalStyleVariables;
\ No newline at end of file
diff --git a/src/client/views/_global_variables.ts b/src/client/views/_global_variables.ts
deleted file mode 100644
index caedc7aad..000000000
--- a/src/client/views/_global_variables.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import * as globalStyleVariables from "../views/_global_variables.scss";
-
-export interface IGlobalScss {
-    contextMenuZindex: string;  // context menu shows up over everything
-}
-let globalStyles = globalStyleVariables as any as IGlobalScss;
-
-export default globalStyles;
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index ac320eda3..0ace700ce 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -34,7 +34,6 @@ export interface CollectionViewProps extends FieldViewProps {
     contentRef?: React.Ref<HTMLDivElement>;
 }
 
-export const COLLECTION_BORDER_WIDTH = 1;
 
 @observer
 export class CollectionBaseView extends React.Component<CollectionViewProps> {
diff --git a/src/client/views/collections/CollectionDockingView.scss b/src/client/views/collections/CollectionDockingView.scss
index 583d50c5b..13dd9faa8 100644
--- a/src/client/views/collections/CollectionDockingView.scss
+++ b/src/client/views/collections/CollectionDockingView.scss
@@ -1,8 +1,14 @@
+@import "../../views/globalCssVariables.scss";
+
 .collectiondockingview-content {
     height: 100%;
 }
 
 .collectiondockingview-container {
+    width: 100%;
+    height: 100%;
+    border-style: solid;
+    border-width: $COLLECTION_BORDER_WIDTH;
     position: absolute;
     top: 0;
     left: 0;
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 212cf8a69..05470f405 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -13,7 +13,6 @@ import { Server } from "../../Server";
 import { undoBatch } from "../../util/UndoManager";
 import { DocumentView } from "../nodes/DocumentView";
 import "./CollectionDockingView.scss";
-import { COLLECTION_BORDER_WIDTH } from "./CollectionBaseView";
 import React = require("react");
 import { SubCollectionViewProps } from "./CollectionSubView";
 import { ServerUtils } from "../../../server/ServerUtil";
@@ -271,13 +270,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
     render() {
         return (
             <div className="collectiondockingview-container" id="menuContainer"
-                onPointerDown={this.onPointerDown} onPointerUp={this.onPointerUp} ref={this._containerRef}
-                style={{
-                    width: "100%",
-                    height: "100%",
-                    borderStyle: "solid",
-                    borderWidth: `${COLLECTION_BORDER_WIDTH}px`,
-                }} />
+                onPointerDown={this.onPointerDown} onPointerUp={this.onPointerUp} ref={this._containerRef} />
         );
     }
 }
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index c3a2e88ac..40e49bb5f 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -1,4 +1,4 @@
-@import "../global_variables";
+@import "../globalCssVariables";
 
 //options menu styling
 #schemaOptionsMenuBtn {
@@ -53,7 +53,9 @@
   
 
 .collectionSchemaView-container {
-    border: 1px solid $intermediate-color;
+    border-width: $COLLECTION_BORDER_WIDTH;
+    border-color : $intermediate-color;
+    border-style: solid;
     border-radius: $border-radius;
     box-sizing: border-box;
     position: absolute;
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index f1b3e1b8f..0cb88eab0 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -25,7 +25,7 @@ import "./CollectionSchemaView.scss";
 import { CollectionView } from "./CollectionView";
 import { CollectionSubView } from "./CollectionSubView";
 import { TextField } from "../../../fields/TextField";
-import { COLLECTION_BORDER_WIDTH } from "./CollectionBaseView";
+import * as globalCssVariables from "../../views/globalCssVariables.scss";
 import { emptyFunction, returnFalse } from "../../../Utils";
 
 
@@ -245,11 +245,13 @@ export class CollectionSchemaView extends CollectionSubView {
         this._contentScaling = r.entry.width / selected!.GetNumber(KeyStore.NativeWidth, r.entry.width);
     }
 
+    @computed
+    get borderWidth() { return globalCssVariables.COLLECTION_BORDER_WIDTH; }
     getContentScaling = (): number => this._contentScaling;
     getPanelWidth = (): number => this._panelWidth;
     getPanelHeight = (): number => this._panelHeight;
-    getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- COLLECTION_BORDER_WIDTH - this.DIVIDER_WIDTH - this._dividerX, - COLLECTION_BORDER_WIDTH).scale(1 / this._contentScaling);
-    getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- COLLECTION_BORDER_WIDTH - this.DIVIDER_WIDTH - this._dividerX - this._tableWidth, - COLLECTION_BORDER_WIDTH).scale(1 / this._contentScaling);
+    getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH - this._dividerX, - this.borderWidth).scale(1 / this._contentScaling);
+    getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH - this._dividerX - this._tableWidth, - this.borderWidth).scale(1 / this._contentScaling);
 
     focusDocument = (doc: Document) => { };
 
@@ -349,7 +351,7 @@ export class CollectionSchemaView extends CollectionSubView {
         </Flyout>);
 
         return (
-            <div className="collectionSchemaView-container" onPointerDown={this.onPointerDown} onWheel={this.onWheel} ref={this._mainCont} style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }} >
+            <div className="collectionSchemaView-container" onPointerDown={this.onPointerDown} onWheel={this.onWheel} ref={this._mainCont}>
                 <div className="collectionSchemaView-dropTarget" onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createDropTarget}>
                     <Measure onResize={this.setTableDimensions}>
                         {({ measureRef }) =>
diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss
index f2affbf55..973eead97 100644
--- a/src/client/views/collections/CollectionTreeView.scss
+++ b/src/client/views/collections/CollectionTreeView.scss
@@ -1,7 +1,9 @@
-@import "../global_variables";
+@import "../globalCssVariables";
 
 .collectionTreeView-dropTarget {
-    border: 0px solid transparent;
+    border-width: $COLLECTION_BORDER_WIDTH;
+    border-color: transparent;
+    border-style: solid;
     border-radius: $border-radius;
     box-sizing: border-box;
     height: 100%;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 659cff9fe..20ec16822 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -11,9 +11,9 @@ import { setupDrag, DragManager } from "../../util/DragManager";
 import { EditableView } from "../EditableView";
 import "./CollectionTreeView.scss";
 import { CollectionView } from "./CollectionView";
+import * as globalCssVariables from "../../views/globalCssVariables.scss";
 import { CollectionSubView } from "./CollectionSubView";
 import React = require("react");
-import { COLLECTION_BORDER_WIDTH } from './CollectionBaseView';
 import { props } from 'bluebird';
 
 
@@ -139,7 +139,7 @@ export class CollectionTreeView extends CollectionSubView {
             );
 
         return (
-            <div id="body" className="collectionTreeView-dropTarget" onWheel={(e: React.WheelEvent) => e.stopPropagation()} onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createDropTarget} style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }}>
+            <div id="body" className="collectionTreeView-dropTarget" onWheel={(e: React.WheelEvent) => e.stopPropagation()} onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createDropTarget}>
                 <div className="coll-title">
                     <EditableView
                         contents={this.props.Document.Title}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.scss
index c38787802..c5b8fc5e8 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.scss
@@ -1,4 +1,4 @@
-@import "global_variables";
+@import "globalCssVariables";
 
 .collectionFreeFormRemoteCursors-cont {
     
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
index 81f2146e4..f3ac4a383 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
@@ -1,4 +1,4 @@
-@import "../../global_variables";
+@import "../../globalCssVariables";
 .collectionfreeformview-measure {
     position: absolute;
     top: 0;
@@ -28,8 +28,10 @@
     // background-size: 30px 30px;
   // }
 
+  border-width: $COLLECTION_BORDER_WIDTH;
   box-shadow: $intermediate-color 0.2vw 0.2vw 0.8vw;
-  border: 0px solid $light-color-secondary;
+  border-color:  $light-color-secondary;
+  border-style: solid; 
   border-radius: $border-radius;
   box-sizing: border-box;
   position: absolute;
@@ -49,7 +51,9 @@
   }
  
   opacity: 0.99;
-  border: 0px solid transparent;
+  border-width: 0;
+  border-color: transparent;
+  border-style: solid; 
   border-radius: $border-radius;
   box-sizing: border-box;
   position:absolute;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 01ebbe0e1..e38e71a68 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1,31 +1,31 @@
-import { action, computed, observable, trace, ObservableSet, runInAction } from "mobx";
+import { action, computed, observable, runInAction } from "mobx";
 import { observer } from "mobx-react";
+import Measure from "react-measure";
 import { Document } from "../../../../fields/Document";
 import { FieldWaiting } from "../../../../fields/Field";
 import { KeyStore } from "../../../../fields/KeyStore";
+import { NumberField } from "../../../../fields/NumberField";
 import { TextField } from "../../../../fields/TextField";
+import { emptyFunction, returnFalse } from "../../../../Utils";
+import { DocumentManager } from "../../../util/DocumentManager";
 import { DragManager } from "../../../util/DragManager";
+import { SelectionManager } from "../../../util/SelectionManager";
 import { Transform } from "../../../util/Transform";
 import { undoBatch } from "../../../util/UndoManager";
+import * as globalCssVariables from "../../../views/globalCssVariables.scss";
 import { InkingCanvas } from "../../InkingCanvas";
+import { Main } from "../../Main";
 import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDocumentView";
 import { DocumentContentsView } from "../../nodes/DocumentContentsView";
 import { DocumentViewProps } from "../../nodes/DocumentView";
-import { COLLECTION_BORDER_WIDTH } from "../CollectionBaseView";
 import { CollectionSubView } from "../CollectionSubView";
 import { CollectionFreeFormLinksView } from "./CollectionFreeFormLinksView";
+import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCursors";
 import "./CollectionFreeFormView.scss";
 import { MarqueeView } from "./MarqueeView";
+import { PreviewCursor } from "./PreviewCursor";
 import React = require("react");
 import v5 = require("uuid/v5");
-import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCursors";
-import { PreviewCursor } from "./PreviewCursor";
-import { DocumentManager } from "../../../util/DocumentManager";
-import { SelectionManager } from "../../../util/SelectionManager";
-import { NumberField } from "../../../../fields/NumberField";
-import { Main } from "../../Main";
-import Measure from "react-measure";
-import { returnFalse, emptyFunction } from "../../../../Utils";
 
 @observer
 export class CollectionFreeFormView extends CollectionSubView {
@@ -297,8 +297,12 @@ export class CollectionFreeFormView extends CollectionSubView {
                 layoutKey={KeyStore.OverlayLayout} isTopMost={this.props.isTopMost} isSelected={returnFalse} select={emptyFunction} />);
     }
 
-    getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH).translate(-this.centeringShiftX, -this.centeringShiftY).transform(this.getLocalTransform());
-    getContainerTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH);
+    @computed
+    get borderWidth() {
+        return this.isAnnotationOverlay ? 0 : globalCssVariables.COLLECTION_BORDER_WIDTH;
+    }
+    getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth, -this.borderWidth).translate(-this.centeringShiftX, -this.centeringShiftY).transform(this.getLocalTransform());
+    getContainerTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth, -this.borderWidth);
     getLocalTransform = (): Transform => Transform.Identity().scale(1 / this.scale).translate(this.panX, this.panY);
     noScaling = () => 1;
     childViews = () => this.views;
@@ -317,8 +321,7 @@ export class CollectionFreeFormView extends CollectionSubView {
                     <div className={`collectionfreeformview-measure`} ref={measureRef}>
                         <div className={`collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`}
                             onPointerDown={this.onPointerDown} onPointerMove={(e) => super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY))}
-                            onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} onWheel={this.onPointerWheel}
-                            style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }} ref={this.createDropTarget}>
+                            onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} onWheel={this.onPointerWheel} ref={this.createDropTarget}>
                             <MarqueeView container={this} activeDocuments={this.getActiveDocuments} selectDocuments={this.selectDocuments}
                                 addDocument={this.addDocument} removeDocument={this.props.removeDocument}
                                 getContainerTransform={this.getContainerTransform} getTransform={this.getTransform}>
diff --git a/src/client/views/globalCssVariables.scss b/src/client/views/globalCssVariables.scss
new file mode 100644
index 000000000..5c8e9c8fc
--- /dev/null
+++ b/src/client/views/globalCssVariables.scss
@@ -0,0 +1,29 @@
+@import url("https://fonts.googleapis.com/css?family=Noto+Sans:400,700|Crimson+Text:400,400i,700");
+// colors
+$light-color: #fcfbf7;
+$light-color-secondary: rgb(241, 239, 235);
+$main-accent: #61aaa3;
+// $alt-accent: #cdd5ec;
+// $alt-accent: #cdeceb;
+$alt-accent: #59dff7;
+$lighter-alt-accent: rgb(207, 220, 240);
+$intermediate-color: #9c9396;
+$dark-color: #121721;
+// fonts
+$sans-serif: "Noto Sans", sans-serif;
+// $sans-serif: "Roboto Slab", sans-serif;
+$serif: "Crimson Text", serif;
+// misc values
+$border-radius: 0.3em;
+//
+
+                            // dragged items
+$contextMenu-zindex: 1000;  // context menu shows up over everything
+$mainTextInput-zindex: 999; // then text input overlay so that it's context menu will appear over decorations, etc
+$docDecorations-zindex: 998; // then doc decorations appear over everything else
+$remoteCursors-zindex: 997; // ... not sure what level the remote cursors should go -- is this right?
+$COLLECTION_BORDER_WIDTH: 1;
+:export  {
+    contextMenuZindex: $contextMenu-zindex;
+    COLLECTION_BORDER_WIDTH: $COLLECTION_BORDER_WIDTH;
+}
\ No newline at end of file
diff --git a/src/client/views/globalCssVariables.scss.d.ts b/src/client/views/globalCssVariables.scss.d.ts
new file mode 100644
index 000000000..e874b815d
--- /dev/null
+++ b/src/client/views/globalCssVariables.scss.d.ts
@@ -0,0 +1,8 @@
+
+interface IGlobalScss {
+    contextMenuZindex: string;  // context menu shows up over everything
+    COLLECTION_BORDER_WIDTH: number;
+}
+declare const globalCssVariables: IGlobalScss;
+
+export = globalCssVariables;
\ No newline at end of file
diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss
index 5126e69f9..039d1bcc6 100644
--- a/src/client/views/nodes/DocumentView.scss
+++ b/src/client/views/nodes/DocumentView.scss
@@ -1,4 +1,4 @@
-@import "../global_variables";
+@import "../globalCssVariables";
 
 .documentView-node {
   position: absolute;
diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss
index d2ba52cf9..3978c3d38 100644
--- a/src/client/views/nodes/FormattedTextBox.scss
+++ b/src/client/views/nodes/FormattedTextBox.scss
@@ -1,4 +1,4 @@
-@import "../global_variables";
+@import "../globalCssVariables";
 .ProseMirror {
   width: 100%;
   height: auto;
diff --git a/src/client/views/nodes/KeyValueBox.scss b/src/client/views/nodes/KeyValueBox.scss
index 63ae75424..f60edc675 100644
--- a/src/client/views/nodes/KeyValueBox.scss
+++ b/src/client/views/nodes/KeyValueBox.scss
@@ -1,4 +1,4 @@
-@import "../global_variables";
+@import "../globalCssVariables";
 .keyValueBox-cont {
     overflow-y: scroll;
     height: 100%;
diff --git a/src/client/views/nodes/KeyValuePair.scss b/src/client/views/nodes/KeyValuePair.scss
index 64e871e1c..0bb92e5a3 100644
--- a/src/client/views/nodes/KeyValuePair.scss
+++ b/src/client/views/nodes/KeyValuePair.scss
@@ -1,4 +1,4 @@
-@import "../global_variables";
+@import "../globalCssVariables";
 
 .container{
     display: flex;                 
diff --git a/src/client/views/nodes/LinkBox.scss b/src/client/views/nodes/LinkBox.scss
index 5d5f782d2..8bc70b48f 100644
--- a/src/client/views/nodes/LinkBox.scss
+++ b/src/client/views/nodes/LinkBox.scss
@@ -1,4 +1,4 @@
-@import "../global_variables";
+@import "../globalCssVariables";
 .link-container {
     width: 100%;
     height: 35px;
diff --git a/src/client/views/nodes/LinkEditor.scss b/src/client/views/nodes/LinkEditor.scss
index fb0c69cff..ea2e7289c 100644
--- a/src/client/views/nodes/LinkEditor.scss
+++ b/src/client/views/nodes/LinkEditor.scss
@@ -1,4 +1,4 @@
-@import "../global_variables";
+@import "../globalCssVariables";
 .edit-container {
     width: 100%;
     height: auto;
-- 
cgit v1.2.3-70-g09d2


From 0c9d3637bde9825efe93c55afce8270b2a2e979c Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 12 Apr 2019 11:18:23 -0400
Subject: cleaned up and enabled linking to a top-level document

---
 src/client/util/DragManager.ts                     | 29 ++++++++++++++++++++-
 src/client/views/DocumentDecorations.tsx           | 27 ++-----------------
 src/client/views/Main.tsx                          |  4 +--
 .../views/collections/CollectionDockingView.tsx    | 30 +++-------------------
 .../views/collections/CollectionSchemaView.tsx     |  4 +--
 .../views/collections/CollectionTreeView.tsx       |  4 +--
 src/client/views/nodes/DocumentView.tsx            |  3 ---
 7 files changed, 39 insertions(+), 62 deletions(-)

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

diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 2562ba18a..6a7047725 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -6,8 +6,10 @@ import { DocumentDecorations } from "../views/DocumentDecorations";
 import { Main } from "../views/Main";
 import { DocumentView } from "../views/nodes/DocumentView";
 import * as globalCssVariables from "../views/globalCssVariables.scss";
+import { KeyStore } from "../../fields/KeyStore";
+import { FieldWaiting } from "../../fields/Field";
 
-export function setupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc: () => Document, moveFunc?: DragManager.MoveFunction, copyOnDrop: boolean = false) {
+export function SetupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc: () => Document, moveFunc?: DragManager.MoveFunction, copyOnDrop: boolean = false) {
     let onRowMove = action((e: PointerEvent): void => {
         e.stopPropagation();
         e.preventDefault();
@@ -39,6 +41,31 @@ export function setupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc:
     return onItemDown;
 }
 
+export async function DragLinksAsDocuments(dragEle: HTMLElement, x: number, y: number, sourceDoc: Document) {
+    let srcTarg = sourceDoc.GetT(KeyStore.Prototype, Document);
+    let draggedDocs = (srcTarg && srcTarg !== FieldWaiting) ?
+        srcTarg.GetList(KeyStore.LinkedToDocs, [] as Document[]).map(linkDoc =>
+            (linkDoc.GetT(KeyStore.LinkedToDocs, Document)) as Document) : [];
+    let draggedFromDocs = (srcTarg && srcTarg !== FieldWaiting) ?
+        srcTarg.GetList(KeyStore.LinkedFromDocs, [] as Document[]).map(linkDoc =>
+            (linkDoc.GetT(KeyStore.LinkedFromDocs, Document)) as Document) : [];
+    draggedDocs.push(...draggedFromDocs);
+    if (draggedDocs.length) {
+        let moddrag = [] as Document[];
+        for (const draggedDoc of draggedDocs) {
+            let doc = await draggedDoc.GetTAsync(KeyStore.AnnotationOn, Document);
+            if (doc) moddrag.push(doc);
+        }
+        let dragData = new DragManager.DocumentDragData(moddrag.length ? moddrag : draggedDocs);
+        DragManager.StartDocumentDrag([dragEle], dragData, x, y, {
+            handlers: {
+                dragComplete: action(emptyFunction),
+            },
+            hideSource: false
+        });
+    }
+}
+
 export namespace DragManager {
     export function Root() {
         const root = document.getElementById("root");
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 69623b8f0..03b16fb0b 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -7,7 +7,7 @@ import { ListField } from "../../fields/ListField";
 import { NumberField } from "../../fields/NumberField";
 import { Document } from "../../fields/Document";
 import { TextField } from "../../fields/TextField";
-import { DragManager } from "../util/DragManager";
+import { DragManager, DragLinksAsDocuments } from "../util/DragManager";
 import { SelectionManager } from "../util/SelectionManager";
 import { CollectionView } from "./collections/CollectionView";
 import './DocumentDecorations.scss';
@@ -246,34 +246,11 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             document.removeEventListener("pointermove", this.onLinkButtonMoved);
             document.removeEventListener("pointerup", this.onLinkButtonUp);
 
-            let sourceDoc = SelectionManager.SelectedDocuments()[0].props.Document;
-            let srcTarg = sourceDoc.GetT(KeyStore.Prototype, Document);
-            let draggedDocs = (srcTarg && srcTarg !== FieldWaiting) ?
-                srcTarg.GetList(KeyStore.LinkedToDocs, [] as Document[]).map(linkDoc =>
-                    (linkDoc.GetT(KeyStore.LinkedToDocs, Document)) as Document) : [];
-            let draggedFromDocs = (srcTarg && srcTarg !== FieldWaiting) ?
-                srcTarg.GetList(KeyStore.LinkedFromDocs, [] as Document[]).map(linkDoc =>
-                    (linkDoc.GetT(KeyStore.LinkedFromDocs, Document)) as Document) : [];
-            draggedDocs.push(...draggedFromDocs);
-            if (draggedDocs.length) {
-                let moddrag = [] as Document[];
-                for (const draggedDoc of draggedDocs) {
-                    let doc = await draggedDoc.GetTAsync(KeyStore.AnnotationOn, Document);
-                    if (doc) moddrag.push(doc);
-                }
-                let dragData = new DragManager.DocumentDragData(moddrag.length ? moddrag : draggedDocs);
-                DragManager.StartDocumentDrag([this._linkButton.current], dragData, e.x, e.y, {
-                    handlers: {
-                        dragComplete: action(emptyFunction),
-                    },
-                    hideSource: false
-                });
-            }
+            DragLinksAsDocuments(this._linkButton.current, e.x, e.y, SelectionManager.SelectedDocuments()[0].props.Document);
         }
         e.stopPropagation();
     }
 
-
     onPointerMove = (e: PointerEvent): void => {
         e.stopPropagation();
         e.preventDefault();
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index c4c4a6bf9..60f7098fb 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -28,7 +28,7 @@ import '../northstar/model/ModelExtensions';
 import { HistogramOperation } from '../northstar/operations/HistogramOperation';
 import '../northstar/utils/Extensions';
 import { Server } from '../Server';
-import { setupDrag, DragManager } from '../util/DragManager';
+import { SetupDrag, DragManager } from '../util/DragManager';
 import { Transform } from '../util/Transform';
 import { UndoManager } from '../util/UndoManager';
 import { CollectionDockingView } from './collections/CollectionDockingView';
@@ -344,7 +344,7 @@ export class Main extends React.Component {
                 <ul id="add-options-list">
                     {btns.map(btn =>
                         <li key={btn[1]} ><div ref={btn[0]}>
-                            <button className="round-button add-button" title={btn[2]} onPointerDown={setupDrag(btn[0], btn[3])}>
+                            <button className="round-button add-button" title={btn[2]} onPointerDown={SetupDrag(btn[0], btn[3])}>
                                 <FontAwesomeIcon icon={btn[1]} size="sm" />
                             </button>
                         </div></li>)}
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index f2f41e821..e54c25474 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -16,7 +16,7 @@ import "./CollectionDockingView.scss";
 import React = require("react");
 import { SubCollectionViewProps } from "./CollectionSubView";
 import { ServerUtils } from "../../../server/ServerUtil";
-import { DragManager } from "../../util/DragManager";
+import { DragManager, DragLinksAsDocuments } from "../../util/DragManager";
 import { TextField } from "../../../fields/TextField";
 import { ListField } from "../../../fields/ListField";
 
@@ -201,32 +201,8 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
             let y = e.clientY;
             let docid = (e.target as any).DashDocId;
             let tab = (e.target as any).parentElement as HTMLElement;
-            Server.GetField(docid, action(async (sourceDoc: Opt<Field>) => {
-                if (sourceDoc instanceof Document) {
-                    let srcTarg = sourceDoc.GetT(KeyStore.Prototype, Document);
-                    let draggedDocs = (srcTarg && srcTarg !== FieldWaiting) ?
-                        srcTarg.GetList(KeyStore.LinkedToDocs, [] as Document[]).map(linkDoc =>
-                            (linkDoc.GetT(KeyStore.LinkedToDocs, Document)) as Document) : [];
-                    let draggedFromDocs = (srcTarg && srcTarg !== FieldWaiting) ?
-                        srcTarg.GetList(KeyStore.LinkedFromDocs, [] as Document[]).map(linkDoc =>
-                            (linkDoc.GetT(KeyStore.LinkedFromDocs, Document)) as Document) : [];
-                    draggedDocs.push(...draggedFromDocs);
-                    if (draggedDocs.length) {
-                        let moddrag = [] as Document[];
-                        for (const draggedDoc of draggedDocs) {
-                            let doc = await draggedDoc.GetTAsync(KeyStore.AnnotationOn, Document);
-                            if (doc) moddrag.push(doc);
-                        }
-                        let dragData = new DragManager.DocumentDragData(moddrag.length ? moddrag : draggedDocs);
-                        DragManager.StartDocumentDrag([tab], dragData, x, y, {
-                            handlers: {
-                                dragComplete: action(emptyFunction),
-                            },
-                            hideSource: false
-                        });
-                    }
-                }
-            }));
+            Server.GetField(docid, action(async (sourceDoc: Opt<Field>) =>
+                (sourceDoc instanceof Document) && DragLinksAsDocuments(tab, x, y, sourceDoc)));
         } else
             if ((className === "lm_title" || className === "lm_tab lm_active") && !e.shiftKey) {
                 e.stopPropagation();
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 0cb88eab0..f53b2a76e 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -13,7 +13,7 @@ import { Key } from "../../../fields/Key";
 import { KeyStore } from "../../../fields/KeyStore";
 import { ListField } from "../../../fields/ListField";
 import { Server } from "../../Server";
-import { setupDrag } from "../../util/DragManager";
+import { SetupDrag } from "../../util/DragManager";
 import { CompileScript, ToField } from "../../util/Scripting";
 import { Transform } from "../../util/Transform";
 import { anchorPoints, Flyout } from "../DocumentDecorations";
@@ -90,7 +90,7 @@ export class CollectionSchemaView extends CollectionSubView {
             <FieldView {...props} />
         );
         let reference = React.createRef<HTMLDivElement>();
-        let onItemDown = setupDrag(reference, () => props.Document, this.props.moveDocument);
+        let onItemDown = SetupDrag(reference, () => props.Document, this.props.moveDocument);
         let applyToDoc = (doc: Document, run: (args?: { [name: string]: any }) => any) => {
             const res = run({ this: doc });
             if (!res.success) return false;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 20ec16822..51a02fc25 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -7,7 +7,7 @@ import { Document } from "../../../fields/Document";
 import { FieldWaiting } from "../../../fields/Field";
 import { KeyStore } from "../../../fields/KeyStore";
 import { ListField } from "../../../fields/ListField";
-import { setupDrag, DragManager } from "../../util/DragManager";
+import { SetupDrag, DragManager } from "../../util/DragManager";
 import { EditableView } from "../EditableView";
 import "./CollectionTreeView.scss";
 import { CollectionView } from "./CollectionView";
@@ -77,7 +77,7 @@ class TreeView extends React.Component<TreeViewProps> {
      */
     renderTitle() {
         let reference = React.createRef<HTMLDivElement>();
-        let onItemDown = setupDrag(reference, () => this.props.document, this.props.moveDocument, this.props.copyOnDrag);
+        let onItemDown = SetupDrag(reference, () => this.props.document, this.props.moveDocument, this.props.copyOnDrag);
         let editableView = (titleString: string) =>
             (<EditableView
                 display={"inline"}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 649104d6c..06182d1a6 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -243,9 +243,6 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         if (de.data instanceof DragManager.LinkDragData) {
             let sourceDoc: Document = de.data.linkSourceDocument;
             let destDoc: Document = this.props.Document;
-            if (this.props.isTopMost) {
-                return;
-            }
             let linkDoc: Document = new Document();
 
             destDoc.GetTAsync(KeyStore.Prototype, Document).then(protoDest =>
-- 
cgit v1.2.3-70-g09d2


From 0afa18bfc219c597ad55a52ffc5a2086c3d110d2 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 12 Apr 2019 14:15:05 -0400
Subject: changed signatures of focus functions.

---
 src/Utils.ts                                       |  3 +++
 src/client/views/DocumentDecorations.tsx           |  2 +-
 src/client/views/Main.tsx                          |  8 ++++----
 .../views/collections/CollectionDockingView.tsx    |  4 ++--
 .../views/collections/CollectionSchemaView.tsx     |  8 +++-----
 src/client/views/nodes/FieldView.tsx               |  4 ++--
 src/client/views/nodes/KeyValuePair.tsx            |  4 ++--
 src/client/views/nodes/LinkBox.tsx                 | 24 ++++++++--------------
 8 files changed, 25 insertions(+), 32 deletions(-)

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

diff --git a/src/Utils.ts b/src/Utils.ts
index b0e66787e..ae194bcc7 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -2,6 +2,7 @@ import v4 = require('uuid/v4');
 import v5 = require("uuid/v5");
 import { Socket } from 'socket.io';
 import { Message, Types } from './server/Message';
+import { Document } from './fields/Document';
 
 export class Utils {
 
@@ -96,4 +97,6 @@ export function returnFalse() {
 
 export function emptyFunction() { }
 
+export function emptyDocFunction(doc: Document) { console.log("focus " + doc.Title) }
+
 export type Without<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
\ No newline at end of file
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 15ac0a8fc..c172e870e 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -244,7 +244,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
     }
 
     onLinkButtonMoved = async (e: PointerEvent) => {
-        if (this._linkButton.current !== null) {
+        if (this._linkButton.current !== null && (e.movementX > 1 || e.movementY > 1)) {
             document.removeEventListener("pointermove", this.onLinkButtonMoved);
             document.removeEventListener("pointerup", this.onLinkButtonUp);
 
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 60f7098fb..419de6fc1 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -15,7 +15,7 @@ import { ListField } from '../../fields/ListField';
 import { WorkspacesMenu } from '../../server/authentication/controllers/WorkspacesMenu';
 import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils';
 import { MessageStore } from '../../server/Message';
-import { Utils, returnTrue, emptyFunction } from '../../Utils';
+import { Utils, returnTrue, emptyFunction, emptyDocFunction } from '../../Utils';
 import * as rp from 'request-promise';
 import { RouteStore } from '../../server/RouteStore';
 import { ServerUtils } from '../../server/ServerUtil';
@@ -202,7 +202,6 @@ export class Main extends React.Component {
 
     pwidthFunc = () => this.pwidth;
     pheightFunc = () => this.pheight;
-    focusDocument = (doc: Document) => { };
     noScaling = () => 1;
 
     @observable _textDoc?: Document = undefined;
@@ -280,7 +279,8 @@ export class Main extends React.Component {
             s[0] = Math.sqrt((s[0] - t[0]) * (s[0] - t[0]) + (s[1] - t[1]) * (s[1] - t[1]));
             return <div className="mainDiv-textInput" style={{ pointerEvents: "none", transform: `translate(${x}px, ${y}px) scale(${1 / s[0]},${1 / s[0]})`, width: "auto", height: "auto" }} >
                 <div className="mainDiv-textInput" onPointerDown={this.textBoxDown} ref={this._textProxyDiv} onScroll={this.textScroll} style={{ pointerEvents: "none", transform: `scale(${1}, ${1})`, width: `${w * s[0]}px`, height: `${h * s[0]}px` }}>
-                    <FormattedTextBox fieldKey={this._textFieldKey!} isOverlay={true} Document={this._textDoc} isSelected={returnTrue} select={emptyFunction} isTopMost={true} selectOnLoad={true} onActiveChanged={emptyFunction} active={returnTrue} ScreenToLocalTransform={() => this._textXf} focus={(doc) => { }} />
+                    <FormattedTextBox fieldKey={this._textFieldKey!} isOverlay={true} Document={this._textDoc} isSelected={returnTrue} select={emptyFunction} isTopMost={true}
+                        selectOnLoad={true} onActiveChanged={emptyFunction} active={returnTrue} ScreenToLocalTransform={() => this._textXf} focus={emptyDocFunction} />
                 </div>
             </ div>;
         }
@@ -299,7 +299,7 @@ export class Main extends React.Component {
                 PanelHeight={this.pheightFunc}
                 isTopMost={true}
                 selectOnLoad={false}
-                focus={this.focusDocument}
+                focus={emptyDocFunction}
                 parentActive={returnTrue}
                 onActiveChanged={emptyFunction}
                 ContainingCollectionView={undefined} />;
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index e54c25474..77ffb4157 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -8,7 +8,7 @@ import { Document } from "../../../fields/Document";
 import { KeyStore } from "../../../fields/KeyStore";
 import Measure from "react-measure";
 import { FieldId, Opt, Field, FieldWaiting } from "../../../fields/Field";
-import { Utils, returnTrue, emptyFunction } from "../../../Utils";
+import { Utils, returnTrue, emptyFunction, emptyDocFunction } from "../../../Utils";
 import { Server } from "../../Server";
 import { undoBatch } from "../../util/UndoManager";
 import { DocumentView } from "../nodes/DocumentView";
@@ -350,7 +350,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
                     selectOnLoad={false}
                     parentActive={returnTrue}
                     onActiveChanged={emptyFunction}
-                    focus={(doc: Document) => { }}
+                    focus={emptyDocFunction}
                     ContainingCollectionView={undefined} />
             </div>;
 
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index f53b2a76e..4cf187963 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -26,7 +26,7 @@ import { CollectionView } from "./CollectionView";
 import { CollectionSubView } from "./CollectionSubView";
 import { TextField } from "../../../fields/TextField";
 import * as globalCssVariables from "../../views/globalCssVariables.scss";
-import { emptyFunction, returnFalse } from "../../../Utils";
+import { emptyFunction, returnFalse, emptyDocFunction } from "../../../Utils";
 
 
 // bcz: need to add drag and drop of rows and columns.  This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657
@@ -82,7 +82,7 @@ export class CollectionSchemaView extends CollectionSubView {
             isTopMost: false,
             selectOnLoad: false,
             ScreenToLocalTransform: Transform.Identity,
-            focus: emptyFunction,
+            focus: emptyDocFunction,
             active: returnFalse,
             onActiveChanged: emptyFunction,
         };
@@ -253,8 +253,6 @@ export class CollectionSchemaView extends CollectionSubView {
     getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH - this._dividerX, - this.borderWidth).scale(1 / this._contentScaling);
     getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH - this._dividerX - this._tableWidth, - this.borderWidth).scale(1 / this._contentScaling);
 
-    focusDocument = (doc: Document) => { };
-
     onPointerDown = (e: React.PointerEvent): void => {
         if (e.button === 1 && this.props.isSelected() && !e.altKey && !e.ctrlKey && !e.metaKey) {
             e.stopPropagation();
@@ -317,7 +315,7 @@ export class CollectionSchemaView extends CollectionSubView {
                                 PanelWidth={this.getPanelWidth}
                                 PanelHeight={this.getPanelHeight}
                                 ContainingCollectionView={undefined}
-                                focus={this.focusDocument}
+                                focus={emptyDocFunction}
                                 parentActive={this.props.active}
                                 onActiveChanged={this.props.onActiveChanged} /> : null}
                         <input value={this.previewScript} onChange={this.onPreviewScriptChange}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 40b44aae5..0037d7b28 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -19,7 +19,7 @@ import { ListField } from "../../../fields/ListField";
 import { DocumentContentsView } from "./DocumentContentsView";
 import { Transform } from "../../util/Transform";
 import { KeyStore } from "../../../fields/KeyStore";
-import { returnFalse, emptyFunction } from "../../../Utils";
+import { returnFalse, emptyDocFunction } from "../../../Utils";
 
 
 //
@@ -85,7 +85,7 @@ export class FieldView extends React.Component<FieldViewProps> {
                     PanelHeight={() => 100}
                     isTopMost={true} //TODO Why is this top most?
                     selectOnLoad={false}
-                    focus={emptyFunction}
+                    focus={emptyDocFunction}
                     isSelected={returnFalse}
                     select={returnFalse}
                     layoutKey={KeyStore.Layout}
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index a1050dc6e..7f43d8fdf 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -12,7 +12,7 @@ import { Server } from "../../Server";
 import { EditableView } from "../EditableView";
 import { CompileScript, ToField } from "../../util/Scripting";
 import { Transform } from '../../util/Transform';
-import { returnFalse, emptyFunction } from '../../../Utils';
+import { returnFalse, emptyFunction, emptyDocFunction } from '../../../Utils';
 
 // Represents one row in a key value plane
 
@@ -54,7 +54,7 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
             active: returnFalse,
             onActiveChanged: emptyFunction,
             ScreenToLocalTransform: Transform.Identity,
-            focus: emptyFunction,
+            focus: emptyDocFunction,
         };
         let contents = (
             <FieldView {...props} />
diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx
index b016a3d48..1c0e316e8 100644
--- a/src/client/views/nodes/LinkBox.tsx
+++ b/src/client/views/nodes/LinkBox.tsx
@@ -1,24 +1,16 @@
-import { observable, computed, action } from "mobx";
-import React = require("react");
-import { SelectionManager } from "../../util/SelectionManager";
+import { library } from '@fortawesome/fontawesome-svg-core';
+import { faEdit, faEye, faTimes } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { observer } from "mobx-react";
-import './LinkBox.scss';
-import { KeyStore } from '../../../fields/KeyStore';
-import { props } from "bluebird";
-import { DocumentView } from "./DocumentView";
 import { Document } from "../../../fields/Document";
+import { KeyStore } from '../../../fields/KeyStore';
 import { ListField } from "../../../fields/ListField";
+import { NumberField } from "../../../fields/NumberField";
 import { DocumentManager } from "../../util/DocumentManager";
-import { LinkEditor } from "./LinkEditor";
-import { CollectionDockingView } from "../collections/CollectionDockingView";
-import { library } from '@fortawesome/fontawesome-svg-core';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { faEye } from '@fortawesome/free-solid-svg-icons';
-import { faEdit } from '@fortawesome/free-solid-svg-icons';
-import { faTimes } from '@fortawesome/free-solid-svg-icons';
 import { undoBatch } from "../../util/UndoManager";
-import { FieldWaiting } from "../../../fields/Field";
-import { NumberField } from "../../../fields/NumberField";
+import { CollectionDockingView } from "../collections/CollectionDockingView";
+import './LinkBox.scss';
+import React = require("react");
 
 
 library.add(faEye);
-- 
cgit v1.2.3-70-g09d2


From 83f269b77aa23b641c0ec6b09fe5696936fb221b Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 12 Apr 2019 16:38:13 -0400
Subject: added undo for creating links.  cleaned up some other code.

---
 .../views/collections/CollectionSchemaView.tsx     | 12 +++--
 src/client/views/collections/CollectionSubView.tsx | 51 +++++++++-------------
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  4 +-
 src/client/views/nodes/DocumentView.tsx            | 14 ++++--
 4 files changed, 38 insertions(+), 43 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 4cf187963..162a39170 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -2,16 +2,17 @@ import React = require("react");
 import { library } from '@fortawesome/fontawesome-svg-core';
 import { faCog, faPlus } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, observable, trace, untracked } from "mobx";
+import { action, computed, observable, untracked } from "mobx";
 import { observer } from "mobx-react";
 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, Opt, FieldWaiting } from "../../../fields/Field";
+import { Field, Opt } from "../../../fields/Field";
 import { Key } from "../../../fields/Key";
 import { KeyStore } from "../../../fields/KeyStore";
 import { ListField } from "../../../fields/ListField";
+import { emptyDocFunction, emptyFunction, returnFalse } from "../../../Utils";
 import { Server } from "../../Server";
 import { SetupDrag } from "../../util/DragManager";
 import { CompileScript, ToField } from "../../util/Scripting";
@@ -22,11 +23,8 @@ import { EditableView } from "../EditableView";
 import { DocumentView } from "../nodes/DocumentView";
 import { FieldView, FieldViewProps } from "../nodes/FieldView";
 import "./CollectionSchemaView.scss";
-import { CollectionView } from "./CollectionView";
 import { CollectionSubView } from "./CollectionSubView";
-import { TextField } from "../../../fields/TextField";
-import * as globalCssVariables from "../../views/globalCssVariables.scss";
-import { emptyFunction, returnFalse, emptyDocFunction } from "../../../Utils";
+import { COLLECTION_BORDER_WIDTH } from "../../views/globalCssVariables.scss";
 
 
 // bcz: need to add drag and drop of rows and columns.  This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657
@@ -246,7 +244,7 @@ export class CollectionSchemaView extends CollectionSubView {
     }
 
     @computed
-    get borderWidth() { return globalCssVariables.COLLECTION_BORDER_WIDTH; }
+    get borderWidth() { return COLLECTION_BORDER_WIDTH; }
     getContentScaling = (): number => this._contentScaling;
     getPanelWidth = (): number => this._panelWidth;
     getPanelHeight = (): number => this._panelHeight;
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 6a6a6c900..d91db68bb 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -166,22 +166,16 @@ export class CollectionSubView extends React.Component<SubCollectionViewProps> {
             let item = e.dataTransfer.items[i];
             if (item.kind === "string" && item.type.indexOf("uri") !== -1) {
                 let str: string;
-                let prom = new Promise<string>(res =>
-                    e.dataTransfer.items[i].getAsString(res)).then(action((s: string) => {
-                        str = s;
-                        return rp.head(ServerUtils.prepend(RouteStore.corsProxy + "/" + s));
-                    })).then(res => {
-                        let type = res.headers["content-type"];
+                let prom = new Promise<string>(resolve => e.dataTransfer.items[i].getAsString(resolve))
+                    .then(action((s: string) => rp.head(ServerUtils.prepend(RouteStore.corsProxy + "/" + (str = s)))))
+                    .then(result => {
+                        let type = result.headers["content-type"];
                         if (type) {
-                            this.getDocumentFromType(type, str, { ...options, width: 300, nativeWidth: 300 }).then(doc => {
-                                if (doc) {
-                                    this.props.addDocument(doc, false);
-                                }
-                            });
+                            this.getDocumentFromType(type, str, { ...options, width: 300, nativeWidth: 300 })
+                                .then(doc => doc && this.props.addDocument(doc, false));
                         }
                     });
                 promises.push(prom);
-                // this.props.addDocument(Documents.WebDocument(s, { ...options, width: 300, height: 300 }), false)
             }
             let type = item.type;
             if (item.kind === "file") {
@@ -197,33 +191,30 @@ export class CollectionSubView extends React.Component<SubCollectionViewProps> {
                     method: 'POST',
                     body: formData
                 }).then(async (res: Response) => {
-                    const json = await res.json();
-                    json.map((file: any) => {
+                    (await res.json()).map(action((file: any) => {
                         let path = window.location.origin + file;
-                        runInAction(() => {
-                            let docPromise = this.getDocumentFromType(type, path, { ...options, nativeWidth: 300, width: 300, title: dropFileName });
+                        let docPromise = this.getDocumentFromType(type, path, { ...options, nativeWidth: 300, width: 300, title: dropFileName });
 
-                            docPromise.then(doc => runInAction(() => {
-                                let docs = this.props.Document.GetT(KeyStore.Data, ListField);
-                                if (docs !== FieldWaiting) {
-                                    if (!docs) {
-                                        docs = new ListField<Document>();
-                                        this.props.Document.Set(KeyStore.Data, docs);
-                                    }
-                                    if (doc) {
-                                        docs.Data.push(doc);
-                                    }
+                        docPromise.then(action((doc?: Document) => {
+                            let docs = this.props.Document.GetT(KeyStore.Data, ListField);
+                            if (docs !== FieldWaiting) {
+                                if (!docs) {
+                                    docs = new ListField<Document>();
+                                    this.props.Document.Set(KeyStore.Data, docs);
                                 }
-                            }));
-                        });
-                    });
+                                if (doc) {
+                                    docs.Data.push(doc);
+                                }
+                            }
+                        }));
+                    }));
                 });
                 promises.push(prom);
             }
         }
 
         if (promises.length) {
-            Promise.all(promises).catch(emptyFunction).then(() => batch.end());
+            Promise.all(promises).finally(() => batch.end());
         } else {
             batch.end();
         }
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index dae62f126..98ebbf1b3 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -12,7 +12,7 @@ import { DragManager } from "../../../util/DragManager";
 import { SelectionManager } from "../../../util/SelectionManager";
 import { Transform } from "../../../util/Transform";
 import { undoBatch } from "../../../util/UndoManager";
-import * as globalCssVariables from "../../../views/globalCssVariables.scss";
+import { COLLECTION_BORDER_WIDTH } from "../../../views/globalCssVariables.scss";
 import { InkingCanvas } from "../../InkingCanvas";
 import { Main } from "../../Main";
 import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDocumentView";
@@ -299,7 +299,7 @@ export class CollectionFreeFormView extends CollectionSubView {
 
     @computed
     get borderWidth() {
-        return this.isAnnotationOverlay ? 0 : globalCssVariables.COLLECTION_BORDER_WIDTH;
+        return this.isAnnotationOverlay ? 0 : COLLECTION_BORDER_WIDTH;
     }
     getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth, -this.borderWidth).translate(-this.centeringShiftX, -this.centeringShiftY).transform(this.getLocalTransform());
     getContainerTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth, -this.borderWidth);
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 06182d1a6..4d7a85316 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -20,6 +20,7 @@ import { ContextMenu } from "../ContextMenu";
 import { DocumentContentsView } from "./DocumentContentsView";
 import "./DocumentView.scss";
 import React = require("react");
+import { undoBatch, UndoManager } from "../../util/UndoManager";
 
 
 export interface DocumentViewProps {
@@ -238,6 +239,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         SelectionManager.DeselectAll();
     }
 
+    @undoBatch
     @action
     drop = (e: Event, de: DragManager.DropEvent) => {
         if (de.data instanceof DragManager.LinkDragData) {
@@ -248,6 +250,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
             destDoc.GetTAsync(KeyStore.Prototype, Document).then(protoDest =>
                 sourceDoc.GetTAsync(KeyStore.Prototype, Document).then(protoSrc =>
                     runInAction(() => {
+                        let batch = UndoManager.StartBatch("document view drop");
                         linkDoc.Set(KeyStore.Title, new TextField("New Link"));
                         linkDoc.Set(KeyStore.LinkDescription, new TextField(""));
                         linkDoc.Set(KeyStore.LinkTags, new TextField("Default"));
@@ -256,20 +259,23 @@ export class DocumentView extends React.Component<DocumentViewProps> {
                         let srcTarg = protoSrc ? protoSrc : sourceDoc;
                         linkDoc.Set(KeyStore.LinkedToDocs, dstTarg);
                         linkDoc.Set(KeyStore.LinkedFromDocs, srcTarg);
-                        dstTarg.GetOrCreateAsync(
+                        const prom1 = new Promise(resolve => dstTarg.GetOrCreateAsync(
                             KeyStore.LinkedFromDocs,
                             ListField,
                             field => {
                                 (field as ListField<Document>).Data.push(linkDoc);
+                                resolve();
                             }
-                        );
-                        srcTarg.GetOrCreateAsync(
+                        ));
+                        const prom2 = new Promise(resolve => srcTarg.GetOrCreateAsync(
                             KeyStore.LinkedToDocs,
                             ListField,
                             field => {
                                 (field as ListField<Document>).Data.push(linkDoc);
+                                resolve();
                             }
-                        );
+                        ));
+                        Promise.all([prom1, prom2]).finally(() => batch.end());
                     })
                 )
             );
-- 
cgit v1.2.3-70-g09d2


From 0737a14e2c436ab9613c638bcebdc5480df1d4d4 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sat, 13 Apr 2019 00:23:44 -0400
Subject: repairs to keyvaluebox

---
 .../views/collections/CollectionSchemaView.tsx     |  2 +-
 .../collectionFreeForm/CollectionFreeFormView.scss | 10 +--
 .../collectionFreeForm/MarqueeView.scss            |  2 +-
 src/client/views/nodes/DocumentView.scss           |  2 +-
 src/client/views/nodes/KeyValueBox.scss            | 91 ++++++++++++++++++----
 src/client/views/nodes/KeyValueBox.tsx             | 53 ++++++++++---
 src/client/views/nodes/KeyValuePair.scss           | 20 ++++-
 src/client/views/nodes/KeyValuePair.tsx            | 56 ++++++-------
 8 files changed, 175 insertions(+), 61 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 162a39170..fdb82690a 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -17,6 +17,7 @@ import { Server } from "../../Server";
 import { SetupDrag } from "../../util/DragManager";
 import { CompileScript, ToField } from "../../util/Scripting";
 import { Transform } from "../../util/Transform";
+import { COLLECTION_BORDER_WIDTH } from "../../views/globalCssVariables.scss";
 import { anchorPoints, Flyout } from "../DocumentDecorations";
 import '../DocumentDecorations.scss';
 import { EditableView } from "../EditableView";
@@ -24,7 +25,6 @@ import { DocumentView } from "../nodes/DocumentView";
 import { FieldView, FieldViewProps } from "../nodes/FieldView";
 import "./CollectionSchemaView.scss";
 import { CollectionSubView } from "./CollectionSubView";
-import { COLLECTION_BORDER_WIDTH } from "../../views/globalCssVariables.scss";
 
 
 // bcz: need to add drag and drop of rows and columns.  This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
index f3ac4a383..26c794e91 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
@@ -1,13 +1,13 @@
 @import "../../globalCssVariables";
 .collectionfreeformview-measure {
-    position: absolute;
+    position: inherit;
     top: 0;
     left: 0;
     width: 100%;
     height: 100%;
   }
 .collectionfreeformview {
-  position: absolute;
+  position: inherit;
   top: 0;
   left: 0;
   width: 100%;
@@ -16,7 +16,7 @@
 }
 .collectionfreeformview-container {
   .collectionfreeformview > .jsx-parser {
-    position: absolute;
+    position: inherit;
     height: 100%;
     width: 100%;
   }
@@ -43,7 +43,7 @@
 }
 .collectionfreeformview-overlay {
   .collectionfreeformview > .jsx-parser {
-    position: absolute;
+    position: inherit;
     height: 100%;
   }
   .formattedTextBox-cont {
@@ -56,7 +56,7 @@
   border-style: solid; 
   border-radius: $border-radius;
   box-sizing: border-box;
-  position:absolute;
+  position: absolute;
   overflow: hidden;
   top: 0;
   left: 0;
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.scss b/src/client/views/collections/collectionFreeForm/MarqueeView.scss
index 0b406e722..e5ffcec76 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.scss
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.scss
@@ -1,6 +1,6 @@
 
 .marqueeView {
-    position: absolute;
+    position: inherit;
     top:0;
     left:0;
     width:100%;
diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss
index 039d1bcc6..a946ac1a8 100644
--- a/src/client/views/nodes/DocumentView.scss
+++ b/src/client/views/nodes/DocumentView.scss
@@ -1,7 +1,7 @@
 @import "../globalCssVariables";
 
 .documentView-node {
-  position: absolute;
+  position: inherit;
   top: 0;
   left:0;
   background: $light-color; //overflow: hidden;
diff --git a/src/client/views/nodes/KeyValueBox.scss b/src/client/views/nodes/KeyValueBox.scss
index f60edc675..6ebd73f2c 100644
--- a/src/client/views/nodes/KeyValueBox.scss
+++ b/src/client/views/nodes/KeyValueBox.scss
@@ -1,6 +1,7 @@
 @import "../globalCssVariables";
 .keyValueBox-cont {
     overflow-y: scroll;
+    width:100%;
     height: 100%;
     background-color: $light-color;
     border: 1px solid $intermediate-color;
@@ -8,31 +9,58 @@
     box-sizing: border-box;
     display: inline-block;
     .imageBox-cont img {
-        max-height: 45px;
-        height: auto;
-    }
-    td {
-        padding: 6px 8px;
-        border-right: 1px solid $intermediate-color;
-        border-top: 1px solid $intermediate-color;
-        &:last-child {
-            border-right: none;
-        }
+        width: auto;
     }
 }
+$header-height: 30px;
+.keyValueBox-tbody {
+    width:100%;
+    height:100%;
+    position: absolute;
+    overflow-y: scroll;
+}
+.keyValueBox-key {
+    display: inline-block;
+    height:100%;
+    width:50%;
+    text-align: center;
+}
+.keyValueBox-fields {
+    display: inline-block;
+    height:100%;
+    width:50%;
+    text-align: center;
+}
 
 .keyValueBox-table {
-    position: relative;
+    position: absolute;
+    width:100%;
+    height:100%;
     border-collapse: collapse;
 }
-
+.keyValueBox-td-key {
+    display:inline-block;
+    height:30px;
+}
+.keyValueBox-td-value {
+    display:inline-block;
+    height:30px;
+}
+.keyValueBox-valueRow {
+    width:100%;
+    height:30px;
+    display: inline-block;
+}
 .keyValueBox-header {
+    width:100%;
+    position: relative;
+    display: inline-block;
     background: $intermediate-color;
     color: $light-color;
     text-transform: uppercase;
     letter-spacing: 2px;
     font-size: 12px;
-    height: 30px;
+    height: $header-height;
     padding-top: 4px;
     th {
         font-weight: normal;
@@ -43,13 +71,50 @@
 }
 
 .keyValueBox-evenRow {
+    position: relative;
+    display: inline-block;
+    width:100%;
+    height:$header-height;
     background: $light-color;
     .formattedTextBox-cont {
         background: $light-color;
     }
 }
+.keyValueBox-cont {
+    .collectionfreeformview-overlay {
+        position: relative;
+    }
+}
+.keyValueBox-dividerDraggerThumb{
+    position: relative;
+    width: 4px;
+    float: left; 
+    height: 30px;
+    width: 10px;
+    z-index: 20;
+    right: 0;
+    top: 0;
+    border-radius: 10px;
+    background: gray;
+    pointer-events: all;
+}
+.keyValueBox-dividerDragger{
+    position: relative; 
+    width: 100%;
+    float: left; 
+    height: 37px;
+    z-index: 20;
+    right: 0;
+    top: 0;
+    background: transparent;
+    pointer-events: none;
+}
 
 .keyValueBox-oddRow {
+    position: relative;
+    display: inline-block;
+    width:100%;
+    height:30px;
     background: $light-color-secondary;
     .formattedTextBox-cont {
         background: $light-color-secondary;
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index bcac113f0..29e4af160 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -1,23 +1,25 @@
 
+import { action, computed, observable } from "mobx";
 import { observer } from "mobx-react";
 import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app
 import { Document } from '../../../fields/Document';
-import { FieldWaiting, Field } from '../../../fields/Field';
+import { Field, FieldWaiting } from '../../../fields/Field';
+import { Key } from '../../../fields/Key';
 import { KeyStore } from '../../../fields/KeyStore';
+import { CompileScript, ToField } from "../../util/Scripting";
 import { FieldView, FieldViewProps } from './FieldView';
 import "./KeyValueBox.scss";
 import { KeyValuePair } from "./KeyValuePair";
 import React = require("react");
-import { CompileScript, ToField } from "../../util/Scripting";
-import { Key } from '../../../fields/Key';
-import { observable, action } from "mobx";
 
 @observer
 export class KeyValueBox extends React.Component<FieldViewProps> {
+    private _mainCont = React.createRef<HTMLDivElement>();
 
     public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(KeyValueBox, fieldStr); }
     @observable private _keyInput: string = "";
     @observable private _valueInput: string = "";
+    @computed get splitPercentage() { return this.props.Document.GetNumber(KeyStore.SchemaSplitPercentage, 50); }
 
 
     constructor(props: FieldViewProps) {
@@ -90,7 +92,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
         let rows: JSX.Element[] = [];
         let i = 0;
         for (let key in ids) {
-            rows.push(<KeyValuePair doc={realDoc} rowStyle={"keyValueBox-" + (i++ % 2 ? "oddRow" : "evenRow")} fieldId={key} key={key} />);
+            rows.push(<KeyValuePair doc={realDoc} keyWidth={100 - this.splitPercentage} rowStyle={"keyValueBox-" + (i++ % 2 ? "oddRow" : "evenRow")} fieldId={key} key={key} />);
         }
         return rows;
     }
@@ -107,24 +109,51 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
 
     newKeyValue = () =>
         (
-            <tr>
-                <td><input type="text" value={this._keyInput} placeholder="Key" onChange={this.keyChanged} /></td>
-                <td><input type="text" value={this._valueInput} placeholder="Value" onChange={this.valueChanged} onKeyPress={this.onEnterKey} /></td>
+            <tr className="keyValueBox-valueRow">
+                <td className="keyValueBox-td-key" style={{ width: `${100 - this.splitPercentage}%` }}>
+                    <input style={{ width: "100%" }} type="text" value={this._keyInput} placeholder="Key" onChange={this.keyChanged} />
+                </td>
+                <td className="keyValueBox-td-value" style={{ width: `${this.splitPercentage}%` }}>
+                    <input style={{ width: "100%" }} type="text" value={this._valueInput} placeholder="Value" onChange={this.valueChanged} onKeyPress={this.onEnterKey} />
+                </td>
             </tr>
         )
 
+    @action
+    onDividerMove = (e: PointerEvent): void => {
+        let nativeWidth = this._mainCont.current!.getBoundingClientRect();
+        this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, Math.max(0, 100 - Math.round((e.clientX - nativeWidth.left) / nativeWidth.width * 100)));
+    }
+    @action
+    onDividerUp = (e: PointerEvent): void => {
+        document.removeEventListener("pointermove", this.onDividerMove);
+        document.removeEventListener('pointerup', this.onDividerUp);
+    }
+    onDividerDown = (e: React.PointerEvent) => {
+        e.stopPropagation();
+        e.preventDefault();
+        document.addEventListener("pointermove", this.onDividerMove);
+        document.addEventListener('pointerup', this.onDividerUp);
+    }
+
     render() {
-        return (<div className="keyValueBox-cont" onWheel={this.onPointerWheel}>
+        let dividerDragger = this.splitPercentage === 0 ? (null) :
+            <div className="keyValueBox-dividerDragger" style={{ transform: `translate(calc(${100 - this.splitPercentage}% - 5px), 0px)` }}>
+                <div className="keyValueBox-dividerDraggerThumb" onPointerDown={this.onDividerDown} />
+            </div>;
+
+        return (<div className="keyValueBox-cont" onWheel={this.onPointerWheel} ref={this._mainCont}>
             <table className="keyValueBox-table">
-                <tbody>
+                <tbody className="keyValueBox-tbody">
                     <tr className="keyValueBox-header">
-                        <th>Key</th>
-                        <th>Fields</th>
+                        <th className="keyValueBox-key" style={{ width: `${100 - this.splitPercentage}%` }}>Key</th>
+                        <th className="keyValueBox-fields" style={{ width: `${this.splitPercentage}%` }}>Fields</th>
                     </tr>
                     {this.createTable()}
                     {this.newKeyValue()}
                 </tbody>
             </table>
+            {dividerDragger}
         </div>);
     }
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/KeyValuePair.scss b/src/client/views/nodes/KeyValuePair.scss
index 0bb92e5a3..04d002c7b 100644
--- a/src/client/views/nodes/KeyValuePair.scss
+++ b/src/client/views/nodes/KeyValuePair.scss
@@ -1,12 +1,30 @@
 @import "../globalCssVariables";
 
 .container{
+    width:100%;
+    height:100%;
     display: flex;                 
     flex-direction: row;           
     flex-wrap: nowrap;              
     justify-content: space-between; 
 }
 
+.keyValuePair-td-key {
+    display:inline-block;
+    width: 50%;
+}
+.keyValuePair-td-value {
+    display:inline-block;
+    width: 50%;
+}
+.keyValuePair-keyField {
+    width:100%;
+    text-align: center;
+    position: relative;
+    overflow: auto;
+}
 .delete{
-    color: red;
+    position: relative;
+    background-color: transparent;
+    color:red;
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index 7f43d8fdf..3e0b61c3d 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -20,6 +20,7 @@ export interface KeyValuePairProps {
     rowStyle: string;
     fieldId: string;
     doc: Document;
+    keyWidth: number;
 }
 @observer
 export class KeyValuePair extends React.Component<KeyValuePairProps> {
@@ -61,45 +62,46 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
         );
         return (
             <tr className={this.props.rowStyle}>
-                {/* <button>X</button> */}
-                <td>
+                <td className="keyValuePair-td-key" style={{ width: `${this.props.keyWidth}%` }}>
                     <div className="container">
-                        <div>{this.key.Name}</div>
                         <button className="delete" onClick={() => {
                             let field = props.Document.Get(props.fieldKey);
                             if (field && field instanceof Field) {
                                 props.Document.Set(props.fieldKey, undefined);
                             }
                         }}>X</button>
+                        <div className="keyValuePair-keyField">{this.key.Name}</div>
                     </div>
                 </td>
-                <td><EditableView contents={contents} height={36} GetValue={() => {
-                    let field = props.Document.Get(props.fieldKey);
-                    if (field && field instanceof Field) {
-                        return field.ToScriptString();
-                    }
-                    return field || "";
-                }}
-                    SetValue={(value: string) => {
-                        let script = CompileScript(value, { addReturn: true });
-                        if (!script.compiled) {
-                            return false;
+                <td className="keyValuePair-td-value" style={{ width: `${100 - this.props.keyWidth}%` }}>
+                    <EditableView contents={contents} height={36} GetValue={() => {
+                        let field = props.Document.Get(props.fieldKey);
+                        if (field && field instanceof Field) {
+                            return field.ToScriptString();
                         }
-                        let res = script.run();
-                        if (!res.success) return false;
-                        const field = res.result;
-                        if (field instanceof Field) {
-                            props.Document.Set(props.fieldKey, field);
-                            return true;
-                        } else {
-                            let dataField = ToField(field);
-                            if (dataField) {
-                                props.Document.Set(props.fieldKey, dataField);
+                        return field || "";
+                    }}
+                        SetValue={(value: string) => {
+                            let script = CompileScript(value, { addReturn: true });
+                            if (!script.compiled) {
+                                return false;
+                            }
+                            let res = script.run();
+                            if (!res.success) return false;
+                            const field = res.result;
+                            if (field instanceof Field) {
+                                props.Document.Set(props.fieldKey, field);
                                 return true;
+                            } else {
+                                let dataField = ToField(field);
+                                if (dataField) {
+                                    props.Document.Set(props.fieldKey, dataField);
+                                    return true;
+                                }
                             }
-                        }
-                        return false;
-                    }}></EditableView></td>
+                            return false;
+                        }}>
+                    </EditableView></td>
             </tr>
         );
     }
-- 
cgit v1.2.3-70-g09d2


From 7e05ea0058766a3afa2ec82f6312f2df87178883 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sun, 14 Apr 2019 12:23:10 -0400
Subject: starting to add LOD

---
 src/client/views/Main.tsx                          |  1 +
 .../views/collections/CollectionBaseView.tsx       |  6 +-
 .../views/collections/CollectionDockingView.tsx    |  1 +
 .../views/collections/CollectionSchemaView.tsx     |  1 +
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 72 +++++++++++++---------
 .../views/nodes/CollectionFreeFormDocumentView.tsx | 13 ++--
 src/client/views/nodes/DocumentView.tsx            |  1 +
 src/client/views/nodes/FieldView.tsx               |  1 +
 src/fields/KeyStore.ts                             |  1 +
 9 files changed, 57 insertions(+), 40 deletions(-)

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

diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index ed61aa5a7..babd3be2a 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -295,6 +295,7 @@ export class Main extends React.Component {
             <DocumentView Document={this.mainContainer}
                 addDocument={undefined}
                 removeDocument={undefined}
+                opacity={1}
                 ScreenToLocalTransform={Transform.Identity}
                 ContentScaling={this.noScaling}
                 PanelWidth={this.pwidthFunc}
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index b5eaab349..bff56e8c3 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -1,4 +1,4 @@
-import { action } from 'mobx';
+import { action, computed } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Document } from '../../../fields/Document';
@@ -80,12 +80,16 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         }
         return false;
     }
+    @computed get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldKey.Id === KeyStore.Annotations.Id; } // bcz: ? Why do we need to compare Id's?
 
     @action.bound
     addDocument(doc: Document, allowDuplicates: boolean = false): boolean {
         let props = this.props;
         var curPage = props.Document.GetNumber(KeyStore.CurPage, -1);
         doc.SetOnPrototype(KeyStore.Page, new NumberField(curPage));
+        if (this.isAnnotationOverlay) {
+            doc.SetOnPrototype(KeyStore.Zoom, new NumberField(this.props.Document.GetNumber(KeyStore.Scale, 1)));
+        }
         if (curPage >= 0) {
             doc.SetOnPrototype(KeyStore.AnnotationOn, props.Document);
         }
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index eb1cd1c09..6d772b90e 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -343,6 +343,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
                 <DocumentView key={this._document.Id} Document={this._document}
                     addDocument={undefined}
                     removeDocument={undefined}
+                    opacity={1}
                     ContentScaling={this._contentScaling}
                     PanelWidth={this._nativeWidth}
                     PanelHeight={this._nativeHeight}
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index fdb82690a..2a1d1dd94 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -307,6 +307,7 @@ export class CollectionSchemaView extends CollectionSubView {
                             <DocumentView Document={doc}
                                 addDocument={this.props.addDocument} removeDocument={this.props.removeDocument}
                                 isTopMost={false}
+                                opacity={1}
                                 selectOnLoad={false}
                                 ScreenToLocalTransform={this.getPreviewTransform}
                                 ContentScaling={this.getContentScaling}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 0da6fe49c..94945bde6 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1,4 +1,4 @@
-import { action, computed, observable, runInAction } from "mobx";
+import { action, computed, observable, runInAction, untracked } from "mobx";
 import { observer } from "mobx-react";
 import Measure from "react-measure";
 import { Document } from "../../../../fields/Document";
@@ -37,8 +37,12 @@ export class CollectionFreeFormView extends CollectionSubView {
         this.addDocument(newBox, false);
     }
 
-    public addDocument = (newBox: Document, allowDuplicates: boolean) =>
-        this.props.addDocument(this.bringToFront(newBox), false)
+    public addDocument = (newBox: Document, allowDuplicates: boolean) => {
+        if (this.isAnnotationOverlay) {
+            newBox.SetNumber(KeyStore.Zoom, this.props.Document.GetNumber(KeyStore.Scale, 1));
+        }
+        return this.props.addDocument(this.bringToFront(newBox), false);
+    }
 
     public selectDocuments = (docs: Document[]) => {
         SelectionManager.DeselectAll;
@@ -131,25 +135,27 @@ export class CollectionFreeFormView extends CollectionSubView {
                 let x = this.props.Document.GetNumber(KeyStore.PanX, 0);
                 let y = this.props.Document.GetNumber(KeyStore.PanY, 0);
                 let docs = this.props.Document.GetList(this.props.fieldKey, [] as Document[]);
-                let minx = docs.length ? docs[0].GetNumber(KeyStore.X, 0) : 0;
-                let maxx = docs.length ? docs[0].GetNumber(KeyStore.Width, 0) + minx : minx;
-                let miny = docs.length ? docs[0].GetNumber(KeyStore.Y, 0) : 0;
-                let maxy = docs.length ? docs[0].GetNumber(KeyStore.Height, 0) + miny : miny;
-                let ranges = docs.filter(doc => doc).reduce((range, doc) => {
-                    let x = doc.GetNumber(KeyStore.X, 0);
-                    let xe = x + doc.GetNumber(KeyStore.Width, 0);
-                    let y = doc.GetNumber(KeyStore.Y, 0);
-                    let ye = y + doc.GetNumber(KeyStore.Height, 0);
-                    return [[range[0][0] > x ? x : range[0][0], range[0][1] < xe ? xe : range[0][1]],
-                    [range[1][0] > y ? y : range[1][0], range[1][1] < ye ? ye : range[1][1]]];
-                }, [[minx, maxx], [miny, maxy]]);
-                let panelwidth = this._pwidth / this.scale / 2;
-                let panelheight = this._pheight / this.scale / 2;
                 let [dx, dy] = this.getTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY);
-                if (x - dx < ranges[0][0] - panelwidth) x = ranges[0][1] + panelwidth + dx;
-                if (x - dx > ranges[0][1] + panelwidth) x = ranges[0][0] - panelwidth + dx;
-                if (y - dy < ranges[1][0] - panelheight) y = ranges[1][1] + panelheight + dy;
-                if (y - dy > ranges[1][1] + panelheight) y = ranges[1][0] - panelheight + dy;
+                if (!this.isAnnotationOverlay) {
+                    let minx = docs.length ? docs[0].GetNumber(KeyStore.X, 0) : 0;
+                    let maxx = docs.length ? docs[0].GetNumber(KeyStore.Width, 0) + minx : minx;
+                    let miny = docs.length ? docs[0].GetNumber(KeyStore.Y, 0) : 0;
+                    let maxy = docs.length ? docs[0].GetNumber(KeyStore.Height, 0) + miny : miny;
+                    let ranges = docs.filter(doc => doc).reduce((range, doc) => {
+                        let x = doc.GetNumber(KeyStore.X, 0);
+                        let xe = x + doc.GetNumber(KeyStore.Width, 0);
+                        let y = doc.GetNumber(KeyStore.Y, 0);
+                        let ye = y + doc.GetNumber(KeyStore.Height, 0);
+                        return [[range[0][0] > x ? x : range[0][0], range[0][1] < xe ? xe : range[0][1]],
+                        [range[1][0] > y ? y : range[1][0], range[1][1] < ye ? ye : range[1][1]]];
+                    }, [[minx, maxx], [miny, maxy]]);
+                    let panelwidth = this._pwidth / this.scale / 2;
+                    let panelheight = this._pheight / this.scale / 2;
+                    if (x - dx < ranges[0][0] - panelwidth) x = ranges[0][1] + panelwidth + dx;
+                    if (x - dx > ranges[0][1] + panelwidth) x = ranges[0][0] - panelwidth + dx;
+                    if (y - dy < ranges[1][0] - panelheight) y = ranges[1][1] + panelheight + dy;
+                    if (y - dy > ranges[1][1] + panelheight) y = ranges[1][0] - panelheight + dy;
+                }
                 this.SetPan(x - dx, y - dy);
                 this._lastX = e.pageX;
                 this._lastY = e.pageY;
@@ -161,9 +167,9 @@ export class CollectionFreeFormView extends CollectionSubView {
 
     @action
     onPointerWheel = (e: React.WheelEvent): void => {
-        if (!this.props.active()) {
-            return;
-        }
+        // if (!this.props.active()) {
+        //     return;
+        // }
         e.stopPropagation();
         let coefficient = 1000;
 
@@ -255,9 +261,10 @@ export class CollectionFreeFormView extends CollectionSubView {
         this.props.focus(this.props.Document);
     }
 
-    getDocumentViewProps(document: Document): DocumentViewProps {
+    getDocumentViewProps(document: Document, opacity: number): DocumentViewProps {
         return {
             Document: document,
+            opacity: opacity,
             addDocument: this.props.addDocument,
             removeDocument: this.props.removeDocument,
             moveDocument: this.props.moveDocument,
@@ -277,25 +284,30 @@ export class CollectionFreeFormView extends CollectionSubView {
     @computed
     get views() {
         var curPage = this.props.Document.GetNumber(KeyStore.CurPage, -1);
-        return this.props.Document.GetList(this.props.fieldKey, [] as Document[]).filter(doc => doc).reduce((prev, doc) => {
+        let docviews = this.props.Document.GetList(this.props.fieldKey, [] as Document[]).filter(doc => doc).reduce((prev, doc) => {
             var page = doc.GetNumber(KeyStore.Page, -1);
-            if (page === curPage || page === -1) {
-                prev.push(<CollectionFreeFormDocumentView key={doc.Id} {...this.getDocumentViewProps(doc)} />);
+            var zoom = doc.GetNumber(KeyStore.Zoom, 1);
+            var dv = DocumentManager.Instance.getDocumentView(doc);
+            let opacity = this.isAnnotationOverlay && (!dv || !SelectionManager.IsSelected(dv)) ? 1 - Math.abs(zoom - this.scale) : 1;
+            if ((page === curPage || page === -1)) {
+                prev.push(<CollectionFreeFormDocumentView key={doc.Id} {...this.getDocumentViewProps(doc, opacity)} />);
             }
             return prev;
         }, [] as JSX.Element[]);
+        untracked(() => this._selectOnLoaded = "");
+        return docviews;
     }
 
     @computed
     get backgroundView() {
         return !this.backgroundLayout ? (null) :
-            (<DocumentContentsView {...this.getDocumentViewProps(this.props.Document)}
+            (<DocumentContentsView {...this.getDocumentViewProps(this.props.Document, 1)}
                 layoutKey={KeyStore.BackgroundLayout} isTopMost={this.props.isTopMost} isSelected={returnFalse} select={emptyFunction} />);
     }
     @computed
     get overlayView() {
         return !this.overlayLayout ? (null) :
-            (<DocumentContentsView {...this.getDocumentViewProps(this.props.Document)}
+            (<DocumentContentsView {...this.getDocumentViewProps(this.props.Document, 1)}
                 layoutKey={KeyStore.OverlayLayout} isTopMost={this.props.isTopMost} isSelected={returnFalse} select={emptyFunction} />);
     }
 
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 77f41105f..0aa152209 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -6,7 +6,6 @@ import { Transform } from "../../util/Transform";
 import { DocumentView, DocumentViewProps } from "./DocumentView";
 import "./DocumentView.scss";
 import React = require("react");
-import { thisExpression } from "babel-types";
 
 
 @observer
@@ -16,18 +15,13 @@ export class CollectionFreeFormDocumentView extends React.Component<DocumentView
     constructor(props: DocumentViewProps) {
         super(props);
     }
-    get screenRect(): ClientRect | DOMRect {
-        if (this._mainCont.current) {
-            return this._mainCont.current.getBoundingClientRect();
-        }
-        return new DOMRect();
-    }
 
     @computed
     get transform(): string {
-        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)`;
+        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) scale(${this.zoom}, ${this.zoom}) `;
     }
 
+    @computed get zoom(): number { return 1 / this.props.Document.GetNumber(KeyStore.Zoom, 1); }
     @computed get zIndex(): number { return this.props.Document.GetNumber(KeyStore.ZIndex, 0); }
     @computed get width(): number { return this.props.Document.Width(); }
     @computed get height(): number { return this.props.Document.Height(); }
@@ -57,7 +51,7 @@ export class CollectionFreeFormDocumentView extends React.Component<DocumentView
     getTransform = (): Transform =>
         this.props.ScreenToLocalTransform()
             .translate(-this.props.Document.GetNumber(KeyStore.X, 0), -this.props.Document.GetNumber(KeyStore.Y, 0))
-            .scale(1 / this.contentScaling())
+            .scale(1 / this.contentScaling()).scale(1 / this.zoom)
 
     @computed
     get docView() {
@@ -74,6 +68,7 @@ export class CollectionFreeFormDocumentView extends React.Component<DocumentView
     render() {
         return (
             <div className="collectionFreeFormDocumentView-container" ref={this._mainCont} style={{
+                opacity: this.props.opacity,
                 transformOrigin: "left top",
                 transform: this.transform,
                 pointerEvents: "all",
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 4d7a85316..f0f9af89f 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -26,6 +26,7 @@ import { undoBatch, UndoManager } from "../../util/UndoManager";
 export interface DocumentViewProps {
     ContainingCollectionView: Opt<CollectionView>;
     Document: Document;
+    opacity: number;
     addDocument?: (doc: Document, allowDuplicates?: boolean) => boolean;
     removeDocument?: (doc: Document) => boolean;
     moveDocument?: (doc: Document, targetCollection: Document, addDocument: (document: Document) => boolean) => boolean;
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 0037d7b28..e0c5e19fb 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -79,6 +79,7 @@ export class FieldView extends React.Component<FieldViewProps> {
                 <DocumentContentsView Document={field}
                     addDocument={undefined}
                     removeDocument={undefined}
+                    opacity={1}
                     ScreenToLocalTransform={Transform.Identity}
                     ContentScaling={() => 1}
                     PanelWidth={() => 100}
diff --git a/src/fields/KeyStore.ts b/src/fields/KeyStore.ts
index da2d7268f..19431bbe3 100644
--- a/src/fields/KeyStore.ts
+++ b/src/fields/KeyStore.ts
@@ -15,6 +15,7 @@ export namespace KeyStore {
     export const Width = new Key("Width");
     export const Height = new Key("Height");
     export const ZIndex = new Key("ZIndex");
+    export const Zoom = new Key("Zoom");
     export const Data = new Key("Data");
     export const Annotations = new Key("Annotations");
     export const ViewType = new Key("ViewType");
-- 
cgit v1.2.3-70-g09d2


From a12bc4e408119ca2c310c04598c3aa2b424751c5 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sun, 14 Apr 2019 15:10:12 -0400
Subject: restored ContainingCollectionView for use in drawings links (maybe
 brushing later)

---
 src/client/views/Main.tsx                          |  2 +-
 .../views/collections/CollectionSchemaView.tsx     |  4 +++-
 src/client/views/collections/CollectionSubView.tsx |  2 ++
 src/client/views/collections/CollectionView.tsx    |  8 +++----
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  2 +-
 .../collections/collectionFreeForm/MarqueeView.tsx |  5 ++--
 src/client/views/nodes/DocumentContentsView.tsx    | 28 ++++++++++++----------
 src/client/views/nodes/FieldView.tsx               |  7 ++++--
 src/client/views/nodes/KeyValuePair.tsx            |  2 ++
 9 files changed, 36 insertions(+), 24 deletions(-)

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

diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index babd3be2a..03cfbe9da 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -282,7 +282,7 @@ export class Main extends React.Component {
             return <div className="mainDiv-textInput" style={{ pointerEvents: "none", transform: `translate(${x}px, ${y}px) scale(${1 / s[0]},${1 / s[0]})`, width: "auto", height: "auto" }} >
                 <div className="mainDiv-textInput" onPointerDown={this.textBoxDown} ref={this._textProxyDiv} onScroll={this.textScroll} style={{ pointerEvents: "none", transform: `scale(${1}, ${1})`, width: `${w * s[0]}px`, height: `${h * s[0]}px` }}>
                     <FormattedTextBox fieldKey={this._textFieldKey!} isOverlay={true} Document={this._textDoc} isSelected={returnTrue} select={emptyFunction} isTopMost={true}
-                        selectOnLoad={true} onActiveChanged={emptyFunction} active={returnTrue} ScreenToLocalTransform={() => this._textXf} focus={emptyDocFunction} />
+                        selectOnLoad={true} ContainingCollectionView={undefined} CollectionView={undefined} onActiveChanged={emptyFunction} active={returnTrue} ScreenToLocalTransform={() => this._textXf} focus={emptyDocFunction} />
                 </div>
             </ div>;
         }
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 2a1d1dd94..63346a4c6 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -75,6 +75,8 @@ export class CollectionSchemaView extends CollectionSubView {
         let props: FieldViewProps = {
             Document: rowProps.value[0],
             fieldKey: rowProps.value[1],
+            CollectionView: this.props.CollectionView,
+            ContainingCollectionView: this.props.CollectionView,
             isSelected: returnFalse,
             select: emptyFunction,
             isTopMost: false,
@@ -313,7 +315,7 @@ export class CollectionSchemaView extends CollectionSubView {
                                 ContentScaling={this.getContentScaling}
                                 PanelWidth={this.getPanelWidth}
                                 PanelHeight={this.getPanelHeight}
-                                ContainingCollectionView={undefined}
+                                ContainingCollectionView={this.props.CollectionView}
                                 focus={emptyDocFunction}
                                 parentActive={this.props.active}
                                 onActiveChanged={this.props.onActiveChanged} /> : null}
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index d91db68bb..61b7787e7 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -16,6 +16,7 @@ import { Server } from "../../Server";
 import { FieldViewProps } from "../nodes/FieldView";
 import * as rp from 'request-promise';
 import { emptyFunction } from "../../../Utils";
+import { CollectionView } from "./CollectionView";
 
 export interface CollectionViewProps extends FieldViewProps {
     addDocument: (document: Document, allowDuplicates?: boolean) => boolean;
@@ -24,6 +25,7 @@ export interface CollectionViewProps extends FieldViewProps {
 }
 
 export interface SubCollectionViewProps extends CollectionViewProps {
+    CollectionView: Opt<CollectionView>;
 }
 
 export type CursorEntry = TupleField<[string, string], [number, number]>;
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 8abd0a02d..1f69a69e8 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -18,12 +18,12 @@ export class CollectionView extends React.Component<FieldViewProps> {
     private SubView = (type: CollectionViewType, renderProps: CollectionRenderProps) => {
         let props = { ...this.props, ...renderProps };
         switch (type) {
-            case CollectionViewType.Schema: return (<CollectionSchemaView {...props} />);
-            case CollectionViewType.Docking: return (<CollectionDockingView {...props} />);
-            case CollectionViewType.Tree: return (<CollectionTreeView {...props} />);
+            case CollectionViewType.Schema: return (<CollectionSchemaView {...props} CollectionView={this} />);
+            case CollectionViewType.Docking: return (<CollectionDockingView {...props} CollectionView={this} />);
+            case CollectionViewType.Tree: return (<CollectionTreeView {...props} CollectionView={this} />);
             case CollectionViewType.Freeform:
             default:
-                return (<CollectionFreeFormView {...props} />);
+                return (<CollectionFreeFormView {...props} CollectionView={this} />);
         }
         return (null);
     }
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 94945bde6..e9e942b78 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -274,7 +274,7 @@ export class CollectionFreeFormView extends CollectionSubView {
             PanelWidth: document.Width,
             PanelHeight: document.Height,
             ContentScaling: this.noScaling,
-            ContainingCollectionView: undefined,
+            ContainingCollectionView: this.props.CollectionView,
             focus: this.focusDocument,
             parentActive: this.props.active,
             onActiveChanged: this.props.active,
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index a4722a6f8..cf75aef40 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -209,10 +209,11 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
         let selRect = this.Bounds;
         let selection: Document[] = [];
         this.props.activeDocuments().map(doc => {
+            var z = doc.GetNumber(KeyStore.Zoom, 1);
             var x = doc.GetNumber(KeyStore.X, 0);
             var y = doc.GetNumber(KeyStore.Y, 0);
-            var w = doc.GetNumber(KeyStore.Width, 0);
-            var h = doc.GetNumber(KeyStore.Height, 0);
+            var w = doc.GetNumber(KeyStore.Width, 0) / z;
+            var h = doc.GetNumber(KeyStore.Height, 0) / z;
             if (this.intersectRect({ left: x, top: y, width: w, height: h }, selRect)) {
                 selection.push(doc);
             }
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 5836da396..a967db000 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -44,19 +44,19 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
 
 
     CreateBindings(): JsxBindings {
-        let
-            {
-                Document,
-                isSelected,
-                select,
-                isTopMost,
-                selectOnLoad,
-                ScreenToLocalTransform,
-                addDocument,
-                removeDocument,
-                onActiveChanged,
-                parentActive: active,
-            } = this.props;
+        let {
+            Document,
+            isSelected,
+            select,
+            isTopMost,
+            selectOnLoad,
+            ScreenToLocalTransform,
+            ContainingCollectionView,
+            addDocument,
+            removeDocument,
+            onActiveChanged,
+            parentActive: active,
+        } = this.props;
         let bindings: JsxBindings = {
             props: {
                 Document,
@@ -65,6 +65,8 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
                 isTopMost,
                 selectOnLoad,
                 ScreenToLocalTransform,
+                CollectionView: undefined,
+                ContainingCollectionView,
                 active,
                 onActiveChanged,
                 addDocument,
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index e0c5e19fb..755367d23 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -1,7 +1,7 @@
 import React = require("react");
 import { observer } from "mobx-react";
 import { computed } from "mobx";
-import { Field, FieldWaiting, FieldValue } from "../../../fields/Field";
+import { Field, FieldWaiting, FieldValue, Opt } from "../../../fields/Field";
 import { Document } from "../../../fields/Document";
 import { TextField } from "../../../fields/TextField";
 import { NumberField } from "../../../fields/NumberField";
@@ -20,6 +20,7 @@ import { DocumentContentsView } from "./DocumentContentsView";
 import { Transform } from "../../util/Transform";
 import { KeyStore } from "../../../fields/KeyStore";
 import { returnFalse, emptyDocFunction } from "../../../Utils";
+import { CollectionView } from "../collections/CollectionView";
 
 
 //
@@ -29,6 +30,8 @@ import { returnFalse, emptyDocFunction } from "../../../Utils";
 //
 export interface FieldViewProps {
     fieldKey: Key;
+    ContainingCollectionView: Opt<CollectionView>;
+    CollectionView: Opt<CollectionView>;
     Document: Document;
     isSelected: () => boolean;
     select: (isCtrlPressed: boolean) => void;
@@ -90,7 +93,7 @@ export class FieldView extends React.Component<FieldViewProps> {
                     isSelected={returnFalse}
                     select={returnFalse}
                     layoutKey={KeyStore.Layout}
-                    ContainingCollectionView={undefined}
+                    ContainingCollectionView={this.props.ContainingCollectionView}
                     parentActive={this.props.active}
                     onActiveChanged={this.props.onActiveChanged} />
             );
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index 3e0b61c3d..1b9dd26bd 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -47,6 +47,8 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
         }
         let props: FieldViewProps = {
             Document: this.props.doc,
+            CollectionView: undefined,
+            ContainingCollectionView: undefined,
             fieldKey: this.key,
             isSelected: returnFalse,
             select: emptyFunction,
-- 
cgit v1.2.3-70-g09d2


From 2cb379ebe0fd8f2dc9ffa64c2b303bef648cfa33 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sun, 14 Apr 2019 16:59:21 -0400
Subject: cleaned up ContainingCollectionView stuff a bit

---
 src/client/util/DocumentManager.ts                 | 22 ++++------
 src/client/views/Main.tsx                          |  2 +-
 src/client/views/collections/CollectionPDFView.tsx |  4 +-
 .../views/collections/CollectionSchemaView.tsx     |  1 -
 src/client/views/collections/CollectionSubView.tsx |  4 +-
 .../views/collections/CollectionVideoView.tsx      |  2 +-
 .../CollectionFreeFormLinksView.tsx                | 21 +++++-----
 src/client/views/nodes/DocumentContentsView.tsx    |  1 -
 src/client/views/nodes/DocumentView.tsx            | 12 +++---
 src/client/views/nodes/FieldView.tsx               |  5 ++-
 src/client/views/nodes/KeyValuePair.scss           | 40 +++++++++---------
 src/client/views/nodes/KeyValuePair.tsx            | 47 +++++++++-------------
 12 files changed, 71 insertions(+), 90 deletions(-)

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

diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 3e093c8dc..3b5a5b470 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -1,11 +1,9 @@
-import React = require('react');
-import { observer } from 'mobx-react';
-import { observable, action, computed } from 'mobx';
+import { computed, observable } from 'mobx';
 import { Document } from "../../fields/Document";
-import { DocumentView } from '../views/nodes/DocumentView';
-import { KeyStore } from '../../fields/KeyStore';
 import { FieldWaiting } from '../../fields/Field';
+import { KeyStore } from '../../fields/KeyStore';
 import { ListField } from '../../fields/ListField';
+import { DocumentView } from '../views/nodes/DocumentView';
 
 
 export class DocumentManager {
@@ -27,10 +25,6 @@ export class DocumentManager {
         // this.DocumentViews = new Array<DocumentView>();
     }
 
-    public getAllDocumentViews(collection: Document) {
-        return this.DocumentViews.filter(dv => dv.props.ContainingCollectionView && dv.props.ContainingCollectionView.props.Document === collection);
-    }
-
     public getDocumentView(toFind: Document): DocumentView | null {
 
         let toReturn: DocumentView | null;
@@ -39,7 +33,6 @@ export class DocumentManager {
         //gets document view that is in a freeform canvas collection
         DocumentManager.Instance.DocumentViews.map(view => {
             let doc = view.props.Document;
-            // if (view.props.ContainingCollectionView instanceof CollectionFreeFormView) {
 
             if (doc === toFind) {
                 toReturn = view;
@@ -51,7 +44,7 @@ export class DocumentManager {
             }
         });
 
-        return (toReturn);
+        return toReturn;
     }
     public getDocumentViews(toFind: Document): DocumentView[] {
 
@@ -72,7 +65,7 @@ export class DocumentManager {
             }
         });
 
-        return (toReturn);
+        return toReturn;
     }
 
     @computed
@@ -84,9 +77,8 @@ export class DocumentManager {
                     if (link instanceof Document) {
                         let linkToDoc = link.GetT(KeyStore.LinkedToDocs, Document);
                         if (linkToDoc && linkToDoc !== FieldWaiting) {
-                            DocumentManager.Instance.getDocumentViews(linkToDoc).map(docView1 => {
-                                pairs.push({ a: dv, b: docView1, l: link });
-                            });
+                            DocumentManager.Instance.getDocumentViews(linkToDoc).map(docView1 =>
+                                pairs.push({ a: dv, b: docView1, l: link }));
                         }
                     }
                     return pairs;
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 03cfbe9da..f8c6ec0e2 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -282,7 +282,7 @@ export class Main extends React.Component {
             return <div className="mainDiv-textInput" style={{ pointerEvents: "none", transform: `translate(${x}px, ${y}px) scale(${1 / s[0]},${1 / s[0]})`, width: "auto", height: "auto" }} >
                 <div className="mainDiv-textInput" onPointerDown={this.textBoxDown} ref={this._textProxyDiv} onScroll={this.textScroll} style={{ pointerEvents: "none", transform: `scale(${1}, ${1})`, width: `${w * s[0]}px`, height: `${h * s[0]}px` }}>
                     <FormattedTextBox fieldKey={this._textFieldKey!} isOverlay={true} Document={this._textDoc} isSelected={returnTrue} select={emptyFunction} isTopMost={true}
-                        selectOnLoad={true} ContainingCollectionView={undefined} CollectionView={undefined} onActiveChanged={emptyFunction} active={returnTrue} ScreenToLocalTransform={() => this._textXf} focus={emptyDocFunction} />
+                        selectOnLoad={true} ContainingCollectionView={undefined} onActiveChanged={emptyFunction} active={returnTrue} ScreenToLocalTransform={() => this._textXf} focus={emptyDocFunction} />
                 </div>
             </ div>;
         }
diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx
index 6cbe59012..229bc4059 100644
--- a/src/client/views/collections/CollectionPDFView.tsx
+++ b/src/client/views/collections/CollectionPDFView.tsx
@@ -1,4 +1,4 @@
-import { action, computed, observable } from "mobx";
+import { action } from "mobx";
 import { observer } from "mobx-react";
 import { KeyStore } from "../../../fields/KeyStore";
 import { ContextMenu } from "../ContextMenu";
@@ -42,7 +42,7 @@ export class CollectionPDFView extends React.Component<FieldViewProps> {
         let props = { ...this.props, ...renderProps };
         return (
             <>
-                <CollectionFreeFormView {...props} />
+                <CollectionFreeFormView {...props} CollectionView={this} />
                 {this.props.isSelected() ? this.uIButtons : (null)}
             </>
         );
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 63346a4c6..2c99c9c67 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -75,7 +75,6 @@ export class CollectionSchemaView extends CollectionSubView {
         let props: FieldViewProps = {
             Document: rowProps.value[0],
             fieldKey: rowProps.value[1],
-            CollectionView: this.props.CollectionView,
             ContainingCollectionView: this.props.CollectionView,
             isSelected: returnFalse,
             select: emptyFunction,
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 61b7787e7..1c927c78d 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -17,6 +17,8 @@ import { FieldViewProps } from "../nodes/FieldView";
 import * as rp from 'request-promise';
 import { emptyFunction } from "../../../Utils";
 import { CollectionView } from "./CollectionView";
+import { CollectionPDFView } from "./CollectionPDFView";
+import { CollectionVideoView } from "./CollectionVideoView";
 
 export interface CollectionViewProps extends FieldViewProps {
     addDocument: (document: Document, allowDuplicates?: boolean) => boolean;
@@ -25,7 +27,7 @@ export interface CollectionViewProps extends FieldViewProps {
 }
 
 export interface SubCollectionViewProps extends CollectionViewProps {
-    CollectionView: Opt<CollectionView>;
+    CollectionView: CollectionView | CollectionPDFView | CollectionVideoView;
 }
 
 export type CursorEntry = TupleField<[string, string], [number, number]>;
diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index 6c9780adb..29fb342c6 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -109,7 +109,7 @@ export class CollectionVideoView extends React.Component<FieldViewProps> {
         let props = { ...this.props, ...renderProps };
         return (
             <>
-                <CollectionFreeFormView {...props} />
+                <CollectionFreeFormView {...props} CollectionView={this} />
                 {this.props.isSelected() ? this.uIButtons : (null)}
             </>
         );
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
index 647c83d4d..2f684a54e 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
@@ -1,7 +1,6 @@
-import { computed, reaction, trace, IReactionDisposer } from "mobx";
+import { computed, IReactionDisposer, reaction } from "mobx";
 import { observer } from "mobx-react";
 import { Document } from "../../../../fields/Document";
-import { FieldWaiting } from "../../../../fields/Field";
 import { KeyStore } from "../../../../fields/KeyStore";
 import { ListField } from "../../../../fields/ListField";
 import { Utils } from "../../../../Utils";
@@ -85,19 +84,17 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
             let targetViews = this.documentAnchors(connection.b);
             let possiblePairs: { a: Document, b: Document, }[] = [];
             srcViews.map(sv => targetViews.map(tv => possiblePairs.push({ a: sv.props.Document, b: tv.props.Document })));
-            possiblePairs.map(possiblePair => {
-                if (!drawnPairs.reduce((found, drawnPair) => {
+            possiblePairs.map(possiblePair =>
+                drawnPairs.reduce((found, drawnPair) => {
                     let match = (possiblePair.a === drawnPair.a && possiblePair.b === drawnPair.b);
-                    if (match) {
-                        if (!drawnPair.l.reduce((found, link) => found || link.Id === connection.l.Id, false)) {
-                            drawnPair.l.push(connection.l);
-                        }
+                    if (match && !drawnPair.l.reduce((found, link) => found || link.Id === connection.l.Id, false)) {
+                        drawnPair.l.push(connection.l);
                     }
                     return match || found;
-                }, false)) {
-                    drawnPairs.push({ a: possiblePair.a, b: possiblePair.b, l: [connection.l] });
-                }
-            });
+                }, false)
+                ||
+                drawnPairs.push({ a: possiblePair.a, b: possiblePair.b, l: [connection.l] })
+            );
             return drawnPairs;
         }, [] as { a: Document, b: Document, l: Document[] }[]);
         return connections.map(c => <CollectionFreeFormLinkView key={Utils.GenerateGuid()} A={c.a} B={c.b} LinkDocs={c.l} />);
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index a967db000..88900c4b1 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -65,7 +65,6 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
                 isTopMost,
                 selectOnLoad,
                 ScreenToLocalTransform,
-                CollectionView: undefined,
                 ContainingCollectionView,
                 active,
                 onActiveChanged,
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index f0f9af89f..935540af1 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1,30 +1,32 @@
-import { action, computed, IReactionDisposer, reaction, runInAction, trace } from "mobx";
+import { action, computed, runInAction } from "mobx";
 import { observer } from "mobx-react";
+import { BooleanField } from "../../../fields/BooleanField";
 import { Document } from "../../../fields/Document";
 import { Field, FieldWaiting, Opt } from "../../../fields/Field";
 import { Key } from "../../../fields/Key";
 import { KeyStore } from "../../../fields/KeyStore";
 import { ListField } from "../../../fields/ListField";
-import { BooleanField } from "../../../fields/BooleanField";
 import { TextField } from "../../../fields/TextField";
 import { ServerUtils } from "../../../server/ServerUtil";
-import { Utils, emptyFunction } from "../../../Utils";
+import { emptyFunction, Utils } from "../../../Utils";
 import { Documents } from "../../documents/Documents";
 import { DocumentManager } from "../../util/DocumentManager";
 import { DragManager } from "../../util/DragManager";
 import { SelectionManager } from "../../util/SelectionManager";
 import { Transform } from "../../util/Transform";
+import { undoBatch, UndoManager } from "../../util/UndoManager";
 import { CollectionDockingView } from "../collections/CollectionDockingView";
+import { CollectionPDFView } from "../collections/CollectionPDFView";
+import { CollectionVideoView } from "../collections/CollectionVideoView";
 import { CollectionView } from "../collections/CollectionView";
 import { ContextMenu } from "../ContextMenu";
 import { DocumentContentsView } from "./DocumentContentsView";
 import "./DocumentView.scss";
 import React = require("react");
-import { undoBatch, UndoManager } from "../../util/UndoManager";
 
 
 export interface DocumentViewProps {
-    ContainingCollectionView: Opt<CollectionView>;
+    ContainingCollectionView: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
     Document: Document;
     opacity: number;
     addDocument?: (doc: Document, allowDuplicates?: boolean) => boolean;
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 755367d23..562de4827 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -21,6 +21,8 @@ import { Transform } from "../../util/Transform";
 import { KeyStore } from "../../../fields/KeyStore";
 import { returnFalse, emptyDocFunction } from "../../../Utils";
 import { CollectionView } from "../collections/CollectionView";
+import { CollectionPDFView } from "../collections/CollectionPDFView";
+import { CollectionVideoView } from "../collections/CollectionVideoView";
 
 
 //
@@ -30,8 +32,7 @@ import { CollectionView } from "../collections/CollectionView";
 //
 export interface FieldViewProps {
     fieldKey: Key;
-    ContainingCollectionView: Opt<CollectionView>;
-    CollectionView: Opt<CollectionView>;
+    ContainingCollectionView: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
     Document: Document;
     isSelected: () => boolean;
     select: (isCtrlPressed: boolean) => void;
diff --git a/src/client/views/nodes/KeyValuePair.scss b/src/client/views/nodes/KeyValuePair.scss
index 04d002c7b..01701e02c 100644
--- a/src/client/views/nodes/KeyValuePair.scss
+++ b/src/client/views/nodes/KeyValuePair.scss
@@ -1,30 +1,28 @@
 @import "../globalCssVariables";
 
-.container{
-    width:100%;
-    height:100%;
-    display: flex;                 
-    flex-direction: row;           
-    flex-wrap: nowrap;              
-    justify-content: space-between; 
-}
 
 .keyValuePair-td-key {
     display:inline-block;
-    width: 50%;
+    .keyValuePair-td-key-container{
+        width:100%;
+        height:100%;
+        display: flex;                 
+        flex-direction: row;           
+        flex-wrap: nowrap;              
+        justify-content: space-between; 
+        .keyValuePair-td-key-delete{
+            position: relative;
+            background-color: transparent;
+            color:red;
+        }
+        .keyValuePair-keyField {
+            width:100%;
+            text-align: center;
+            position: relative;
+            overflow: auto;
+        }
+    }
 }
 .keyValuePair-td-value {
     display:inline-block;
-    width: 50%;
-}
-.keyValuePair-keyField {
-    width:100%;
-    text-align: center;
-    position: relative;
-    overflow: auto;
-}
-.delete{
-    position: relative;
-    background-color: transparent;
-    color:red;
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index 1b9dd26bd..5d69f23b2 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -1,18 +1,18 @@
-import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app
-import "./KeyValueBox.scss";
-import "./KeyValuePair.scss";
-import React = require("react");
-import { FieldViewProps, FieldView } from './FieldView';
-import { Opt, Field } from '../../../fields/Field';
+import { action, observable } from 'mobx';
 import { observer } from "mobx-react";
-import { observable, action } from 'mobx';
+import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app
 import { Document } from '../../../fields/Document';
+import { Field, Opt } from '../../../fields/Field';
 import { Key } from '../../../fields/Key';
+import { emptyDocFunction, emptyFunction, returnFalse } from '../../../Utils';
 import { Server } from "../../Server";
-import { EditableView } from "../EditableView";
 import { CompileScript, ToField } from "../../util/Scripting";
 import { Transform } from '../../util/Transform';
-import { returnFalse, emptyFunction, emptyDocFunction } from '../../../Utils';
+import { EditableView } from "../EditableView";
+import { FieldView, FieldViewProps } from './FieldView';
+import "./KeyValueBox.scss";
+import "./KeyValuePair.scss";
+import React = require("react");
 
 // Represents one row in a key value plane
 
@@ -25,29 +25,22 @@ export interface KeyValuePairProps {
 @observer
 export class KeyValuePair extends React.Component<KeyValuePairProps> {
 
-    @observable
-    private key: Opt<Key>;
+    @observable private key: Opt<Key>;
 
     constructor(props: KeyValuePairProps) {
         super(props);
         Server.GetField(this.props.fieldId,
-            action((field: Opt<Field>) => {
-                if (field) {
-                    this.key = field as Key;
-                }
-            }));
+            action((field: Opt<Field>) => field instanceof Key && (this.key = field)));
 
     }
 
 
     render() {
         if (!this.key) {
-            return <tr><td>error</td><td></td></tr>;
-
+            return <tr><td>error</td><td /></tr>;
         }
         let props: FieldViewProps = {
             Document: this.props.doc,
-            CollectionView: undefined,
             ContainingCollectionView: undefined,
             fieldKey: this.key,
             isSelected: returnFalse,
@@ -59,19 +52,17 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
             ScreenToLocalTransform: Transform.Identity,
             focus: emptyDocFunction,
         };
-        let contents = (
-            <FieldView {...props} />
-        );
+        let contents = <FieldView {...props} />;
         return (
             <tr className={this.props.rowStyle}>
                 <td className="keyValuePair-td-key" style={{ width: `${this.props.keyWidth}%` }}>
-                    <div className="container">
-                        <button className="delete" onClick={() => {
+                    <div className="keyValuePair-td-key-container">
+                        <button className="keyValuePair-td-key-delete" onClick={() => {
                             let field = props.Document.Get(props.fieldKey);
-                            if (field && field instanceof Field) {
-                                props.Document.Set(props.fieldKey, undefined);
-                            }
-                        }}>X</button>
+                            field && field instanceof Field && props.Document.Set(props.fieldKey, undefined);
+                        }}>
+                            X
+                        </button>
                         <div className="keyValuePair-keyField">{this.key.Name}</div>
                     </div>
                 </td>
-- 
cgit v1.2.3-70-g09d2


From 6c0b421db6aa3204bbc6e42139d240f503000b5d Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Mon, 15 Apr 2019 11:59:50 -0400
Subject: fixed zoom fading somewhat.

---
 src/Utils.ts                                       | 15 ++++++++++
 src/client/northstar/dash-fields/HistogramField.ts | 12 ++------
 src/client/views/Main.tsx                          |  3 +-
 src/client/views/MainOverlayTextBox.tsx            |  3 +-
 .../views/collections/CollectionDockingView.tsx    |  3 +-
 .../views/collections/CollectionSchemaView.tsx     |  3 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 19 ++++++-------
 .../views/nodes/CollectionFreeFormDocumentView.tsx | 18 ++++++++----
 src/client/views/nodes/DocumentContentsView.tsx    | 33 ++--------------------
 src/client/views/nodes/DocumentView.tsx            |  1 -
 src/client/views/nodes/FieldView.tsx               |  3 +-
 src/client/views/nodes/FormattedTextBox.tsx        |  4 ++-
 12 files changed, 51 insertions(+), 66 deletions(-)

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

diff --git a/src/Utils.ts b/src/Utils.ts
index e07d4e82d..dec6245ef 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -87,10 +87,25 @@ export class Utils {
     }
 }
 
+export function OmitKeys(obj: any, keys: any, addKeyFunc?: (dup: any) => void) {
+    var dup: any = {};
+    for (var key in obj) {
+        if (keys.indexOf(key) === -1) {
+            dup[key] = obj[key];
+        }
+    }
+    addKeyFunc && addKeyFunc(dup);
+    return dup;
+}
+
 export function returnTrue() { return true; }
 
 export function returnFalse() { return false; }
 
+export function returnOne() { return 1; }
+
+export function returnZero() { return 0; }
+
 export function emptyFunction() { }
 
 export function emptyDocFunction(doc: Document) { }
diff --git a/src/client/northstar/dash-fields/HistogramField.ts b/src/client/northstar/dash-fields/HistogramField.ts
index 82de51d56..c699691a4 100644
--- a/src/client/northstar/dash-fields/HistogramField.ts
+++ b/src/client/northstar/dash-fields/HistogramField.ts
@@ -6,6 +6,7 @@ import { BasicField } from "../../../fields/BasicField";
 import { Field, FieldId } from "../../../fields/Field";
 import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils";
 import { Types } from "../../../server/Message";
+import { OmitKeys } from "../../../Utils";
 
 
 export class HistogramField extends BasicField<HistogramOperation> {
@@ -13,17 +14,8 @@ export class HistogramField extends BasicField<HistogramOperation> {
         super(data ? data : HistogramOperation.Empty, save, id);
     }
 
-    omitKeys(obj: any, keys: any) {
-        var dup: any = {};
-        for (var key in obj) {
-            if (keys.indexOf(key) === -1) {
-                dup[key] = obj[key];
-            }
-        }
-        return dup;
-    }
     toString(): string {
-        return JSON.stringify(this.omitKeys(this.Data, ['Links', 'BrushLinks', 'Result', 'BrushColors', 'FilterModels', 'FilterOperand']));
+        return JSON.stringify(OmitKeys(this.Data, ['Links', 'BrushLinks', 'Result', 'BrushColors', 'FilterModels', 'FilterOperand']));
     }
 
     Copy(): Field {
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index d26586216..98ef329c7 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -17,7 +17,7 @@ import { CurrentUserUtils } from '../../server/authentication/models/current_use
 import { MessageStore } from '../../server/Message';
 import { RouteStore } from '../../server/RouteStore';
 import { ServerUtils } from '../../server/ServerUtil';
-import { emptyDocFunction, emptyFunction, returnTrue, Utils } from '../../Utils';
+import { emptyDocFunction, emptyFunction, returnTrue, Utils, returnOne } from '../../Utils';
 import { Documents } from '../documents/Documents';
 import { ColumnAttributeModel } from '../northstar/core/attribute/AttributeModel';
 import { AttributeTransformationModel } from '../northstar/core/attribute/AttributeTransformationModel';
@@ -178,7 +178,6 @@ export class Main extends React.Component {
                         <DocumentView Document={mainCont}
                             addDocument={undefined}
                             removeDocument={undefined}
-                            opacity={1}
                             ScreenToLocalTransform={Transform.Identity}
                             ContentScaling={noScaling}
                             PanelWidth={pwidthFunc}
diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx
index df1addbc7..6d43d88f0 100644
--- a/src/client/views/MainOverlayTextBox.tsx
+++ b/src/client/views/MainOverlayTextBox.tsx
@@ -56,7 +56,8 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
     @action
     textScroll = (e: React.UIEvent) => {
         if (this._textProxyDiv.current && this._textTargetDiv) {
-            this._textTargetDiv.scrollTop = this.TextScroll = this._textProxyDiv.current.children[0].scrollTop;
+            this.TextScroll = (e as any)._targetInst.stateNode.scrollTop;//  this._textProxyDiv.current.children[0].scrollTop;
+            this._textTargetDiv.scrollTop = this.TextScroll;
         }
     }
 
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 4f7d4fc0d..2b96e7678 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -8,7 +8,7 @@ import { Document } from "../../../fields/Document";
 import { KeyStore } from "../../../fields/KeyStore";
 import Measure from "react-measure";
 import { FieldId, Opt, Field, FieldWaiting } from "../../../fields/Field";
-import { Utils, returnTrue, emptyFunction, emptyDocFunction } from "../../../Utils";
+import { Utils, returnTrue, emptyFunction, emptyDocFunction, returnOne } from "../../../Utils";
 import { Server } from "../../Server";
 import { undoBatch } from "../../util/UndoManager";
 import { DocumentView } from "../nodes/DocumentView";
@@ -343,7 +343,6 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
                 <DocumentView key={this._document.Id} Document={this._document}
                     addDocument={undefined}
                     removeDocument={undefined}
-                    opacity={1}
                     ContentScaling={this._contentScaling}
                     PanelWidth={this._nativeWidth}
                     PanelHeight={this._nativeHeight}
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 2c99c9c67..4f4068e7a 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -12,7 +12,7 @@ import { Field, Opt } from "../../../fields/Field";
 import { Key } from "../../../fields/Key";
 import { KeyStore } from "../../../fields/KeyStore";
 import { ListField } from "../../../fields/ListField";
-import { emptyDocFunction, emptyFunction, returnFalse } from "../../../Utils";
+import { emptyDocFunction, emptyFunction, returnFalse, returnOne } from "../../../Utils";
 import { Server } from "../../Server";
 import { SetupDrag } from "../../util/DragManager";
 import { CompileScript, ToField } from "../../util/Scripting";
@@ -308,7 +308,6 @@ export class CollectionSchemaView extends CollectionSubView {
                             <DocumentView Document={doc}
                                 addDocument={this.props.addDocument} removeDocument={this.props.removeDocument}
                                 isTopMost={false}
-                                opacity={1}
                                 selectOnLoad={false}
                                 ScreenToLocalTransform={this.getPreviewTransform}
                                 ContentScaling={this.getContentScaling}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index cb4e8fb2e..4db3bf81b 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -5,7 +5,7 @@ import { Document } from "../../../../fields/Document";
 import { FieldWaiting } from "../../../../fields/Field";
 import { KeyStore } from "../../../../fields/KeyStore";
 import { TextField } from "../../../../fields/TextField";
-import { emptyFunction, returnFalse } from "../../../../Utils";
+import { emptyFunction, returnFalse, returnOne } from "../../../../Utils";
 import { DocumentManager } from "../../../util/DocumentManager";
 import { DragManager } from "../../../util/DragManager";
 import { SelectionManager } from "../../../util/SelectionManager";
@@ -14,7 +14,7 @@ import { undoBatch } from "../../../util/UndoManager";
 import { COLLECTION_BORDER_WIDTH } from "../../../views/globalCssVariables.scss";
 import { InkingCanvas } from "../../InkingCanvas";
 import { Main } from "../../Main";
-import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDocumentView";
+import { CollectionFreeFormDocumentView, CollectionFreeFormDocumentViewProps } from "../../nodes/CollectionFreeFormDocumentView";
 import { DocumentContentsView } from "../../nodes/DocumentContentsView";
 import { DocumentViewProps } from "../../nodes/DocumentView";
 import { CollectionSubView, SubCollectionViewProps } from "../CollectionSubView";
@@ -200,7 +200,6 @@ export class CollectionFreeFormView extends CollectionSubView {
             this.props.Document.SetNumber(KeyStore.Scale, localTransform.Scale);
             this.SetPan(-localTransform.TranslateX / localTransform.Scale, -localTransform.TranslateY / localTransform.Scale);
             e.stopPropagation();
-            e.preventDefault();
         }
     }
 
@@ -261,10 +260,9 @@ export class CollectionFreeFormView extends CollectionSubView {
         this.props.focus(this.props.Document);
     }
 
-    getDocumentViewProps(document: Document, opacity: number): DocumentViewProps {
+    getDocumentViewProps(document: Document): DocumentViewProps {
         return {
             Document: document,
-            opacity: opacity,
             addDocument: this.props.addDocument,
             removeDocument: this.props.removeDocument,
             moveDocument: this.props.moveDocument,
@@ -288,9 +286,10 @@ export class CollectionFreeFormView extends CollectionSubView {
             var page = doc.GetNumber(KeyStore.Page, -1);
             var zoom = doc.GetNumber(KeyStore.Zoom, 1);
             var dv = DocumentManager.Instance.getDocumentView(doc);
-            let opacity = this.isAnnotationOverlay && (!dv || !SelectionManager.IsSelected(dv)) ? 1 - Math.abs(zoom - this.scale) : 1;
-            if ((page === curPage || page === -1)) {
-                prev.push(<CollectionFreeFormDocumentView key={doc.Id} {...this.getDocumentViewProps(doc, opacity)} />);
+            let zoomFade = !this.isAnnotationOverlay || (dv && SelectionManager.IsSelected(dv)) ? 1 :
+                Math.max(0, 2 - (zoom < this.scale ? this.scale / zoom : zoom / this.scale));
+            if (page === curPage || page === -1) {
+                prev.push(<CollectionFreeFormDocumentView key={doc.Id} {...this.getDocumentViewProps(doc)} zoomFade={zoomFade} />);
             }
             return prev;
         }, [] as JSX.Element[]);
@@ -305,13 +304,13 @@ export class CollectionFreeFormView extends CollectionSubView {
     @computed
     get backgroundView() {
         return !this.backgroundLayout ? (null) :
-            (<DocumentContentsView {...this.getDocumentViewProps(this.props.Document, 1)}
+            (<DocumentContentsView {...this.getDocumentViewProps(this.props.Document)}
                 layoutKey={KeyStore.BackgroundLayout} isTopMost={this.props.isTopMost} isSelected={returnFalse} select={emptyFunction} />);
     }
     @computed
     get overlayView() {
         return !this.overlayLayout ? (null) :
-            (<DocumentContentsView {...this.getDocumentViewProps(this.props.Document, 1)}
+            (<DocumentContentsView {...this.getDocumentViewProps(this.props.Document)}
                 layoutKey={KeyStore.OverlayLayout} isTopMost={this.props.isTopMost} isSelected={returnFalse} select={emptyFunction} />);
     }
 
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 0aa152209..b00cefbf6 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";
@@ -6,13 +6,17 @@ import { Transform } from "../../util/Transform";
 import { DocumentView, DocumentViewProps } from "./DocumentView";
 import "./DocumentView.scss";
 import React = require("react");
+import { OmitKeys } from "../../../Utils";
 
+export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
+    zoomFade: number;
+}
 
 @observer
-export class CollectionFreeFormDocumentView extends React.Component<DocumentViewProps> {
+export class CollectionFreeFormDocumentView extends React.Component<CollectionFreeFormDocumentViewProps> {
     private _mainCont = React.createRef<HTMLDivElement>();
 
-    constructor(props: DocumentViewProps) {
+    constructor(props: CollectionFreeFormDocumentViewProps) {
         super(props);
     }
 
@@ -55,20 +59,24 @@ export class CollectionFreeFormDocumentView extends React.Component<DocumentView
 
     @computed
     get docView() {
-        return <DocumentView {...this.props}
+        return <DocumentView {...this.docViewProps}
             ContentScaling={this.contentScaling}
             ScreenToLocalTransform={this.getTransform}
             PanelWidth={this.panelWidth}
             PanelHeight={this.panelHeight}
         />;
     }
+    @computed
+    get docViewProps(): DocumentViewProps {
+        return (OmitKeys(this.props, ['zoomFade']));
+    }
     panelWidth = () => this.props.Document.GetBoolean(KeyStore.Minimized, false) ? 10 : this.props.PanelWidth();
     panelHeight = () => this.props.Document.GetBoolean(KeyStore.Minimized, false) ? 10 : this.props.PanelHeight();
 
     render() {
         return (
             <div className="collectionFreeFormDocumentView-container" ref={this._mainCont} style={{
-                opacity: this.props.opacity,
+                opacity: this.props.zoomFade,
                 transformOrigin: "left top",
                 transform: this.transform,
                 pointerEvents: "all",
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 88900c4b1..76f852601 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -23,7 +23,7 @@ import { HistogramBox } from "../../northstar/dash-nodes/HistogramBox";
 import React = require("react");
 import { Document } from "../../../fields/Document";
 import { FieldViewProps } from "./FieldView";
-import { Without } from "../../../Utils";
+import { Without, OmitKeys } from "../../../Utils";
 const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this?
 
 type BindingProps = Without<FieldViewProps, 'fieldKey'>;
@@ -44,35 +44,8 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
 
 
     CreateBindings(): JsxBindings {
-        let {
-            Document,
-            isSelected,
-            select,
-            isTopMost,
-            selectOnLoad,
-            ScreenToLocalTransform,
-            ContainingCollectionView,
-            addDocument,
-            removeDocument,
-            onActiveChanged,
-            parentActive: active,
-        } = this.props;
-        let bindings: JsxBindings = {
-            props: {
-                Document,
-                isSelected,
-                select,
-                isTopMost,
-                selectOnLoad,
-                ScreenToLocalTransform,
-                ContainingCollectionView,
-                active,
-                onActiveChanged,
-                addDocument,
-                removeDocument,
-                focus,
-            }
-        };
+        let bindings: JsxBindings = { props: OmitKeys(this.props, ['parentActive'], (obj: any) => obj.active = this.props.parentActive) };
+
         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
         }
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 935540af1..bcd746024 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -28,7 +28,6 @@ import React = require("react");
 export interface DocumentViewProps {
     ContainingCollectionView: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
     Document: Document;
-    opacity: number;
     addDocument?: (doc: Document, allowDuplicates?: boolean) => boolean;
     removeDocument?: (doc: Document) => boolean;
     moveDocument?: (doc: Document, targetCollection: Document, addDocument: (document: Document) => boolean) => boolean;
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 562de4827..ebd25f937 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -19,7 +19,7 @@ import { ListField } from "../../../fields/ListField";
 import { DocumentContentsView } from "./DocumentContentsView";
 import { Transform } from "../../util/Transform";
 import { KeyStore } from "../../../fields/KeyStore";
-import { returnFalse, emptyDocFunction } from "../../../Utils";
+import { returnFalse, emptyDocFunction, emptyFunction, returnOne } from "../../../Utils";
 import { CollectionView } from "../collections/CollectionView";
 import { CollectionPDFView } from "../collections/CollectionPDFView";
 import { CollectionVideoView } from "../collections/CollectionVideoView";
@@ -83,7 +83,6 @@ export class FieldView extends React.Component<FieldViewProps> {
                 <DocumentContentsView Document={field}
                     addDocument={undefined}
                     removeDocument={undefined}
-                    opacity={1}
                     ScreenToLocalTransform={Transform.Identity}
                     ContentScaling={() => 1}
                     PanelWidth={() => 100}
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 87c1bcb1e..ad1ed5df0 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -1,4 +1,4 @@
-import { action, IReactionDisposer, reaction } from "mobx";
+import { action, IReactionDisposer, reaction, trace, computed } from "mobx";
 import { baseKeymap } from "prosemirror-commands";
 import { history, redo, undo } from "prosemirror-history";
 import { keymap } from "prosemirror-keymap";
@@ -17,6 +17,7 @@ import React = require("react");
 import { TextField } from "../../../fields/TextField";
 import { KeyStore } from "../../../fields/KeyStore";
 import { MainOverlayTextBox } from "../MainOverlayTextBox";
+import { observer } from "mobx-react";
 const { buildMenuItems } = require("prosemirror-example-setup");
 const { menuBar } = require("prosemirror-menu");
 
@@ -41,6 +42,7 @@ export interface FormattedTextBoxOverlay {
     isOverlay?: boolean;
 }
 
+@observer
 export class FormattedTextBox extends React.Component<(FieldViewProps & FormattedTextBoxOverlay)> {
     public static LayoutString(fieldStr: string = "DataKey") {
         return FieldView.LayoutString(FormattedTextBox, fieldStr);
-- 
cgit v1.2.3-70-g09d2


From 21b1e20106ff49c02657c88f503ef46bc7e4fb07 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 16 Apr 2019 23:09:03 -0400
Subject: various bug fixes

---
 src/client/northstar/dash-nodes/HistogramBox.tsx   |  2 +-
 .../views/collections/CollectionBaseView.tsx       |  9 ++++--
 .../views/collections/CollectionDockingView.scss   |  5 ++++
 .../views/collections/CollectionDockingView.tsx    |  7 ++++-
 .../views/collections/CollectionSchemaView.tsx     | 14 ++++++----
 src/client/views/collections/CollectionView.tsx    |  4 ++-
 .../CollectionFreeFormLinksView.tsx                |  4 +--
 .../CollectionFreeFormRemoteCursors.tsx            |  2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  2 +-
 .../collections/collectionFreeForm/MarqueeView.tsx |  1 -
 src/client/views/nodes/DocumentView.scss           |  4 +--
 src/client/views/nodes/ImageBox.tsx                | 32 ++++++----------------
 12 files changed, 44 insertions(+), 42 deletions(-)

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

diff --git a/src/client/northstar/dash-nodes/HistogramBox.tsx b/src/client/northstar/dash-nodes/HistogramBox.tsx
index 3e94fed81..0e84ace50 100644
--- a/src/client/northstar/dash-nodes/HistogramBox.tsx
+++ b/src/client/northstar/dash-nodes/HistogramBox.tsx
@@ -118,7 +118,7 @@ export class HistogramBox extends React.Component<FieldViewProps> {
             this.props.Document.GetTAsync(this.props.fieldKey, HistogramField).then((histoOp: Opt<HistogramField>) => runInAction(() => {
                 this.HistoOp = histoOp ? histoOp.Data : HistogramOperation.Empty;
                 if (this.HistoOp !== HistogramOperation.Empty) {
-                    reaction(() => this.props.Document.GetList(KeyStore.LinkedFromDocs, []), (docs: Document[]) => this.HistoOp.Links.splice(0, this.HistoOp.Links.length, ...docs), { fireImmediately: true });
+                    reaction(() => this.props.Document.GetList(KeyStore.LinkedFromDocs, [] as Document[]), (docs) => this.HistoOp.Links.splice(0, this.HistoOp.Links.length, ...docs), { fireImmediately: true });
                     reaction(() => this.props.Document.GetList(KeyStore.BrushingDocs, []).length,
                         () => {
                             let brushingDocs = this.props.Document.GetList(KeyStore.BrushingDocs, [] as Document[]);
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 444f6fc26..4fda38a26 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -61,13 +61,16 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
     }
 
     createsCycle(documentToAdd: Document, containerDocument: Document): boolean {
-        let data = documentToAdd.GetList<Document>(KeyStore.Data, []);
-        for (const doc of data) {
+        if (!(documentToAdd instanceof Document)) {
+            return false;
+        }
+        let data = documentToAdd.GetList(KeyStore.Data, [] as Document[]);
+        for (const doc of data.filter(d => d instanceof Document)) {
             if (this.createsCycle(doc, containerDocument)) {
                 return true;
             }
         }
-        let annots = documentToAdd.GetList<Document>(KeyStore.Annotations, []);
+        let annots = documentToAdd.GetList(KeyStore.Annotations, [] as Document[]);
         for (const annot of annots) {
             if (this.createsCycle(annot, containerDocument)) {
                 return true;
diff --git a/src/client/views/collections/CollectionDockingView.scss b/src/client/views/collections/CollectionDockingView.scss
index 0e7e0afa7..5ed4567cf 100644
--- a/src/client/views/collections/CollectionDockingView.scss
+++ b/src/client/views/collections/CollectionDockingView.scss
@@ -2,6 +2,11 @@
 
 .collectiondockingview-content {
     height: 100%;
+    text-align:center;
+    .documentView-node-topmost {
+        transform-origin: center top;
+        display: inline-block;
+    }
 }
 .lm_active .messageCounter{
     color:white;
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 4ea21b2f5..b998362f4 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -327,7 +327,12 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
 
     private _nativeWidth = () => this._document!.GetNumber(KeyStore.NativeWidth, this._panelWidth);
     private _nativeHeight = () => this._document!.GetNumber(KeyStore.NativeHeight, this._panelHeight);
-    private _contentScaling = () => this._panelWidth / (this._nativeWidth() ? this._nativeWidth() : this._panelWidth);
+    private _contentScaling = () => {
+        let wscale = this._panelWidth / (this._nativeWidth() ? this._nativeWidth() : this._panelWidth);
+        if (wscale * this._nativeHeight() > this._panelHeight)
+            return this._panelHeight / (this._nativeHeight() ? this._nativeHeight() : this._panelHeight);
+        return wscale;
+    }
 
     ScreenToLocalTransform = () => {
         let { scale, translateX, translateY } = Utils.GetScreenTransform(this._mainCont.current!);
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 4f4068e7a..1defdba7e 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -167,7 +167,7 @@ export class CollectionSchemaView extends CollectionSubView {
 
     @computed
     get columns() {
-        return this.props.Document.GetList<Key>(KeyStore.ColumnsKey, []);
+        return this.props.Document.GetList(KeyStore.ColumnsKey, [] as Key[]);
     }
 
     @action
@@ -195,7 +195,7 @@ export class CollectionSchemaView extends CollectionSubView {
 
     @computed
     get findAllDocumentKeys(): { [id: string]: boolean } {
-        const docs = this.props.Document.GetList<Document>(this.props.fieldKey, []);
+        const docs = this.props.Document.GetList(this.props.fieldKey, [] as Document[]);
         let keys: { [id: string]: boolean } = {};
         if (this._optionsActivated > -1) {
             // bcz: ugh.  this is untracked since otherwise a large collection of documents will blast the server for all their fields.
@@ -237,7 +237,7 @@ export class CollectionSchemaView extends CollectionSubView {
     }
     @action
     setScaling = (r: any) => {
-        const children = this.props.Document.GetList<Document>(this.props.fieldKey, []);
+        const children = this.props.Document.GetList(this.props.fieldKey, [] as Document[]);
         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;
@@ -253,8 +253,10 @@ export class CollectionSchemaView extends CollectionSubView {
     getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH - this._dividerX - this._tableWidth, - this.borderWidth).scale(1 / this._contentScaling);
 
     onPointerDown = (e: React.PointerEvent): void => {
-        if (e.button === 1 && this.props.isSelected() && !e.altKey && !e.ctrlKey && !e.metaKey) {
-            e.stopPropagation();
+        if (e.button === 0 && !e.altKey && !e.ctrlKey && !e.metaKey) {
+            if (this.props.isSelected())
+                e.stopPropagation();
+            else e.preventDefault();
         }
     }
 
@@ -293,7 +295,7 @@ export class CollectionSchemaView extends CollectionSubView {
         library.add(faCog);
         library.add(faPlus);
         const columns = this.columns;
-        const children = this.props.Document.GetList<Document>(this.props.fieldKey, []);
+        const children = this.props.Document.GetList(this.props.fieldKey, [] as Document[]);
         const selected = children.length > this._selectedIndex ? children[this._selectedIndex] : undefined;
         //all the keys/columns that will be displayed in the schema
         const allKeys = this.findAllDocumentKeys;
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index bd7a5635f..675e720e2 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -29,8 +29,10 @@ export class CollectionView extends React.Component<FieldViewProps> {
         return (null);
     }
 
+    get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldKey.Id === KeyStore.Annotations.Id; } // bcz: ? Why do we need to compare Id's?
+
     onContextMenu = (e: React.MouseEvent): void => {
-        if (!e.isPropagationStopped() && this.props.Document.Id !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
+        if (!this.isAnnotationOverlay && !e.isPropagationStopped() && this.props.Document.Id !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
             ContextMenu.Instance.addItem({ description: "Freeform", event: undoBatch(() => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform)) });
             ContextMenu.Instance.addItem({ description: "Schema", event: undoBatch(() => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Schema)) });
             ContextMenu.Instance.addItem({ description: "Treeview", event: undoBatch(() => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Tree)) });
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
index 2f684a54e..cd74d3a84 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
@@ -16,9 +16,9 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
 
     _brushReactionDisposer?: IReactionDisposer;
     componentDidMount() {
-        this._brushReactionDisposer = reaction(() => this.props.Document.GetList<Document>(this.props.fieldKey, []).map(doc => doc.GetNumber(KeyStore.X, 0)),
+        this._brushReactionDisposer = reaction(() => this.props.Document.GetList(this.props.fieldKey, [] as Document[]).map(doc => doc.GetNumber(KeyStore.X, 0)),
             () => {
-                let views = this.props.Document.GetList<Document>(this.props.fieldKey, []);
+                let views = this.props.Document.GetList(this.props.fieldKey, [] as Document[]);
                 for (let i = 0; i < views.length; i++) {
                     for (let j = 0; j < views.length; j++) {
                         let srcDoc = views[j];
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx
index 751ea8190..cf0a6de00 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx
@@ -12,7 +12,7 @@ export class CollectionFreeFormRemoteCursors extends React.Component<CollectionV
     protected getCursors(): CursorEntry[] {
         let doc = this.props.Document;
         let id = CurrentUserUtils.id;
-        let cursors = doc.GetList<CursorEntry>(KeyStore.Cursors, []);
+        let cursors = doc.GetList(KeyStore.Cursors, [] as CursorEntry[]);
         let notMe = cursors.filter(entry => entry.Data[0][0] !== id);
         return id ? notMe : [];
     }
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 3ae64d2c6..97708ce19 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -218,7 +218,7 @@ export class CollectionFreeFormView extends CollectionSubView {
 
     @action
     bringToFront(doc: Document) {
-        this.props.Document.GetList<Document>(this.props.fieldKey, []).slice().sort((doc1, doc2) => {
+        this.props.Document.GetList(this.props.fieldKey, [] as Document[]).slice().sort((doc1, doc2) => {
             if (doc1 === doc) return 1;
             if (doc2 === doc) return -1;
             return doc1.GetNumber(KeyStore.ZIndex, 0) - doc2.GetNumber(KeyStore.ZIndex, 0);
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 96d59c831..65f461b27 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -147,7 +147,6 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                 d.SetNumber(KeyStore.X, d.GetNumber(KeyStore.X, 0) - bounds.left - bounds.width / 2);
                 d.SetNumber(KeyStore.Y, d.GetNumber(KeyStore.Y, 0) - bounds.top - bounds.height / 2);
                 d.SetNumber(KeyStore.Page, -1);
-                d.SetText(KeyStore.Title, "" + d.Width() + " " + d.Height());
                 return d;
             });
             let ink = this.props.container.props.Document.GetT(KeyStore.Ink, InkField);
diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss
index 6383ac3f6..690ee50e8 100644
--- a/src/client/views/nodes/DocumentView.scss
+++ b/src/client/views/nodes/DocumentView.scss
@@ -1,6 +1,6 @@
 @import "../globalCssVariables";
 
-.documentView-node, .documentView-node-topMost {
+.documentView-node, .documentView-node-topmost {
   position: inherit;
   top: 0;
   left:0;
@@ -29,7 +29,7 @@
     height: calc(100% - 20px);
   }
 }
-.documentView-node-topMost {
+.documentView-node-topmost {
     background: white;
 }
 
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index ac54321d5..fe0b07bc0 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -1,24 +1,20 @@
 
-import { action, observable, trace } from 'mobx';
+import { action, observable } from 'mobx';
 import { observer } from "mobx-react";
 import Lightbox from 'react-image-lightbox';
 import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app
+import { Document } from '../../../fields/Document';
 import { FieldWaiting } from '../../../fields/Field';
 import { ImageField } from '../../../fields/ImageField';
 import { KeyStore } from '../../../fields/KeyStore';
+import { ListField } from '../../../fields/ListField';
+import { Utils } from '../../../Utils';
+import { DragManager } from '../../util/DragManager';
+import { undoBatch } from '../../util/UndoManager';
 import { ContextMenu } from "../../views/ContextMenu";
 import { FieldView, FieldViewProps } from './FieldView';
 import "./ImageBox.scss";
 import React = require("react");
-import { Utils } from '../../../Utils';
-import { ListField } from '../../../fields/ListField';
-import { DragManager } from '../../util/DragManager';
-import { undoBatch, UndoManager } from '../../util/UndoManager';
-import { TextField } from '../../../fields/TextField';
-import { Document } from '../../../fields/Document';
-import { RouteStore } from '../../../server/RouteStore';
-import { ServerUtils } from '../../../server/ServerUtil';
-import { CollectionSubView } from '../collections/CollectionSubView';
 
 @observer
 export class ImageBox extends React.Component<FieldViewProps> {
@@ -36,10 +32,6 @@ export class ImageBox extends React.Component<FieldViewProps> {
         super(props);
 
         this._imgRef = React.createRef();
-        this.state = {
-            photoIndex: 0,
-            isOpen: false,
-        };
     }
 
     @action
@@ -49,8 +41,6 @@ export class ImageBox extends React.Component<FieldViewProps> {
         if (this._photoIndex == 0) this.props.Document.SetNumber(KeyStore.NativeHeight, this.props.Document.GetNumber(KeyStore.NativeWidth, 0) * h / w);
     }
 
-    componentDidMount() {
-    }
 
     protected createDropTarget = (ele: HTMLDivElement) => {
         if (this.dropDisposer) {
@@ -60,10 +50,6 @@ export class ImageBox extends React.Component<FieldViewProps> {
             this.dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } });
         }
     }
-
-    componentWillUnmount() {
-    }
-
     onDrop = (e: React.DragEvent) => {
         e.stopPropagation();
         e.preventDefault();
@@ -158,8 +144,8 @@ export class ImageBox extends React.Component<FieldViewProps> {
         let dist = Math.min(nativeWidth / paths.length, 40);
         let left = (nativeWidth - paths.length * dist) / 2;
         return paths.map((p, i) =>
-            <div className="imageBox-placer"  >
-                <div className="imageBox-dot" style={{ transform: `translate(${i * dist + left}px, 0px)` }} key={`i`} onPointerDown={(e: React.PointerEvent) => { e.stopPropagation(); this.onDotDown(i); }} />
+            <div className="imageBox-placer" key={i} >
+                <div className="imageBox-dot" style={{ background: (i == this._photoIndex ? "black" : "gray"), transform: `translate(${i * dist + left}px, 0px)` }} onPointerDown={(e: React.PointerEvent) => { e.stopPropagation(); this.onDotDown(i); }} />
             </div>
         )
     }
@@ -174,7 +160,7 @@ export class ImageBox extends React.Component<FieldViewProps> {
         return (
             <div className="imageBox-cont" onPointerDown={this.onPointerDown} onDrop={this.onDrop} ref={this.createDropTarget} onContextMenu={this.specificContextMenu}>
                 <img src={paths[Math.min(paths.length, this._photoIndex)]} style={{ objectFit: (this._photoIndex == 0 ? undefined : "contain") }} width={nativeWidth} alt="Image not found" ref={this._imgRef} onLoad={this.onLoad} />
-                {this.dots(paths)}
+                {paths.length > 1 ? this.dots(paths) : (null)}
                 {this.lightbox(paths)}
             </div>);
     }
-- 
cgit v1.2.3-70-g09d2


From 1319573481868f2647259fce37cd15b35c3cafad Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 17 Apr 2019 12:07:55 -0400
Subject: fixed onactivechanged exception.  restored preview region

---
 src/client/util/SelectionManager.ts                           |  4 ++--
 src/client/views/Main.tsx                                     |  2 +-
 src/client/views/MainOverlayTextBox.tsx                       |  2 +-
 src/client/views/collections/CollectionBaseView.tsx           |  8 ++++----
 src/client/views/collections/CollectionDockingView.tsx        |  2 +-
 src/client/views/collections/CollectionSchemaView.tsx         | 11 +++++------
 .../collections/collectionFreeForm/CollectionFreeFormView.tsx |  2 +-
 src/client/views/nodes/DocumentView.tsx                       |  2 +-
 src/client/views/nodes/FieldView.tsx                          |  4 ++--
 src/client/views/nodes/KeyValuePair.tsx                       |  2 +-
 10 files changed, 19 insertions(+), 20 deletions(-)

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

diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 320553952..b15a93d9f 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -18,13 +18,13 @@ export namespace SelectionManager {
 
             if (manager.SelectedDocuments.indexOf(doc) === -1) {
                 manager.SelectedDocuments.push(doc);
-                doc.props.onActiveChanged(true);
+                doc.props.whenActiveChanged(true);
             }
         }
 
         @action
         DeselectAll(): void {
-            manager.SelectedDocuments.map(dv => dv.props.onActiveChanged(false));
+            manager.SelectedDocuments.map(dv => dv.props.whenActiveChanged(false));
             manager.SelectedDocuments = [];
             MainOverlayTextBox.Instance.SetTextDoc();
         }
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 0469211fa..84fdeab92 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -190,7 +190,7 @@ export class Main extends React.Component {
                             selectOnLoad={false}
                             focus={emptyDocFunction}
                             parentActive={returnTrue}
-                            onActiveChanged={emptyFunction}
+                            whenActiveChanged={emptyFunction}
                             ContainingCollectionView={undefined} />}
                 </div>
             }
diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx
index 141b3ad74..8cb01117c 100644
--- a/src/client/views/MainOverlayTextBox.tsx
+++ b/src/client/views/MainOverlayTextBox.tsx
@@ -101,7 +101,7 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
             return <div className="mainOverlayTextBox-textInput" style={{ pointerEvents: "none", transform: `translate(${x}px, ${y}px) scale(${1 / s[0]},${1 / s[0]})`, width: "auto", height: "auto" }} >
                 <div className="mainOverlayTextBox-textInput" onPointerDown={this.textBoxDown} ref={this._textProxyDiv} onScroll={this.textScroll} style={{ pointerEvents: "none", transform: `scale(${1}, ${1})`, width: `${w * s[0]}px`, height: `${h * s[0]}px` }}>
                     <FormattedTextBox fieldKey={this._textFieldKey} isOverlay={true} Document={this.TextDoc} isSelected={returnTrue} select={emptyFunction} isTopMost={true}
-                        selectOnLoad={true} ContainingCollectionView={undefined} onActiveChanged={emptyFunction} active={returnTrue} ScreenToLocalTransform={() => this._textXf} focus={emptyDocFunction} />
+                        selectOnLoad={true} ContainingCollectionView={undefined} whenActiveChanged={emptyFunction} active={returnTrue} ScreenToLocalTransform={() => this._textXf} focus={emptyDocFunction} />
                 </div>
             </ div>;
         }
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 4fda38a26..a8b061b04 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -22,7 +22,7 @@ export interface CollectionRenderProps {
     removeDocument: (document: Document) => boolean;
     moveDocument: (document: Document, targetCollection: Document, addDocument: (document: Document) => boolean) => boolean;
     active: () => boolean;
-    onActiveChanged: (isActive: boolean) => void;
+    whenActiveChanged: (isActive: boolean) => void;
 }
 
 export interface CollectionViewProps extends FieldViewProps {
@@ -55,9 +55,9 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
 
     //TODO should this be observable?
     private _isChildActive = false;
-    onActiveChanged = (isActive: boolean) => {
+    whenActiveChanged = (isActive: boolean) => {
         this._isChildActive = isActive;
-        this.props.onActiveChanged(isActive);
+        this.props.whenActiveChanged(isActive);
     }
 
     createsCycle(documentToAdd: Document, containerDocument: Document): boolean {
@@ -184,7 +184,7 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
             removeDocument: this.removeDocument,
             moveDocument: this.moveDocument,
             active: this.active,
-            onActiveChanged: this.onActiveChanged,
+            whenActiveChanged: this.whenActiveChanged,
         };
         const viewtype = this.collectionViewType;
         return (
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 2b886adb6..9ec0b3aeb 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -363,7 +363,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
                     isTopMost={true}
                     selectOnLoad={false}
                     parentActive={returnTrue}
-                    onActiveChanged={emptyFunction}
+                    whenActiveChanged={emptyFunction}
                     focus={emptyDocFunction}
                     ContainingCollectionView={undefined} />
             </div>;
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 1defdba7e..15b7617ae 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -24,7 +24,7 @@ import { EditableView } from "../EditableView";
 import { DocumentView } from "../nodes/DocumentView";
 import { FieldView, FieldViewProps } from "../nodes/FieldView";
 import "./CollectionSchemaView.scss";
-import { CollectionSubView } from "./CollectionSubView";
+import { CollectionSubView, SubCollectionViewProps } from "./CollectionSubView";
 
 
 // bcz: need to add drag and drop of rows and columns.  This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657
@@ -70,7 +70,6 @@ export class CollectionSchemaView extends CollectionSubView {
 
     @computed get splitPercentage() { return this.props.Document.GetNumber(KeyStore.SchemaSplitPercentage, 0); }
 
-
     renderCell = (rowProps: CellInfo) => {
         let props: FieldViewProps = {
             Document: rowProps.value[0],
@@ -83,7 +82,7 @@ export class CollectionSchemaView extends CollectionSubView {
             ScreenToLocalTransform: Transform.Identity,
             focus: emptyDocFunction,
             active: returnFalse,
-            onActiveChanged: emptyFunction,
+            whenActiveChanged: emptyFunction,
         };
         let contents = (
             <FieldView {...props} />
@@ -285,7 +284,7 @@ export class CollectionSchemaView extends CollectionSubView {
         this._optionsActivated++;
     }
 
-    @observable previewScript: string = "this";
+    @observable previewScript: string = "";
     @action
     onPreviewScriptChange = (e: React.ChangeEvent<HTMLInputElement>) => {
         this.previewScript = e.currentTarget.value;
@@ -299,7 +298,7 @@ export class CollectionSchemaView extends CollectionSubView {
         const selected = children.length > this._selectedIndex ? children[this._selectedIndex] : undefined;
         //all the keys/columns that will be displayed in the schema
         const allKeys = this.findAllDocumentKeys;
-        let doc: any = selected ? selected.Get(new Key(this.previewScript)) : undefined;
+        let doc: any = selected ? (this.previewScript ? selected.Get(new Key(this.previewScript)) : selected) : undefined;
 
         // let doc = CompileScript(this.previewScript, { this: selected }, true)();
         let content = this._selectedIndex === -1 || !selected ? (null) : (
@@ -318,7 +317,7 @@ export class CollectionSchemaView extends CollectionSubView {
                                 ContainingCollectionView={this.props.CollectionView}
                                 focus={emptyDocFunction}
                                 parentActive={this.props.active}
-                                onActiveChanged={this.props.onActiveChanged} /> : null}
+                                whenActiveChanged={this.props.whenActiveChanged} /> : null}
                         <input value={this.previewScript} onChange={this.onPreviewScriptChange}
                             style={{ position: 'absolute', bottom: '0px' }} />
                     </div>
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 97708ce19..80322c900 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -248,7 +248,7 @@ export class CollectionFreeFormView extends CollectionSubView {
             ContainingCollectionView: this.props.CollectionView,
             focus: this.focusDocument,
             parentActive: this.props.active,
-            onActiveChanged: this.props.active,
+            whenActiveChanged: this.props.active,
         };
     }
 
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index b99e449be..d74f9fc57 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -39,7 +39,7 @@ export interface DocumentViewProps {
     focus: (doc: Document) => void;
     selectOnLoad: boolean;
     parentActive: () => boolean;
-    onActiveChanged: (isActive: boolean) => void;
+    whenActiveChanged: (isActive: boolean) => void;
 }
 export interface JsxArgs extends DocumentViewProps {
     Keys: { [name: string]: Key };
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index ebd25f937..e9f6950ff 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -43,7 +43,7 @@ export interface FieldViewProps {
     moveDocument?: (document: Document, targetCollection: Document, addDocument: (document: Document) => boolean) => boolean;
     ScreenToLocalTransform: () => Transform;
     active: () => boolean;
-    onActiveChanged: (isActive: boolean) => void;
+    whenActiveChanged: (isActive: boolean) => void;
     focus: (doc: Document) => void;
 }
 
@@ -95,7 +95,7 @@ export class FieldView extends React.Component<FieldViewProps> {
                     layoutKey={KeyStore.Layout}
                     ContainingCollectionView={this.props.ContainingCollectionView}
                     parentActive={this.props.active}
-                    onActiveChanged={this.props.onActiveChanged} />
+                    whenActiveChanged={this.props.whenActiveChanged} />
             );
         }
         else if (field instanceof ListField) {
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index 5d69f23b2..d480eb5af 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -48,7 +48,7 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
             isTopMost: false,
             selectOnLoad: false,
             active: returnFalse,
-            onActiveChanged: emptyFunction,
+            whenActiveChanged: emptyFunction,
             ScreenToLocalTransform: Transform.Identity,
             focus: emptyDocFunction,
         };
-- 
cgit v1.2.3-70-g09d2


From 8d7d4d4bee15f250eb93f4fb850075e99bebedd3 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 17 Apr 2019 14:17:29 -0400
Subject: schemaviews

---
 .../views/collections/CollectionSchemaView.scss    | 10 ++-
 .../views/collections/CollectionSchemaView.tsx     | 89 +++++++++++++---------
 2 files changed, 60 insertions(+), 39 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index c8bfedff4..8c51ed752 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -71,7 +71,10 @@ ul {
         position: absolute;
         height: 100%;
         width: 100%;
-        overflow: auto;
+        .documentView-node:first-child {
+            position: relative;
+            background: $light-color;
+        }
     }
     .collectionSchemaView-previewRegion {
         position: relative;
@@ -193,6 +196,11 @@ ul {
         border-bottom-style: solid;
         border-bottom-width: 1;
     }
+    .documentView-node-topmost {
+        text-align:left;
+        transform-origin: center top;
+        display: inline-block;
+    }
     .documentView-node:first-child {
         background: $light-color;
         .imageBox-cont img {
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 15b7617ae..9e740eb00 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -12,7 +12,7 @@ import { Field, Opt } from "../../../fields/Field";
 import { Key } from "../../../fields/Key";
 import { KeyStore } from "../../../fields/KeyStore";
 import { ListField } from "../../../fields/ListField";
-import { emptyDocFunction, emptyFunction, returnFalse, returnOne } from "../../../Utils";
+import { emptyDocFunction, emptyFunction, returnFalse, returnOne, Utils } from "../../../Utils";
 import { Server } from "../../Server";
 import { SetupDrag } from "../../util/DragManager";
 import { CompileScript, ToField } from "../../util/Scripting";
@@ -25,6 +25,7 @@ import { DocumentView } from "../nodes/DocumentView";
 import { FieldView, FieldViewProps } from "../nodes/FieldView";
 import "./CollectionSchemaView.scss";
 import { CollectionSubView, SubCollectionViewProps } from "./CollectionSubView";
+import { CollectionDockingView } from "./CollectionDockingView";
 
 
 // bcz: need to add drag and drop of rows and columns.  This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657
@@ -60,7 +61,6 @@ export class CollectionSchemaView extends CollectionSubView {
     private DIVIDER_WIDTH = 4;
 
     @observable _columns: Array<Key> = [KeyStore.Title, KeyStore.Data, KeyStore.Author];
-    @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;
@@ -234,22 +234,9 @@ export class CollectionSchemaView extends CollectionSubView {
     setTableDimensions = (r: any) => {
         this._tableWidth = r.entry.width;
     }
-    @action
-    setScaling = (r: any) => {
-        const children = this.props.Document.GetList(this.props.fieldKey, [] as Document[]);
-        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._contentScaling = r.entry.width / selected!.GetNumber(KeyStore.NativeWidth, r.entry.width);
-    }
 
     @computed
     get borderWidth() { return COLLECTION_BORDER_WIDTH; }
-    getContentScaling = (): number => this._contentScaling;
-    getPanelWidth = (): number => this._panelWidth;
-    getPanelHeight = (): number => this._panelHeight;
-    getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH - this._dividerX, - this.borderWidth).scale(1 / this._contentScaling);
-    getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH - this._dividerX - this._tableWidth, - this.borderWidth).scale(1 / this._contentScaling);
 
     onPointerDown = (e: React.PointerEvent): void => {
         if (e.button === 0 && !e.altKey && !e.ctrlKey && !e.metaKey) {
@@ -289,37 +276,63 @@ export class CollectionSchemaView extends CollectionSubView {
     onPreviewScriptChange = (e: React.ChangeEvent<HTMLInputElement>) => {
         this.previewScript = e.currentTarget.value;
     }
+    private get _document(): Document | undefined {
+        const children = this.props.Document.GetList(this.props.fieldKey, [] as Document[]);
+        const selected = children.length > this._selectedIndex ? children[this._selectedIndex] : undefined;
+        return selected ? (this.previewScript ? selected.Get(new Key(this.previewScript)) as Document : selected) : undefined;
+    }
 
+    private nativeWidth = () => this._document!.GetNumber(KeyStore.NativeWidth, this._panelWidth);
+    private nativeHeight = () => this._document!.GetNumber(KeyStore.NativeHeight, this._panelHeight);
+    private panelWidth = () => this.nativeWidth() * this._contentScaling();
+    private panelHeight = () => this.nativeHeight() * this._contentScaling();
+    private _contentScaling = () => {
+        let wscale = this._panelWidth / (this.nativeWidth() ? this.nativeWidth() : this._panelWidth);
+        if (wscale * this.nativeHeight() > this._panelHeight)
+            return this._panelHeight / (this.nativeHeight() ? this.nativeHeight() : this._panelHeight);
+        return wscale;
+    }
+    getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH - this._dividerX - this._tableWidth - this.offset(), - this.borderWidth).scale(1 / this._contentScaling());
+    getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH - this._dividerX, - this.borderWidth).scale(1 / this._contentScaling());
+
+    offset = () => ((this.props as any).PanelWidth() * this.splitPercentage / 100 - this.nativeWidth() * this._contentScaling()) / 2;
+    @action
+    setScaling = (r: any) => {
+        this._panelWidth = r.entry.width;
+        this._panelHeight = r.entry.height ? r.entry.height : this._panelHeight;
+    }
     render() {
         library.add(faCog);
         library.add(faPlus);
+        if (!this._document)
+            return (null);
         const columns = this.columns;
-        const children = this.props.Document.GetList(this.props.fieldKey, [] as Document[]);
-        const selected = children.length > this._selectedIndex ? children[this._selectedIndex] : undefined;
-        //all the keys/columns that will be displayed in the schema
+        let doc = this._document;
+        const childs = this.props.Document.GetList(this.props.fieldKey, [] as Document[]);
         const allKeys = this.findAllDocumentKeys;
-        let doc: any = selected ? (this.previewScript ? selected.Get(new Key(this.previewScript)) : selected) : undefined;
-
         // let doc = CompileScript(this.previewScript, { this: selected }, true)();
-        let content = this._selectedIndex === -1 || !selected ? (null) : (
+        let offset = this.offset();
+        let content = !doc ? (null) : (
             <Measure onResize={this.setScaling}>
                 {({ measureRef }) =>
                     <div className="collectionSchemaView-content" ref={measureRef}>
-                        {doc instanceof Document ?
-                            <DocumentView Document={doc}
-                                addDocument={this.props.addDocument} removeDocument={this.props.removeDocument}
-                                isTopMost={false}
-                                selectOnLoad={false}
-                                ScreenToLocalTransform={this.getPreviewTransform}
-                                ContentScaling={this.getContentScaling}
-                                PanelWidth={this.getPanelWidth}
-                                PanelHeight={this.getPanelHeight}
-                                ContainingCollectionView={this.props.CollectionView}
-                                focus={emptyDocFunction}
-                                parentActive={this.props.active}
-                                whenActiveChanged={this.props.whenActiveChanged} /> : null}
-                        <input value={this.previewScript} onChange={this.onPreviewScriptChange}
-                            style={{ position: 'absolute', bottom: '0px' }} />
+                        <div style={{ transform: `translate(${offset}px, 0px)`, height: "100%", position: "absolute" }}>
+                            {doc instanceof Document ?
+                                <DocumentView Document={doc}
+                                    addDocument={this.props.addDocument} removeDocument={this.props.removeDocument}
+                                    isTopMost={false}
+                                    selectOnLoad={false}
+                                    ScreenToLocalTransform={this.getPreviewTransform}
+                                    ContentScaling={this._contentScaling}
+                                    PanelWidth={this.panelWidth}
+                                    PanelHeight={this.panelHeight}
+                                    ContainingCollectionView={this.props.CollectionView}
+                                    focus={emptyDocFunction}
+                                    parentActive={this.props.active}
+                                    whenActiveChanged={this.props.whenActiveChanged} /> : null}
+                            <input value={this.previewScript} onChange={this.onPreviewScriptChange}
+                                style={{ position: 'absolute', bottom: '0px', left: "0px" }} />
+                        </div>
                     </div>
                 }
             </Measure>
@@ -355,8 +368,8 @@ export class CollectionSchemaView extends CollectionSubView {
                         {({ measureRef }) =>
                             <div className="collectionSchemaView-tableContainer" ref={measureRef} style={{ width: `calc(100% - ${this.splitPercentage}%)` }}>
                                 <ReactTable
-                                    data={children}
-                                    pageSize={children.length}
+                                    data={childs}
+                                    pageSize={childs.length}
                                     page={0}
                                     showPagination={false}
                                     columns={columns.map(col => ({
-- 
cgit v1.2.3-70-g09d2


From 3ec6343ad5f15cfe43c233f29453f02c435aecda Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 17 Apr 2019 19:12:38 -0400
Subject: fixed schema layout

---
 .../views/collections/CollectionSchemaView.scss    |  11 ++
 .../views/collections/CollectionSchemaView.tsx     | 164 ++++++++++-----------
 2 files changed, 86 insertions(+), 89 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 8c51ed752..580bce21b 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -71,6 +71,17 @@ ul {
         position: absolute;
         height: 100%;
         width: 100%;
+        .collectionSchemaView-previewDoc {
+            height: 100%;
+            width: 100%; 
+            position: absolute;
+        }
+        .collectionSchemaView-input {
+            position: absolute;
+            max-width: 150px;
+            width: 100%;
+            bottom: 0px;
+        }
         .documentView-node:first-child {
             position: relative;
             background: $light-color;
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 9e740eb00..f7d69aee1 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -61,9 +61,6 @@ export class CollectionSchemaView extends CollectionSubView {
     private DIVIDER_WIDTH = 4;
 
     @observable _columns: Array<Key> = [KeyStore.Title, KeyStore.Data, KeyStore.Author];
-    @observable _dividerX = 0;
-    @observable _panelWidth = 0;
-    @observable _panelHeight = 0;
     @observable _selectedIndex = 0;
     @observable _columnsPercentage = 0;
     @observable _keys: Key[] = [];
@@ -229,11 +226,6 @@ export class CollectionSchemaView extends CollectionSubView {
         document.addEventListener('pointerup', this.onDividerUp);
     }
 
-    @observable _tableWidth = 0;
-    @action
-    setTableDimensions = (r: any) => {
-        this._tableWidth = r.entry.width;
-    }
 
     @computed
     get borderWidth() { return COLLECTION_BORDER_WIDTH; }
@@ -276,72 +268,65 @@ export class CollectionSchemaView extends CollectionSubView {
     onPreviewScriptChange = (e: React.ChangeEvent<HTMLInputElement>) => {
         this.previewScript = e.currentTarget.value;
     }
-    private get _document(): Document | undefined {
+    private get previewDocument(): Document | undefined {
         const children = this.props.Document.GetList(this.props.fieldKey, [] as Document[]);
         const selected = children.length > this._selectedIndex ? children[this._selectedIndex] : undefined;
         return selected ? (this.previewScript ? selected.Get(new Key(this.previewScript)) as Document : selected) : undefined;
     }
 
-    private nativeWidth = () => this._document!.GetNumber(KeyStore.NativeWidth, this._panelWidth);
-    private nativeHeight = () => this._document!.GetNumber(KeyStore.NativeHeight, this._panelHeight);
-    private panelWidth = () => this.nativeWidth() * this._contentScaling();
-    private panelHeight = () => this.nativeHeight() * this._contentScaling();
-    private _contentScaling = () => {
-        let wscale = this._panelWidth / (this.nativeWidth() ? this.nativeWidth() : this._panelWidth);
-        if (wscale * this.nativeHeight() > this._panelHeight)
-            return this._panelHeight / (this.nativeHeight() ? this.nativeHeight() : this._panelHeight);
+    getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate(
+        - this.borderWidth - this.DIVIDER_WIDTH - this.tableWidth - this.previewPanelCenteringOffset,
+        - this.borderWidth).scale(1 / this.previewContentScaling());
+    getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH, - this.borderWidth).scale(1 / this.previewContentScaling());
+
+    get tableWidth() { return (this.props as any).PanelWidth() * (1 - this.splitPercentage / 100); }
+    get previewRegionHeight() { return (this.props as any).PanelHeight(); }
+    get previewRegionWidth() { return (this.props as any).PanelWidth() * this.splitPercentage / 100 - this.DIVIDER_WIDTH; }
+
+    get previewPanelCenteringOffset() { return (this.previewRegionWidth - this.previewDocNativeWidth() * this.previewContentScaling()) / 2; }
+    private previewPanelWidth = () => this.previewDocNativeWidth() * this.previewContentScaling();
+    private previewPanelHeight = () => this.previewDocNativeHeight() * this.previewContentScaling();
+    private previewContentScaling = () => {
+        let wscale = this.previewRegionWidth / (this.previewDocNativeWidth() ? this.previewDocNativeWidth() : this.previewRegionWidth);
+        if (wscale * this.previewDocNativeHeight() > this.previewRegionHeight)
+            return this.previewRegionHeight / (this.previewDocNativeHeight() ? this.previewDocNativeHeight() : this.previewRegionHeight);
         return wscale;
     }
-    getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH - this._dividerX - this._tableWidth - this.offset(), - this.borderWidth).scale(1 / this._contentScaling());
-    getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH - this._dividerX, - this.borderWidth).scale(1 / this._contentScaling());
+    private previewDocNativeWidth = () => this.previewDocument!.GetNumber(KeyStore.NativeWidth, this.previewRegionWidth);
+    private previewDocNativeHeight = () => this.previewDocument!.GetNumber(KeyStore.NativeHeight, this.previewRegionHeight);
 
-    offset = () => ((this.props as any).PanelWidth() * this.splitPercentage / 100 - this.nativeWidth() * this._contentScaling()) / 2;
-    @action
-    setScaling = (r: any) => {
-        this._panelWidth = r.entry.width;
-        this._panelHeight = r.entry.height ? r.entry.height : this._panelHeight;
-    }
-    render() {
-        library.add(faCog);
-        library.add(faPlus);
-        if (!this._document)
-            return (null);
-        const columns = this.columns;
-        let doc = this._document;
-        const childs = this.props.Document.GetList(this.props.fieldKey, [] as Document[]);
-        const allKeys = this.findAllDocumentKeys;
+    @computed
+    get previewPanel() {
+        let doc = this.previewDocument;
         // let doc = CompileScript(this.previewScript, { this: selected }, true)();
-        let offset = this.offset();
-        let content = !doc ? (null) : (
-            <Measure onResize={this.setScaling}>
-                {({ measureRef }) =>
-                    <div className="collectionSchemaView-content" ref={measureRef}>
-                        <div style={{ transform: `translate(${offset}px, 0px)`, height: "100%", position: "absolute" }}>
-                            {doc instanceof Document ?
-                                <DocumentView Document={doc}
-                                    addDocument={this.props.addDocument} removeDocument={this.props.removeDocument}
-                                    isTopMost={false}
-                                    selectOnLoad={false}
-                                    ScreenToLocalTransform={this.getPreviewTransform}
-                                    ContentScaling={this._contentScaling}
-                                    PanelWidth={this.panelWidth}
-                                    PanelHeight={this.panelHeight}
-                                    ContainingCollectionView={this.props.CollectionView}
-                                    focus={emptyDocFunction}
-                                    parentActive={this.props.active}
-                                    whenActiveChanged={this.props.whenActiveChanged} /> : null}
-                            <input value={this.previewScript} onChange={this.onPreviewScriptChange}
-                                style={{ position: 'absolute', bottom: '0px', left: "0px" }} />
-                        </div>
+        let inputPanelWidth = Math.min(75, this.previewPanelWidth() / 2);
+        return !doc ? (null) : (
+            <div className="collectionSchemaView-previewRegion" style={{ width: `calc(${this.props.Document.GetNumber(KeyStore.SchemaSplitPercentage, 0)}% - ${this.DIVIDER_WIDTH}px)` }}>
+                <div className="collectionSchemaView-content" >
+                    <div className="collectionSchemaView-previewDoc" style={{ transform: `translate(${this.previewPanelCenteringOffset}px, 0px)` }}>
+                        {doc instanceof Document ?
+                            <DocumentView Document={doc} isTopMost={false} selectOnLoad={false}
+                                addDocument={this.props.addDocument} removeDocument={this.props.removeDocument}
+                                ScreenToLocalTransform={this.getPreviewTransform}
+                                ContentScaling={this.previewContentScaling}
+                                PanelWidth={this.previewPanelWidth} PanelHeight={this.previewPanelHeight}
+                                ContainingCollectionView={this.props.CollectionView}
+                                focus={emptyDocFunction}
+                                parentActive={this.props.active}
+                                whenActiveChanged={this.props.whenActiveChanged}
+                            /> :
+                            null}
                     </div>
-                }
-            </Measure>
+                    <input className="collectionSchemaView-input" value={this.previewScript} onChange={this.onPreviewScriptChange}
+                        style={{ left: `calc(50% - ${inputPanelWidth}px)` }} />
+                </div>
+            </div>
         );
-        let dividerDragger = this.splitPercentage === 0 ? (null) :
-            <div className="collectionSchemaView-dividerDragger" onPointerDown={this.onDividerDown} style={{ width: `${this.DIVIDER_WIDTH}px` }} />;
-
-        //options button and menu
-        let optionsMenu = !this.props.active() ? (null) : (<Flyout
+    }
+    @computed
+    get tableOptionsPanel() {
+        const allKeys = this.findAllDocumentKeys;
+        return !this.props.active() ? (null) : (<Flyout
             anchorPoint={anchorPoints.LEFT_TOP}
             content={<div>
                 <div id="schema-options-header"><h5><b>Options</b></h5></div>
@@ -360,37 +345,38 @@ export class CollectionSchemaView extends CollectionSubView {
             }>
             <button id="schemaOptionsMenuBtn" onPointerDown={this.OptionsMenuDown}><FontAwesomeIcon style={{ color: "white" }} icon="cog" size="sm" /></button>
         </Flyout>);
+    }
 
+    @computed
+    get dividerDragger() {
+        return this.splitPercentage === 0 ? (null) :
+            <div className="collectionSchemaView-dividerDragger" onPointerDown={this.onDividerDown} style={{ width: `${this.DIVIDER_WIDTH}px` }} />;
+    }
+
+    render() {
+        library.add(faCog);
+        library.add(faPlus);
+        if (!this.previewDocument)
+            return (null);
+
+        const children = this.props.Document.GetList(this.props.fieldKey, [] as Document[]);
         return (
             <div className="collectionSchemaView-container" onPointerDown={this.onPointerDown} onWheel={this.onWheel} ref={this._mainCont}>
                 <div className="collectionSchemaView-dropTarget" onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createDropTarget}>
-                    <Measure onResize={this.setTableDimensions}>
-                        {({ measureRef }) =>
-                            <div className="collectionSchemaView-tableContainer" ref={measureRef} style={{ width: `calc(100% - ${this.splitPercentage}%)` }}>
-                                <ReactTable
-                                    data={childs}
-                                    pageSize={childs.length}
-                                    page={0}
-                                    showPagination={false}
-                                    columns={columns.map(col => ({
-                                        Header: col.Name,
-                                        accessor: (doc: Document) => [doc, col],
-                                        id: col.Id
-                                    }))}
-                                    column={{
-                                        ...ReactTableDefaults.column,
-                                        Cell: this.renderCell,
-
-                                    }}
-                                    getTrProps={this.getTrProps}
-                                />
-                            </div>}
-                    </Measure>
-                    {dividerDragger}
-                    <div className="collectionSchemaView-previewRegion" style={{ width: `calc(${this.props.Document.GetNumber(KeyStore.SchemaSplitPercentage, 0)}% - ${this.DIVIDER_WIDTH}px)` }}>
-                        {content}
+                    <div className="collectionSchemaView-tableContainer" style={{ width: `calc(100% - ${this.splitPercentage}%)` }}>
+                        <ReactTable data={children} page={0} pageSize={children.length} showPagination={false}
+                            columns={this.columns.map(col => ({
+                                Header: col.Name,
+                                accessor: (doc: Document) => [doc, col],
+                                id: col.Id
+                            }))}
+                            column={{ ...ReactTableDefaults.column, Cell: this.renderCell, }}
+                            getTrProps={this.getTrProps}
+                        />
                     </div>
-                    {optionsMenu}
+                    {this.dividerDragger}
+                    {this.previewPanel}
+                    {this.tableOptionsPanel}
                 </div>
             </div >
         );
-- 
cgit v1.2.3-70-g09d2


From d998bdaa38677e4888393db01cf9b73bb49f2cc9 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 17 Apr 2019 19:55:12 -0400
Subject: some schema view simplifications

---
 .../views/collections/CollectionSchemaView.scss    | 125 ++++++++++-----------
 .../views/collections/CollectionSchemaView.tsx     |  98 ++++++++--------
 src/client/views/collections/CollectionSubView.tsx |   6 +-
 3 files changed, 112 insertions(+), 117 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 580bce21b..bced0d5d4 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -1,61 +1,5 @@
 @import "../globalCssVariables";
 
-//options menu styling
-#schemaOptionsMenuBtn {
-    position: absolute;
-    height: 20px;
-    width: 20px;
-    border-radius: 50%;
-    z-index: 21; 
-    right: 4px;
-    top: 4px; 
-    pointer-events: auto;
-    background-color:black;
-    display:inline-block;
-    padding: 0px;
-    font-size: 100%;
-}
-
-ul {
-    list-style-type: disc;
-}
-
-#schema-options-header {
-    text-align: center;
-    padding: 0px;
-    margin: 0px;
-}
-.schema-options-subHeader {
-    color: $intermediate-color;
-    margin-bottom: 5px;
-}
-#schemaOptionsMenuBtn:hover {
-    transform: scale(1.15);
-}
-
-#preview-schema-checkbox-div {
-    margin-left: 20px;
-    font-size: 12px;
-}
-
-  #options-flyout-div {
-    text-align: left;
-    padding:0px;
-    z-index: 100;
-    font-family: $sans-serif;
-    padding-left: 5px;
-  }
-
-  #schema-col-checklist {
-    overflow: scroll;
-    text-align: left;
-    //background-color: $light-color-secondary;
-    line-height: 25px;
-    max-height: 175px;
-    font-family: $sans-serif;
-    font-size: 12px;
-  }
-  
 
 .collectionSchemaView-container {
     border-width: $COLLECTION_BORDER_WIDTH;
@@ -67,10 +11,11 @@ ul {
     width: 100%;
     height: 100%;
     
-    .collectionSchemaView-content {
-        position: absolute;
+    .collectionSchemaView-previewRegion {
+        position: relative;
+        background: $light-color;
+        float: left;
         height: 100%;
-        width: 100%;
         .collectionSchemaView-previewDoc {
             height: 100%;
             width: 100%; 
@@ -87,12 +32,6 @@ ul {
             background: $light-color;
         }
     }
-    .collectionSchemaView-previewRegion {
-        position: relative;
-        background: $light-color;
-        float: left;
-        height: 100%;
-    }
     .collectionSchemaView-previewHandle {
         position: absolute;
         height: 15px;
@@ -219,6 +158,62 @@ ul {
         }
     }
 }
+//options menu styling
+#schemaOptionsMenuBtn {
+    position: absolute;
+    height: 20px;
+    width: 20px;
+    border-radius: 50%;
+    z-index: 21; 
+    right: 4px;
+    top: 4px; 
+    pointer-events: auto;
+    background-color:black;
+    display:inline-block;
+    padding: 0px;
+    font-size: 100%;
+}
+
+ul {
+    list-style-type: disc;
+}
+
+#schema-options-header {
+    text-align: center;
+    padding: 0px;
+    margin: 0px;
+}
+.schema-options-subHeader {
+    color: $intermediate-color;
+    margin-bottom: 5px;
+}
+#schemaOptionsMenuBtn:hover {
+    transform: scale(1.15);
+}
+
+#preview-schema-checkbox-div {
+    margin-left: 20px;
+    font-size: 12px;
+}
+
+  #options-flyout-div {
+    text-align: left;
+    padding:0px;
+    z-index: 100;
+    font-family: $sans-serif;
+    padding-left: 5px;
+  }
+
+  #schema-col-checklist {
+    overflow: scroll;
+    text-align: left;
+    //background-color: $light-color-secondary;
+    line-height: 25px;
+    max-height: 175px;
+    font-family: $sans-serif;
+    font-size: 12px;
+  }
+  
 
 .Resizer {
     box-sizing: border-box;
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index f7d69aee1..4e3149fe4 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -4,7 +4,6 @@ import { faCog, faPlus } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, computed, observable, untracked } from "mobx";
 import { observer } from "mobx-react";
-import Measure from "react-measure";
 import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table";
 import "react-table/react-table.css";
 import { Document } from "../../../fields/Document";
@@ -12,7 +11,7 @@ import { Field, Opt } from "../../../fields/Field";
 import { Key } from "../../../fields/Key";
 import { KeyStore } from "../../../fields/KeyStore";
 import { ListField } from "../../../fields/ListField";
-import { emptyDocFunction, emptyFunction, returnFalse, returnOne, Utils } from "../../../Utils";
+import { emptyDocFunction, emptyFunction, returnFalse } from "../../../Utils";
 import { Server } from "../../Server";
 import { SetupDrag } from "../../util/DragManager";
 import { CompileScript, ToField } from "../../util/Scripting";
@@ -24,8 +23,7 @@ import { EditableView } from "../EditableView";
 import { DocumentView } from "../nodes/DocumentView";
 import { FieldView, FieldViewProps } from "../nodes/FieldView";
 import "./CollectionSchemaView.scss";
-import { CollectionSubView, SubCollectionViewProps } from "./CollectionSubView";
-import { CollectionDockingView } from "./CollectionDockingView";
+import { CollectionSubView } from "./CollectionSubView";
 
 
 // bcz: need to add drag and drop of rows and columns.  This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657
@@ -56,7 +54,7 @@ class KeyToggle extends React.Component<{ keyId: string, checked: boolean, toggl
 
 @observer
 export class CollectionSchemaView extends CollectionSubView {
-    private _mainCont = React.createRef<HTMLDivElement>();
+    private _mainCont?: HTMLDivElement;
     private _startSplitPercent = 0;
     private DIVIDER_WIDTH = 4;
 
@@ -207,7 +205,7 @@ export class CollectionSchemaView extends CollectionSubView {
 
     @action
     onDividerMove = (e: PointerEvent): void => {
-        let nativeWidth = this._mainCont.current!.getBoundingClientRect();
+        let nativeWidth = this._mainCont!.getBoundingClientRect();
         this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, Math.max(0, 100 - Math.round((e.clientX - nativeWidth.left) / nativeWidth.width * 100)));
     }
     @action
@@ -279,47 +277,41 @@ export class CollectionSchemaView extends CollectionSubView {
         - this.borderWidth).scale(1 / this.previewContentScaling());
     getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH, - this.borderWidth).scale(1 / this.previewContentScaling());
 
-    get tableWidth() { return (this.props as any).PanelWidth() * (1 - this.splitPercentage / 100); }
-    get previewRegionHeight() { return (this.props as any).PanelHeight(); }
-    get previewRegionWidth() { return (this.props as any).PanelWidth() * this.splitPercentage / 100 - this.DIVIDER_WIDTH; }
+    get tableWidth() { return this.props.PanelWidth() * (1 - this.splitPercentage / 100); }
+    get previewRegionHeight() { return this.props.PanelHeight(); }
+    get previewRegionWidth() { return this.props.PanelWidth() * this.splitPercentage / 100 - this.DIVIDER_WIDTH; }
 
-    get previewPanelCenteringOffset() { return (this.previewRegionWidth - this.previewDocNativeWidth() * this.previewContentScaling()) / 2; }
-    private previewPanelWidth = () => this.previewDocNativeWidth() * this.previewContentScaling();
-    private previewPanelHeight = () => this.previewDocNativeHeight() * this.previewContentScaling();
+    private previewDocNativeWidth = () => this.previewDocument!.GetNumber(KeyStore.NativeWidth, this.previewRegionWidth);
+    private previewDocNativeHeight = () => this.previewDocument!.GetNumber(KeyStore.NativeHeight, this.previewRegionHeight);
     private previewContentScaling = () => {
         let wscale = this.previewRegionWidth / (this.previewDocNativeWidth() ? this.previewDocNativeWidth() : this.previewRegionWidth);
         if (wscale * this.previewDocNativeHeight() > this.previewRegionHeight)
             return this.previewRegionHeight / (this.previewDocNativeHeight() ? this.previewDocNativeHeight() : this.previewRegionHeight);
         return wscale;
     }
-    private previewDocNativeWidth = () => this.previewDocument!.GetNumber(KeyStore.NativeWidth, this.previewRegionWidth);
-    private previewDocNativeHeight = () => this.previewDocument!.GetNumber(KeyStore.NativeHeight, this.previewRegionHeight);
+    private previewPanelWidth = () => this.previewDocNativeWidth() * this.previewContentScaling();
+    private previewPanelHeight = () => this.previewDocNativeHeight() * this.previewContentScaling();
+    get previewPanelCenteringOffset() { return (this.previewRegionWidth - this.previewDocNativeWidth() * this.previewContentScaling()) / 2; }
 
     @computed
     get previewPanel() {
-        let doc = this.previewDocument;
         // let doc = CompileScript(this.previewScript, { this: selected }, true)();
-        let inputPanelWidth = Math.min(75, this.previewPanelWidth() / 2);
-        return !doc ? (null) : (
+        return !this.previewDocument ? (null) : (
             <div className="collectionSchemaView-previewRegion" style={{ width: `calc(${this.props.Document.GetNumber(KeyStore.SchemaSplitPercentage, 0)}% - ${this.DIVIDER_WIDTH}px)` }}>
-                <div className="collectionSchemaView-content" >
-                    <div className="collectionSchemaView-previewDoc" style={{ transform: `translate(${this.previewPanelCenteringOffset}px, 0px)` }}>
-                        {doc instanceof Document ?
-                            <DocumentView Document={doc} isTopMost={false} selectOnLoad={false}
-                                addDocument={this.props.addDocument} removeDocument={this.props.removeDocument}
-                                ScreenToLocalTransform={this.getPreviewTransform}
-                                ContentScaling={this.previewContentScaling}
-                                PanelWidth={this.previewPanelWidth} PanelHeight={this.previewPanelHeight}
-                                ContainingCollectionView={this.props.CollectionView}
-                                focus={emptyDocFunction}
-                                parentActive={this.props.active}
-                                whenActiveChanged={this.props.whenActiveChanged}
-                            /> :
-                            null}
-                    </div>
-                    <input className="collectionSchemaView-input" value={this.previewScript} onChange={this.onPreviewScriptChange}
-                        style={{ left: `calc(50% - ${inputPanelWidth}px)` }} />
+                <div className="collectionSchemaView-previewDoc" style={{ transform: `translate(${this.previewPanelCenteringOffset}px, 0px)` }}>
+                    <DocumentView Document={this.previewDocument} isTopMost={false} selectOnLoad={false}
+                        addDocument={this.props.addDocument} removeDocument={this.props.removeDocument}
+                        ScreenToLocalTransform={this.getPreviewTransform}
+                        ContentScaling={this.previewContentScaling}
+                        PanelWidth={this.previewPanelWidth} PanelHeight={this.previewPanelHeight}
+                        ContainingCollectionView={this.props.CollectionView}
+                        focus={emptyDocFunction}
+                        parentActive={this.props.active}
+                        whenActiveChanged={this.props.whenActiveChanged}
+                    />
                 </div>
+                <input className="collectionSchemaView-input" value={this.previewScript} onChange={this.onPreviewScriptChange}
+                    style={{ left: `calc(50% - ${Math.min(75, this.previewPanelWidth() / 2)}px)` }} />
             </div>
         );
     }
@@ -353,6 +345,11 @@ export class CollectionSchemaView extends CollectionSubView {
             <div className="collectionSchemaView-dividerDragger" onPointerDown={this.onDividerDown} style={{ width: `${this.DIVIDER_WIDTH}px` }} />;
     }
 
+    createTarget = (ele: HTMLDivElement) => {
+        this._mainCont = ele;
+        super.CreateDropTarget(ele);
+    }
+
     render() {
         library.add(faCog);
         library.add(faPlus);
@@ -361,24 +358,23 @@ export class CollectionSchemaView extends CollectionSubView {
 
         const children = this.props.Document.GetList(this.props.fieldKey, [] as Document[]);
         return (
-            <div className="collectionSchemaView-container" onPointerDown={this.onPointerDown} onWheel={this.onWheel} ref={this._mainCont}>
-                <div className="collectionSchemaView-dropTarget" onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createDropTarget}>
-                    <div className="collectionSchemaView-tableContainer" style={{ width: `calc(100% - ${this.splitPercentage}%)` }}>
-                        <ReactTable data={children} page={0} pageSize={children.length} showPagination={false}
-                            columns={this.columns.map(col => ({
-                                Header: col.Name,
-                                accessor: (doc: Document) => [doc, col],
-                                id: col.Id
-                            }))}
-                            column={{ ...ReactTableDefaults.column, Cell: this.renderCell, }}
-                            getTrProps={this.getTrProps}
-                        />
-                    </div>
-                    {this.dividerDragger}
-                    {this.previewPanel}
-                    {this.tableOptionsPanel}
+            <div className="collectionSchemaView-container" onPointerDown={this.onPointerDown} onWheel={this.onWheel}
+                onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createTarget}>
+                <div className="collectionSchemaView-tableContainer" style={{ width: `calc(100% - ${this.splitPercentage}%)` }}>
+                    <ReactTable data={children} page={0} pageSize={children.length} showPagination={false}
+                        columns={this.columns.map(col => ({
+                            Header: col.Name,
+                            accessor: (doc: Document) => [doc, col],
+                            id: col.Id
+                        }))}
+                        column={{ ...ReactTableDefaults.column, Cell: this.renderCell, }}
+                        getTrProps={this.getTrProps}
+                    />
                 </div>
-            </div >
+                {this.dividerDragger}
+                {this.previewPanel}
+                {this.tableOptionsPanel}
+            </div>
         );
     }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index d3d69b1af..5c3b2e586 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -15,7 +15,6 @@ import { ServerUtils } from "../../../server/ServerUtil";
 import { Server } from "../../Server";
 import { FieldViewProps } from "../nodes/FieldView";
 import * as rp from 'request-promise';
-import { emptyFunction } from "../../../Utils";
 import { CollectionView } from "./CollectionView";
 import { CollectionPDFView } from "./CollectionPDFView";
 import { CollectionVideoView } from "./CollectionVideoView";
@@ -24,6 +23,8 @@ export interface CollectionViewProps extends FieldViewProps {
     addDocument: (document: Document, allowDuplicates?: boolean) => boolean;
     removeDocument: (document: Document) => boolean;
     moveDocument: (document: Document, targetCollection: Document, addDocument: (document: Document) => boolean) => boolean;
+    PanelWidth: () => number;
+    PanelHeight: () => number;
 }
 
 export interface SubCollectionViewProps extends CollectionViewProps {
@@ -42,6 +43,9 @@ export class CollectionSubView extends React.Component<SubCollectionViewProps> {
             this.dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } });
         }
     }
+    protected CreateDropTarget(ele: HTMLDivElement) {
+        this.createDropTarget(ele);
+    }
 
     @action
     protected setCursorPosition(position: [number, number]) {
-- 
cgit v1.2.3-70-g09d2


From 6c56cbad38efbde578e2c2c90cbce4b7ff033059 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 17 Apr 2019 21:02:12 -0400
Subject: final cleanup of schema views

---
 .../views/collections/CollectionSchemaView.tsx     | 144 +++++++++------------
 1 file changed, 59 insertions(+), 85 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 4e3149fe4..08c9740d0 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -33,22 +33,17 @@ import { CollectionSubView } from "./CollectionSubView";
 class KeyToggle extends React.Component<{ keyId: string, checked: boolean, toggle: (key: Key) => void }> {
     @observable key: Key | undefined;
 
-    componentWillReceiveProps() {
-        Server.GetField(this.props.keyId, action((field: Opt<Field>) => {
-            if (field instanceof Key) {
-                this.key = field;
-            }
-        }));
+    constructor(props: any) {
+        super(props);
+        Server.GetField(this.props.keyId, action((field: Opt<Field>) => field instanceof Key && (this.key = field)));
     }
 
     render() {
-        if (this.key) {
-            return (<div key={this.key.Id}>
+        return !this.key ? (null) :
+            (<div key={this.key.Id}>
                 <input type="checkbox" checked={this.props.checked} onChange={() => this.key && this.props.toggle(this.key)} />
                 {this.key.Name}
             </div>);
-        }
-        return (null);
     }
 }
 
@@ -62,8 +57,11 @@ export class CollectionSchemaView extends CollectionSubView {
     @observable _selectedIndex = 0;
     @observable _columnsPercentage = 0;
     @observable _keys: Key[] = [];
+    @observable _newKeyName: string = "";
 
     @computed get splitPercentage() { return this.props.Document.GetNumber(KeyStore.SchemaSplitPercentage, 0); }
+    @computed get columns() { return this.props.Document.GetList(KeyStore.ColumnsKey, [] as Key[]); }
+    @computed get borderWidth() { return COLLECTION_BORDER_WIDTH; }
 
     renderCell = (rowProps: CellInfo) => {
         let props: FieldViewProps = {
@@ -159,9 +157,9 @@ export class CollectionSchemaView extends CollectionSubView {
         };
     }
 
-    @computed
-    get columns() {
-        return this.props.Document.GetList(KeyStore.ColumnsKey, [] as Key[]);
+    private createTarget = (ele: HTMLDivElement) => {
+        this._mainCont = ele;
+        super.CreateDropTarget(ele);
     }
 
     @action
@@ -181,26 +179,7 @@ export class CollectionSchemaView extends CollectionSubView {
     //toggles preview side-panel of schema
     @action
     toggleExpander = (event: React.ChangeEvent<HTMLInputElement>) => {
-        this._startSplitPercent = this.splitPercentage;
-        if (this._startSplitPercent === this.splitPercentage) {
-            this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, this.splitPercentage === 0 ? 33 : 0);
-        }
-    }
-
-    @computed
-    get findAllDocumentKeys(): { [id: string]: boolean } {
-        const docs = this.props.Document.GetList(this.props.fieldKey, [] as Document[]);
-        let keys: { [id: string]: boolean } = {};
-        if (this._optionsActivated > -1) {
-            // bcz: ugh.  this is untracked since otherwise a large collection of documents will blast the server for all their fields.
-            //  then as each document's fields come back, we update the documents _proxies.  Each time we do this, the whole schema will be
-            //  invalidated and re-rendered.   This workaround will inquire all of the document fields before the options button is clicked.
-            //  then by the time the options button is clicked, all of the fields should be in place.  If a new field is added while this menu
-            //  is displayed (unlikely) it won't show up until something else changes.
-            untracked(() => docs.map(doc => doc.GetAllPrototypes().map(proto => proto._proxies.forEach((val: any, key: string) => keys[key] = false))));
-        }
-        this.columns.forEach(key => keys[key.Id] = true);
-        return keys;
+        this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, this.splitPercentage === 0 ? 33 : 0);
     }
 
     @action
@@ -224,10 +203,6 @@ export class CollectionSchemaView extends CollectionSubView {
         document.addEventListener('pointerup', this.onDividerUp);
     }
 
-
-    @computed
-    get borderWidth() { return COLLECTION_BORDER_WIDTH; }
-
     onPointerDown = (e: React.PointerEvent): void => {
         if (e.button === 0 && !e.altKey && !e.ctrlKey && !e.metaKey) {
             if (this.props.isSelected())
@@ -236,29 +211,21 @@ export class CollectionSchemaView extends CollectionSubView {
         }
     }
 
-    @action
-    addColumn = () => {
-        this.columns.push(new Key(this.newKeyName));
-        this.newKeyName = "";
-    }
-
-    @observable
-    newKeyName: string = "";
-
-    @action
-    newKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => {
-        this.newKeyName = e.currentTarget.value;
-    }
     onWheel = (e: React.WheelEvent): void => {
         if (this.props.active()) {
             e.stopPropagation();
         }
     }
 
-    @observable _optionsActivated: number = 0;
     @action
-    OptionsMenuDown = (e: React.PointerEvent) => {
-        this._optionsActivated++;
+    addColumn = () => {
+        this.columns.push(new Key(this._newKeyName));
+        this._newKeyName = "";
+    }
+
+    @action
+    newKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+        this._newKeyName = e.currentTarget.value;
     }
 
     @observable previewScript: string = "";
@@ -266,17 +233,12 @@ export class CollectionSchemaView extends CollectionSubView {
     onPreviewScriptChange = (e: React.ChangeEvent<HTMLInputElement>) => {
         this.previewScript = e.currentTarget.value;
     }
-    private get previewDocument(): Document | undefined {
+
+    get previewDocument(): Document | undefined {
         const children = this.props.Document.GetList(this.props.fieldKey, [] as Document[]);
         const selected = children.length > this._selectedIndex ? children[this._selectedIndex] : undefined;
         return selected ? (this.previewScript ? selected.Get(new Key(this.previewScript)) as Document : selected) : undefined;
     }
-
-    getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate(
-        - this.borderWidth - this.DIVIDER_WIDTH - this.tableWidth - this.previewPanelCenteringOffset,
-        - this.borderWidth).scale(1 / this.previewContentScaling());
-    getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH, - this.borderWidth).scale(1 / this.previewContentScaling());
-
     get tableWidth() { return this.props.PanelWidth() * (1 - this.splitPercentage / 100); }
     get previewRegionHeight() { return this.props.PanelHeight(); }
     get previewRegionWidth() { return this.props.PanelWidth() * this.splitPercentage / 100 - this.DIVIDER_WIDTH; }
@@ -292,6 +254,9 @@ export class CollectionSchemaView extends CollectionSubView {
     private previewPanelWidth = () => this.previewDocNativeWidth() * this.previewContentScaling();
     private previewPanelHeight = () => this.previewDocNativeHeight() * this.previewContentScaling();
     get previewPanelCenteringOffset() { return (this.previewRegionWidth - this.previewDocNativeWidth() * this.previewContentScaling()) / 2; }
+    getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate(
+        - this.borderWidth - this.DIVIDER_WIDTH - this.tableWidth - this.previewPanelCenteringOffset,
+        - this.borderWidth).scale(1 / this.previewContentScaling());
 
     @computed
     get previewPanel() {
@@ -315,28 +280,42 @@ export class CollectionSchemaView extends CollectionSubView {
             </div>
         );
     }
-    @computed
+
+    get documentKeysCheckList() {
+        const docs = this.props.Document.GetList(this.props.fieldKey, [] as Document[]);
+        let keys: { [id: string]: boolean } = {};
+        // bcz: ugh.  this is untracked since otherwise a large collection of documents will blast the server for all their fields.
+        //  then as each document's fields come back, we update the documents _proxies.  Each time we do this, the whole schema will be
+        //  invalidated and re-rendered.   This workaround will inquire all of the document fields before the options button is clicked.
+        //  then by the time the options button is clicked, all of the fields should be in place.  If a new field is added while this menu
+        //  is displayed (unlikely) it won't show up until something else changes.
+        untracked(() => docs.map(doc => doc.GetAllPrototypes().map(proto => proto._proxies.forEach((val: any, key: string) => keys[key] = false))));
+
+        this.columns.forEach(key => keys[key.Id] = true);
+        return Array.from(Object.keys(keys)).map(item =>
+            (<KeyToggle checked={keys[item]} key={item} keyId={item} toggle={this.toggleKey} />));
+    }
+
     get tableOptionsPanel() {
-        const allKeys = this.findAllDocumentKeys;
-        return !this.props.active() ? (null) : (<Flyout
-            anchorPoint={anchorPoints.LEFT_TOP}
-            content={<div>
-                <div id="schema-options-header"><h5><b>Options</b></h5></div>
-                <div id="options-flyout-div">
-                    <h6 className="schema-options-subHeader">Preview Window</h6>
-                    <div id="preview-schema-checkbox-div"><input type="checkbox" key={"Show Preview"} checked={this.splitPercentage !== 0} onChange={this.toggleExpander} />  Show Preview </div>
-                    <h6 className="schema-options-subHeader" >Displayed Columns</h6>
-                    <ul id="schema-col-checklist" >
-                        {Array.from(Object.keys(allKeys)).map(item =>
-                            (<KeyToggle checked={allKeys[item]} key={item} keyId={item} toggle={this.toggleKey} />))}
-                    </ul>
-                    <input value={this.newKeyName} onChange={this.newKeyChange} />
-                    <button onClick={this.addColumn}><FontAwesomeIcon style={{ color: "white" }} icon="plus" size="lg" /></button>
+        return !this.props.active() ? (null) :
+            (<Flyout
+                anchorPoint={anchorPoints.LEFT_TOP}
+                content={<div>
+                    <div id="schema-options-header"><h5><b>Options</b></h5></div>
+                    <div id="options-flyout-div">
+                        <h6 className="schema-options-subHeader">Preview Window</h6>
+                        <div id="preview-schema-checkbox-div"><input type="checkbox" key={"Show Preview"} checked={this.splitPercentage !== 0} onChange={this.toggleExpander} />  Show Preview </div>
+                        <h6 className="schema-options-subHeader" >Displayed Columns</h6>
+                        <ul id="schema-col-checklist" >
+                            {this.documentKeysCheckList}
+                        </ul>
+                        <input value={this._newKeyName} onChange={this.newKeyChange} />
+                        <button onClick={this.addColumn}><FontAwesomeIcon style={{ color: "white" }} icon="plus" size="lg" /></button>
+                    </div>
                 </div>
-            </div>
-            }>
-            <button id="schemaOptionsMenuBtn" onPointerDown={this.OptionsMenuDown}><FontAwesomeIcon style={{ color: "white" }} icon="cog" size="sm" /></button>
-        </Flyout>);
+                }>
+                <button id="schemaOptionsMenuBtn" ><FontAwesomeIcon style={{ color: "white" }} icon="cog" size="sm" /></button>
+            </Flyout>);
     }
 
     @computed
@@ -345,11 +324,6 @@ export class CollectionSchemaView extends CollectionSubView {
             <div className="collectionSchemaView-dividerDragger" onPointerDown={this.onDividerDown} style={{ width: `${this.DIVIDER_WIDTH}px` }} />;
     }
 
-    createTarget = (ele: HTMLDivElement) => {
-        this._mainCont = ele;
-        super.CreateDropTarget(ele);
-    }
-
     render() {
         library.add(faCog);
         library.add(faPlus);
-- 
cgit v1.2.3-70-g09d2


From 23f4ce6107d64e4be8b05f528fc210ad6e85d174 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Thu, 18 Apr 2019 10:03:02 -0400
Subject: more minor schema view fixes.

---
 src/client/views/collections/CollectionSchemaView.scss |  3 ---
 src/client/views/collections/CollectionSchemaView.tsx  | 13 +++++--------
 src/client/views/globalCssVariables.scss.d.ts          |  2 +-
 3 files changed, 6 insertions(+), 12 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index bced0d5d4..6eabbe17c 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -153,9 +153,6 @@
     }
     .documentView-node:first-child {
         background: $light-color;
-        .imageBox-cont img {
-            object-fit: contain;
-        }
     }
 }
 //options menu styling
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 08c9740d0..b61eb342d 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -239,9 +239,9 @@ export class CollectionSchemaView extends CollectionSubView {
         const selected = children.length > this._selectedIndex ? children[this._selectedIndex] : undefined;
         return selected ? (this.previewScript ? selected.Get(new Key(this.previewScript)) as Document : selected) : undefined;
     }
-    get tableWidth() { return this.props.PanelWidth() * (1 - this.splitPercentage / 100); }
-    get previewRegionHeight() { return this.props.PanelHeight(); }
-    get previewRegionWidth() { return this.props.PanelWidth() * this.splitPercentage / 100 - this.DIVIDER_WIDTH; }
+    get tableWidth() { return (this.props.PanelWidth() - 2 * this.borderWidth - this.DIVIDER_WIDTH) * (1 - this.splitPercentage / 100); }
+    get previewRegionHeight() { return this.props.PanelHeight() - 2 * this.borderWidth; }
+    get previewRegionWidth() { return (this.props.PanelWidth() - 2 * this.borderWidth - this.DIVIDER_WIDTH) * this.splitPercentage / 100; }
 
     private previewDocNativeWidth = () => this.previewDocument!.GetNumber(KeyStore.NativeWidth, this.previewRegionWidth);
     private previewDocNativeHeight = () => this.previewDocument!.GetNumber(KeyStore.NativeHeight, this.previewRegionHeight);
@@ -262,7 +262,7 @@ export class CollectionSchemaView extends CollectionSubView {
     get previewPanel() {
         // let doc = CompileScript(this.previewScript, { this: selected }, true)();
         return !this.previewDocument ? (null) : (
-            <div className="collectionSchemaView-previewRegion" style={{ width: `calc(${this.props.Document.GetNumber(KeyStore.SchemaSplitPercentage, 0)}% - ${this.DIVIDER_WIDTH}px)` }}>
+            <div className="collectionSchemaView-previewRegion" style={{ width: `${this.previewRegionWidth}px` }}>
                 <div className="collectionSchemaView-previewDoc" style={{ transform: `translate(${this.previewPanelCenteringOffset}px, 0px)` }}>
                     <DocumentView Document={this.previewDocument} isTopMost={false} selectOnLoad={false}
                         addDocument={this.props.addDocument} removeDocument={this.props.removeDocument}
@@ -327,14 +327,11 @@ export class CollectionSchemaView extends CollectionSubView {
     render() {
         library.add(faCog);
         library.add(faPlus);
-        if (!this.previewDocument)
-            return (null);
-
         const children = this.props.Document.GetList(this.props.fieldKey, [] as Document[]);
         return (
             <div className="collectionSchemaView-container" onPointerDown={this.onPointerDown} onWheel={this.onWheel}
                 onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createTarget}>
-                <div className="collectionSchemaView-tableContainer" style={{ width: `calc(100% - ${this.splitPercentage}%)` }}>
+                <div className="collectionSchemaView-tableContainer" style={{ width: `${this.tableWidth}px` }}>
                     <ReactTable data={children} page={0} pageSize={children.length} showPagination={false}
                         columns={this.columns.map(col => ({
                             Header: col.Name,
diff --git a/src/client/views/globalCssVariables.scss.d.ts b/src/client/views/globalCssVariables.scss.d.ts
index e874b815d..ed8573f41 100644
--- a/src/client/views/globalCssVariables.scss.d.ts
+++ b/src/client/views/globalCssVariables.scss.d.ts
@@ -1,7 +1,7 @@
 
 interface IGlobalScss {
     contextMenuZindex: string;  // context menu shows up over everything
-    COLLECTION_BORDER_WIDTH: number;
+    COLLECTION_BORDER_WIDTH: string;
 }
 declare const globalCssVariables: IGlobalScss;
 
-- 
cgit v1.2.3-70-g09d2


From af6feb64510490da8d815f41ceb639d693b9eae3 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 19 Apr 2019 16:34:32 -0400
Subject: played with iconifying things in a different way.  fixed some things
 with schemas.

---
 src/Utils.ts                                       |  2 +-
 src/client/documents/Documents.ts                  | 16 ++++
 src/client/northstar/dash-nodes/HistogramBox.scss  |  6 +-
 src/client/northstar/dash-nodes/HistogramBox.tsx   |  2 +-
 src/client/views/DocumentDecorations.tsx           | 42 ++++++----
 src/client/views/Main.tsx                          |  8 +-
 .../views/collections/CollectionSchemaView.scss    |  9 ++-
 .../views/collections/CollectionSchemaView.tsx     |  5 +-
 .../CollectionFreeFormLinkView.tsx                 |  8 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 13 ++--
 .../collections/collectionFreeForm/MarqueeView.tsx |  9 +--
 src/client/views/globalCssVariables.scss           |  2 +
 src/client/views/globalCssVariables.scss.d.ts      |  1 +
 .../views/nodes/CollectionFreeFormDocumentView.tsx | 26 +++----
 src/client/views/nodes/DocumentContentsView.tsx    |  3 +-
 src/client/views/nodes/DocumentView.scss           | 16 +---
 src/client/views/nodes/DocumentView.tsx            | 71 ++++++++---------
 src/client/views/nodes/FieldView.tsx               |  5 ++
 src/client/views/nodes/IconBox.scss                | 12 +++
 src/client/views/nodes/IconBox.tsx                 | 90 ++++++++++++++++++++++
 src/fields/IconFIeld.ts                            | 25 ++++++
 src/fields/KeyStore.ts                             | 10 +--
 src/server/Message.ts                              |  2 +-
 src/server/ServerUtil.ts                           |  2 +
 24 files changed, 264 insertions(+), 121 deletions(-)
 create mode 100644 src/client/views/nodes/IconBox.scss
 create mode 100644 src/client/views/nodes/IconBox.tsx
 create mode 100644 src/fields/IconFIeld.ts

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

diff --git a/src/Utils.ts b/src/Utils.ts
index dec6245ef..98f75d3b9 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -1,7 +1,7 @@
 import v4 = require('uuid/v4');
 import v5 = require("uuid/v5");
 import { Socket } from 'socket.io';
-import { Message, Types, Transferable } from './server/Message';
+import { Message } from './server/Message';
 import { Document } from './fields/Document';
 
 export class Utils {
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 4febfa7eb..b0bb74d89 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -32,6 +32,9 @@ import { action } from "mobx";
 import { ColumnAttributeModel } from "../northstar/core/attribute/AttributeModel";
 import { AttributeTransformationModel } from "../northstar/core/attribute/AttributeTransformationModel";
 import { AggregateFunction } from "../northstar/model/idea/idea";
+import { MINIMIZED_ICON_SIZE } from "../views/globalCssVariables.scss";
+import { IconBox } from "../views/nodes/IconBox";
+import { IconField } from "../../fields/IconFIeld";
 
 export interface DocumentOptions {
     x?: number;
@@ -63,6 +66,7 @@ export namespace Documents {
     let videoProto: Document;
     let audioProto: Document;
     let pdfProto: Document;
+    let iconProto: Document;
     const textProtoId = "textProto";
     const histoProtoId = "histoProto";
     const pdfProtoId = "pdfProto";
@@ -72,6 +76,7 @@ export namespace Documents {
     const kvpProtoId = "kvpProto";
     const videoProtoId = "videoProto";
     const audioProtoId = "audioProto";
+    const iconProtoId = "iconProto";
 
     export function initProtos(): Promise<void> {
         return Server.GetFields([textProtoId, histoProtoId, collProtoId, pdfProtoId, imageProtoId, videoProtoId, audioProtoId, webProtoId, kvpProtoId]).then(fields => {
@@ -84,6 +89,7 @@ export namespace Documents {
             videoProto = fields[videoProtoId] as Document || CreateVideoPrototype();
             audioProto = fields[audioProtoId] as Document || CreateAudioPrototype();
             pdfProto = fields[pdfProtoId] as Document || CreatePdfPrototype();
+            iconProto = fields[iconProtoId] as Document || CreateIconPrototype();
         });
     }
     function assignOptions(doc: Document, options: DocumentOptions): Document {
@@ -92,6 +98,8 @@ export namespace Documents {
         if (options.title !== undefined) { doc.SetText(KeyStore.Title, options.title); }
         if (options.page !== undefined) { doc.SetNumber(KeyStore.Page, options.page); }
         if (options.scale !== undefined) { doc.SetNumber(KeyStore.Scale, options.scale); }
+        if (options.width !== undefined) { doc.SetNumber(KeyStore.Width, options.width); }
+        if (options.height !== undefined) { doc.SetNumber(KeyStore.Height, options.height); }
         if (options.viewType !== undefined) { doc.SetNumber(KeyStore.ViewType, options.viewType); }
         if (options.backgroundColor !== undefined) { doc.SetText(KeyStore.BackgroundColor, options.backgroundColor); }
         if (options.ink !== undefined) { doc.Set(KeyStore.Ink, new InkField(options.ink)); }
@@ -139,6 +147,11 @@ export namespace Documents {
         histoProto.SetText(KeyStore.BackgroundLayout, HistogramBox.LayoutString());
         return histoProto;
     }
+    function CreateIconPrototype(): Document {
+        let iconProto = setupPrototypeOptions(iconProtoId, "ICON_PROTO", IconBox.LayoutString(),
+            { x: 0, y: 0, width: Number(MINIMIZED_ICON_SIZE), height: Number(MINIMIZED_ICON_SIZE), layoutKeys: [KeyStore.Data] });
+        return iconProto;
+    }
     function CreateTextPrototype(): Document {
         let textProto = setupPrototypeOptions(textProtoId, "TEXT_PROTO", FormattedTextBox.LayoutString(),
             { x: 0, y: 0, width: 300, height: 150, layoutKeys: [KeyStore.Data] });
@@ -203,6 +216,9 @@ export namespace Documents {
     export function TextDocument(options: DocumentOptions = {}) {
         return assignToDelegate(SetInstanceOptions(textProto, options, ["", TextField]).MakeDelegate(), options);
     }
+    export function IconDocument(icon: string, options: DocumentOptions = {}) {
+        return assignToDelegate(SetInstanceOptions(iconProto, { width: Number(MINIMIZED_ICON_SIZE), height: Number(MINIMIZED_ICON_SIZE), layoutKeys: [KeyStore.Data], layout: IconBox.LayoutString(), ...options }, [icon, IconField]), options);
+    }
     export function PdfDocument(url: string, options: DocumentOptions = {}) {
         return assignToDelegate(SetInstanceOptions(pdfProto, options, [new URL(url), PDFField]).MakeDelegate(), options);
     }
diff --git a/src/client/northstar/dash-nodes/HistogramBox.scss b/src/client/northstar/dash-nodes/HistogramBox.scss
index e899cf15e..06d781263 100644
--- a/src/client/northstar/dash-nodes/HistogramBox.scss
+++ b/src/client/northstar/dash-nodes/HistogramBox.scss
@@ -1,12 +1,12 @@
 .histogrambox-container {
     padding: 0vw;
     position: absolute;
-    top: 0;
-    left:0;
+    top: -50%;
+    left:-50%;
     text-align: center;
     width: 100%;
     height: 100%;
-    background: black;
+    background: black; 
   }
   .histogrambox-xaxislabel {
     position:absolute;
diff --git a/src/client/northstar/dash-nodes/HistogramBox.tsx b/src/client/northstar/dash-nodes/HistogramBox.tsx
index 0e84ace50..e2ecc8c83 100644
--- a/src/client/northstar/dash-nodes/HistogramBox.tsx
+++ b/src/client/northstar/dash-nodes/HistogramBox.tsx
@@ -146,7 +146,7 @@ export class HistogramBox extends React.Component<FieldViewProps> {
         return (
             <Measure onResize={(r: any) => runInAction(() => { this.PanelWidth = r.entry.width; this.PanelHeight = r.entry.height; })}>
                 {({ measureRef }) =>
-                    <div className="histogrambox-container" ref={measureRef} style={{ transform: `translate(-50%, -50%)` }}>
+                    <div className="histogrambox-container" ref={measureRef}>
                         <div className="histogrambox-yaxislabel" onPointerDown={this.yLabelPointerDown} ref={this._dropYRef} >
                             <span className="histogrambox-yaxislabel-text">
                                 {labelY}
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index cfb9befd5..da2c7a3be 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -5,17 +5,18 @@ import { KeyStore } from "../../fields/KeyStore";
 import { ListField } from "../../fields/ListField";
 import { NumberField } from "../../fields/NumberField";
 import { TextField } from "../../fields/TextField";
+import { Document } from "../../fields/Document";
 import { emptyFunction } from "../../Utils";
 import { DragLinksAsDocuments, DragManager } from "../util/DragManager";
 import { SelectionManager } from "../util/SelectionManager";
 import { undoBatch } from "../util/UndoManager";
 import './DocumentDecorations.scss';
 import { MainOverlayTextBox } from "./MainOverlayTextBox";
-import { MINIMIZED_ICON_SIZE } from "../views/globalCssVariables.scss";
 import { DocumentView } from "./nodes/DocumentView";
 import { LinkMenu } from "./nodes/LinkMenu";
 import React = require("react");
 import { CompileScript } from "../util/Scripting";
+import { IconBox } from "./nodes/IconBox";
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -191,6 +192,9 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             document.addEventListener("pointerup", this.onMinimizeUp);
         }
     }
+
+    @observable _minimizedX = 0;
+    @observable _minimizedY = 0;
     @action
     onMinimizeMove = (e: PointerEvent): void => {
         e.stopPropagation();
@@ -201,12 +205,20 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             let xf = SelectionManager.SelectedDocuments()[0].props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
             let dx = e.pageX - xf[0];
             let dy = e.pageY - xf[1];
-            if (Math.abs(dx) < 20 && Math.abs(dy) < 20)
-                dx = dy = 0;
+            this._minimizedX = e.clientX;
+            this._minimizedY = e.clientY;
+            if (Math.abs(dx) < 20 && Math.abs(dy) < 20) {
+                this._minimizedX = xf[0];
+                this._minimizedY = xf[1];
+            }
             SelectionManager.SelectedDocuments().map(dv => {
-                let where = (dv.props.ScreenToLocalTransform()).scale(dv.props.ContentScaling()).transformDirection(dx, dy);
-                dv.props.Document.SetNumber(KeyStore.MinimizedX, where[0]);
-                dv.props.Document.SetNumber(KeyStore.MinimizedY, where[1]);
+                let minDoc = dv.props.Document.Get(KeyStore.MinimizedDoc);
+                if (minDoc instanceof Document) {
+                    let where = (dv.props.ScreenToLocalTransform()).scale(dv.props.ContentScaling()).transformPoint(this._minimizedX, this._minimizedY);
+                    let minDocument = minDoc as Document;
+                    minDocument.SetNumber(KeyStore.X, where[0] + dv.props.Document.GetNumber(KeyStore.X, 0));
+                    minDocument.SetNumber(KeyStore.Y, where[1] + dv.props.Document.GetNumber(KeyStore.Y, 0));
+                }
             });
         }
     }
@@ -219,6 +231,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             if (Math.abs(dx) < 4 && Math.abs(dy) < 4 && !this._iconifying) {
                 SelectionManager.SelectedDocuments().map(dv => dv.minimize());
                 SelectionManager.DeselectAll();
+            } else {
+                this._minimizedX = this._minimizedY = 0;
             }
             document.removeEventListener("pointermove", this.onMinimizeMove);
             document.removeEventListener("pointerup", this.onMinimizeUp);
@@ -404,24 +418,18 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         if (bounds.x === Number.MAX_VALUE || !seldoc) {
             return (null);
         }
-        let minvec = [seldoc.props.Document.GetNumber(KeyStore.MinimizedX, 0), seldoc.props.Document.GetNumber(KeyStore.MinimizedY, 0)];
-        minvec = seldoc.props.ScreenToLocalTransform().scale(seldoc.props.ContentScaling()).inverse().transformDirection(minvec[0], minvec[1]);
-        let selpos = minvec[0] !== 0 || minvec[1] !== 0 ?
-            [minvec[0] - 12 + (!this._iconifying ? 8 : 0), minvec[1] - 12 + (!this._iconifying ? 28 : 0)] :
+        let selpos = this._minimizedX !== 0 || this._minimizedY !== 0 ?
+            [this._minimizedX - 12 + (!this._iconifying ? 8 : 0), this._minimizedY - 12 + (!this._iconifying ? 28 : 0)] :
             [0, this._iconifying ? -18 : 0];
         let minimizeIcon = (
             <div className="documentDecorations-minimizeButton" onPointerDown={this.onMinimizeDown}
                 style={{ transform: `translate(${selpos[0]}px,${selpos[1]}px)`, }}>
-                {SelectionManager.SelectedDocuments().length == 1 ? SelectionManager.SelectedDocuments()[0].minimizedIcon : "..."}
+                {SelectionManager.SelectedDocuments().length == 1 ? IconBox.DocumentIcon(SelectionManager.SelectedDocuments()[0].props.Document.GetText(KeyStore.Layout, "...")) : "..."}
             </div>);
         if (this._iconifying) {
-            let xfpt = seldoc.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
-            return (<div className="documentDecorations-container" style={{ transform: `translate(${xfpt[0]}px,${xfpt[1]}px` }}>
-                {minimizeIcon}
-            </div>);
+            return (<div className="documentDecorations-container" > {minimizeIcon} </div>);
         }
-        // console.log(this._documents.length)
-        // let test = this._documents[0].props.Document.Title;
+
         if (this.Hidden) {
             return (null);
         }
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 503a11b35..09ef30f6b 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -85,11 +85,11 @@ export class Main extends React.Component {
         this.initEventListeners();
         this.initAuthenticationRouters();
 
-        // try {
-        //     this.initializeNorthstar();
-        // } catch (e) {
+        try {
+            this.initializeNorthstar();
+        } catch (e) {
 
-        // }
+        }
     }
 
     componentDidMount() { window.onpopstate = this.onHistory; }
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 6eabbe17c..cfdb3ab22 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -1,6 +1,7 @@
 @import "../globalCssVariables";
 
 
+
 .collectionSchemaView-container {
     border-width: $COLLECTION_BORDER_WIDTH;
     border-color : $intermediate-color;
@@ -10,6 +11,10 @@
     position: absolute;
     width: 100%;
     height: 100%;
+
+    .collectionSchemaView-cellContents {
+        height: $MAX_ROW_HEIGHT;
+    }
     
     .collectionSchemaView-previewRegion {
         position: relative;
@@ -104,7 +109,7 @@
         }
         .rt-tr-group {
             direction: ltr;
-            max-height: 44px;
+            max-height: $MAX_ROW_HEIGHT;
         }
         .rt-td {
             border-width: 1px;
@@ -136,7 +141,7 @@
     }
     .ReactTable .rt-th,
     .ReactTable .rt-td {
-        max-height: 44;
+        max-height: $MAX_ROW_HEIGHT;
         padding: 3px 7px;
         font-size: 13px;
         text-align: center;
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index b61eb342d..90077b053 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -5,6 +5,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, computed, observable, untracked } from "mobx";
 import { observer } from "mobx-react";
 import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table";
+import { MAX_ROW_HEIGHT } from '../../views/globalCssVariables.scss'
 import "react-table/react-table.css";
 import { Document } from "../../../fields/Document";
 import { Field, Opt } from "../../../fields/Field";
@@ -99,11 +100,11 @@ export class CollectionSchemaView extends CollectionSubView {
             return false;
         };
         return (
-            <div className="collectionSchemaView-cellContents" onPointerDown={onItemDown} style={{ height: "56px" }} key={props.Document.Id} ref={reference}>
+            <div className="collectionSchemaView-cellContents" onPointerDown={onItemDown} key={props.Document.Id} ref={reference}>
                 <EditableView
                     display={"inline"}
                     contents={contents}
-                    height={56}
+                    height={Number(MAX_ROW_HEIGHT)}
                     GetValue={() => {
                         let field = props.Document.Get(props.fieldKey);
                         if (field && field instanceof Field) {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
index 8868f7df0..20c5a84bf 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
@@ -23,10 +23,10 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
         let l = this.props.LinkDocs;
         let a = this.props.A;
         let b = this.props.B;
-        let x1 = a.GetNumber(KeyStore.X, 0) + (a.GetBoolean(KeyStore.Minimized, false) ? 5 : a.Width() / 2);
-        let y1 = a.GetNumber(KeyStore.Y, 0) + (a.GetBoolean(KeyStore.Minimized, false) ? 5 : a.Height() / 2);
-        let x2 = b.GetNumber(KeyStore.X, 0) + (b.GetBoolean(KeyStore.Minimized, false) ? 5 : b.Width() / 2);
-        let y2 = b.GetNumber(KeyStore.Y, 0) + (b.GetBoolean(KeyStore.Minimized, false) ? 5 : b.Height() / 2);
+        let x1 = a.GetNumber(KeyStore.X, 0) + (a.GetBoolean(KeyStore.IsMinimized, false) ? 5 : a.Width() / 2);
+        let y1 = a.GetNumber(KeyStore.Y, 0) + (a.GetBoolean(KeyStore.IsMinimized, false) ? 5 : a.Height() / 2);
+        let x2 = b.GetNumber(KeyStore.X, 0) + (b.GetBoolean(KeyStore.IsMinimized, false) ? 5 : b.Width() / 2);
+        let y2 = b.GetNumber(KeyStore.Y, 0) + (b.GetBoolean(KeyStore.IsMinimized, false) ? 5 : b.Height() / 2);
         return (
             <line key={Utils.GenerateGuid()} className="collectionfreeformlinkview-linkLine" onPointerDown={this.onPointerDown}
                 style={{ strokeWidth: `${l.length * 5}` }}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index c50597655..945c01059 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -21,6 +21,7 @@ import "./CollectionFreeFormView.scss";
 import { MarqueeView } from "./MarqueeView";
 import React = require("react");
 import v5 = require("uuid/v5");
+import { BooleanField } from "../../../../fields/BooleanField";
 
 @observer
 export class CollectionFreeFormView extends CollectionSubView {
@@ -71,17 +72,15 @@ export class CollectionFreeFormView extends CollectionSubView {
     @action
     drop = (e: Event, de: DragManager.DropEvent) => {
         if (super.drop(e, de) && de.data instanceof DragManager.DocumentDragData) {
-            console.log("DROP Aat " + de.x + " off " + de.data.xOffset);
             const [x, y] = this.getTransform().transformPoint(de.x - de.data.xOffset, de.y - de.data.yOffset);
             if (de.data.droppedDocuments.length) {
                 let dragDoc = de.data.droppedDocuments[0];
                 let dropX = dragDoc.GetNumber(KeyStore.X, 0);
                 let dropY = dragDoc.GetNumber(KeyStore.Y, 0);
                 de.data.droppedDocuments.map(d => {
-                    let minimized = d.GetBoolean(KeyStore.Minimized, false);
-                    d.SetNumber(KeyStore.X, x + (d.GetNumber(KeyStore.X, 0) - (minimized ? d.GetNumber(KeyStore.MinimizedX, 0) : 0)) - dropX);
-                    d.SetNumber(KeyStore.Y, y + (d.GetNumber(KeyStore.Y, 0) - (minimized ? d.GetNumber(KeyStore.MinimizedY, 0) : 0)) - dropY);
-                    if (!minimized) {
+                    d.SetNumber(KeyStore.X, x + (d.GetNumber(KeyStore.X, 0)) - dropX);
+                    d.SetNumber(KeyStore.Y, y + (d.GetNumber(KeyStore.Y, 0)) - dropY);
+                    if (!d.GetBoolean(KeyStore.IsMinimized, false)) {
                         if (!d.GetNumber(KeyStore.Width, 0)) {
                             d.SetNumber(KeyStore.Width, 300);
                         }
@@ -264,7 +263,9 @@ export class CollectionFreeFormView extends CollectionSubView {
         let docviews = this.props.Document.GetList(this.props.fieldKey, [] as Document[]).filter(doc => doc).reduce((prev, doc) => {
             var page = doc.GetNumber(KeyStore.Page, -1);
             if (page === curPage || page === -1) {
-                prev.push(<CollectionFreeFormDocumentView key={doc.Id} {...this.getDocumentViewProps(doc)} />);
+                let minim = doc.GetT(KeyStore.IsMinimized, BooleanField);
+                if (minim === undefined || (minim && !minim.Data))
+                    prev.push(<CollectionFreeFormDocumentView key={doc.Id} {...this.getDocumentViewProps(doc)} />);
             }
             return prev;
         }, [] as JSX.Element[]);
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 8b94374fa..bf918beba 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -208,12 +208,11 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
         let selRect = this.Bounds;
         let selection: Document[] = [];
         this.props.activeDocuments().map(doc => {
-            let minimized = doc.GetBoolean(KeyStore.Minimized, false);
             var z = doc.GetNumber(KeyStore.Zoom, 1);
-            var x = doc.GetNumber(KeyStore.X, 0) + (minimized ? doc.GetNumber(KeyStore.MinimizedX, 0) : 0);
-            var y = doc.GetNumber(KeyStore.Y, 0) + (minimized ? doc.GetNumber(KeyStore.MinimizedY, 0) : 0);
-            var w = minimized ? MINIMIZED_ICON_SIZE : doc.Width() / z;
-            var h = minimized ? MINIMIZED_ICON_SIZE : doc.Height() / z;
+            var x = doc.GetNumber(KeyStore.X, 0);
+            var y = doc.GetNumber(KeyStore.Y, 0);
+            var w = doc.Width() / z;
+            var h = doc.Height() / z;
             if (this.intersectRect({ left: x, top: y, width: w, height: h }, selRect)) {
                 selection.push(doc);
             }
diff --git a/src/client/views/globalCssVariables.scss b/src/client/views/globalCssVariables.scss
index f154f8158..4f68b71b0 100644
--- a/src/client/views/globalCssVariables.scss
+++ b/src/client/views/globalCssVariables.scss
@@ -24,8 +24,10 @@ $docDecorations-zindex: 998; // then doc decorations appear over everything else
 $remoteCursors-zindex: 997; // ... not sure what level the remote cursors should go -- is this right?
 $COLLECTION_BORDER_WIDTH: 1;
 $MINIMIZED_ICON_SIZE:25;
+$MAX_ROW_HEIGHT: 44px;
 :export  {
     contextMenuZindex: $contextMenu-zindex;
     COLLECTION_BORDER_WIDTH: $COLLECTION_BORDER_WIDTH;
     MINIMIZED_ICON_SIZE: $MINIMIZED_ICON_SIZE;
+    MAX_ROW_HEIGHT: $MAX_ROW_HEIGHT;
 }
\ No newline at end of file
diff --git a/src/client/views/globalCssVariables.scss.d.ts b/src/client/views/globalCssVariables.scss.d.ts
index cc77d987a..9788d31f7 100644
--- a/src/client/views/globalCssVariables.scss.d.ts
+++ b/src/client/views/globalCssVariables.scss.d.ts
@@ -3,6 +3,7 @@ interface IGlobalScss {
     contextMenuZindex: string;  // context menu shows up over everything
     COLLECTION_BORDER_WIDTH: string;
     MINIMIZED_ICON_SIZE: string;
+    MAX_ROW_HEIGHT: string;
 }
 declare const globalCssVariables: IGlobalScss;
 
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index a3689414d..1d42b3899 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -46,10 +46,10 @@ export class CollectionFreeFormDocumentView extends React.Component<CollectionFr
     }
 
     get X() {
-        return this.props.Document.GetNumber(KeyStore.X, 0) + (this.isMinimized ? this.props.Document.GetNumber(KeyStore.MinimizedX, 0) : 0);
+        return this.props.Document.GetNumber(KeyStore.X, 0);
     }
     get Y() {
-        return this.props.Document.GetNumber(KeyStore.Y, 0) + (this.isMinimized ? this.props.Document.GetNumber(KeyStore.MinimizedY, 0) : 0);
+        return this.props.Document.GetNumber(KeyStore.Y, 0);
     }
     getTransform = (): Transform =>
         this.props.ScreenToLocalTransform()
@@ -57,8 +57,8 @@ export class CollectionFreeFormDocumentView extends React.Component<CollectionFr
             .scale(1 / this.contentScaling()).scale(1 / this.zoom)
 
     contentScaling = () => this.nativeWidth > 0 ? this.width / this.nativeWidth : 1;
-    panelWidth = () => this.isMinimized ? 10 : this.props.PanelWidth();
-    panelHeight = () => this.isMinimized ? 10 : this.props.PanelHeight();
+    panelWidth = () => this.props.PanelWidth();
+    panelHeight = () => this.props.PanelHeight();
 
     @computed
     get docView() {
@@ -70,19 +70,17 @@ export class CollectionFreeFormDocumentView extends React.Component<CollectionFr
         />;
     }
 
-    get isMinimized() { return this.props.Document.GetBoolean(KeyStore.Minimized, false); }
-
     render() {
         let zoomFade = 1;
         //var zoom = doc.GetNumber(KeyStore.Zoom, 1);
-        let transform = this.getTransform().scale(this.contentScaling()).inverse();
-        var [sptX, sptY] = transform.transformPoint(0, 0);
-        let [bptX, bptY] = transform.transformPoint(this.props.PanelWidth(), this.props.PanelHeight());
-        let w = bptX - sptX;
-        //zoomFade = area < 100 || area > 800 ? Math.max(0, Math.min(1, 2 - 5 * (zoom < this.scale ? this.scale / zoom : zoom / this.scale))) : 1;
-        let fadeUp = .75 * 1800;
-        let fadeDown = .075 * 1800;
-        zoomFade = w < fadeDown  /* || w > fadeUp */ ? Math.max(0, Math.min(1, 2 - (w < fadeDown ? fadeDown / w : w / fadeUp))) : 1;
+        // let transform = this.getTransform().scale(this.contentScaling()).inverse();
+        // var [sptX, sptY] = transform.transformPoint(0, 0);
+        // let [bptX, bptY] = transform.transformPoint(this.props.PanelWidth(), this.props.PanelHeight());
+        // let w = bptX - sptX;
+        // //zoomFade = area < 100 || area > 800 ? Math.max(0, Math.min(1, 2 - 5 * (zoom < this.scale ? this.scale / zoom : zoom / this.scale))) : 1;
+        // let fadeUp = .75 * 1800;
+        // let fadeDown = .075 * 1800;
+        // zoomFade = w < fadeDown  /* || w > fadeUp */ ? Math.max(0, Math.min(1, 2 - (w < fadeDown ? fadeDown / w : w / fadeUp))) : 1;
 
         return (
             <div className="collectionFreeFormDocumentView-container" ref={this._mainCont} style={{
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 76f852601..07599c345 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -15,6 +15,7 @@ import { DocumentViewProps } from "./DocumentView";
 import "./DocumentView.scss";
 import { FormattedTextBox } from "./FormattedTextBox";
 import { ImageBox } from "./ImageBox";
+import { IconBox } from "./IconBox";
 import { KeyValueBox } from "./KeyValueBox";
 import { PDFBox } from "./PDFBox";
 import { VideoBox } from "./VideoBox";
@@ -62,7 +63,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
             return <p>Error loading layout keys</p>;
         }
         return <JsxParser
-            components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, CollectionVideoView, WebBox, KeyValueBox, PDFBox, VideoBox, AudioBox, HistogramBox }}
+            components={{ FormattedTextBox, ImageBox, IconBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, CollectionVideoView, WebBox, KeyValueBox, PDFBox, VideoBox, AudioBox, HistogramBox }}
             bindings={this.CreateBindings()}
             jsx={this.layout}
             showWarnings={true}
diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss
index a0e829d26..7c72fb6e6 100644
--- a/src/client/views/nodes/DocumentView.scss
+++ b/src/client/views/nodes/DocumentView.scss
@@ -4,7 +4,7 @@
   position: inherit;
   top: 0;
   left:0;
-  background: $light-color; //overflow: hidden;
+ // background: $light-color; //overflow: hidden;
   transform-origin: left top;
 
   &.minimized {
@@ -30,18 +30,4 @@
 }
 .documentView-node-topmost {
     background: white;
-}
-.minimized-box {
-    position: absolute;
-    left:0;
-    top:0;
-    width:$MINIMIZED_ICON_SIZE;
-    height:$MINIMIZED_ICON_SIZE;
-    transform:translate(-50%, -50%);
-}
-
-.minimized-box:hover {
-  background: $main-accent;
-  transform:translate(-50%, -50%) scale(1.15);;
-  cursor: pointer;
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 3ada3252c..558cbf017 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1,6 +1,3 @@
-import { IconProp, library } from '@fortawesome/fontawesome-svg-core';
-import { faCaretUp, faObjectGroup, faStickyNote, faFilePdf, faFilm, faImage } from '@fortawesome/free-solid-svg-icons';
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { action, computed, runInAction } from "mobx";
 import { observer } from "mobx-react";
 import { Document } from "../../../fields/Document";
@@ -20,18 +17,11 @@ import { CollectionDockingView } from "../collections/CollectionDockingView";
 import { CollectionPDFView } from "../collections/CollectionPDFView";
 import { CollectionVideoView } from "../collections/CollectionVideoView";
 import { CollectionView } from "../collections/CollectionView";
-import { MINIMIZED_ICON_SIZE } from "../../views/globalCssVariables.scss";
 import { ContextMenu } from "../ContextMenu";
 import { DocumentContentsView } from "./DocumentContentsView";
 import "./DocumentView.scss";
 import React = require("react");
-
-
-library.add(faCaretUp);
-library.add(faObjectGroup);
-library.add(faStickyNote);
-library.add(faFilePdf);
-library.add(faFilm);
+import { TextField } from "../../../fields/TextField";
 
 export interface DocumentViewProps {
     ContainingCollectionView: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
@@ -189,10 +179,10 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         document.removeEventListener("pointermove", this.onPointerMove);
         document.removeEventListener("pointerup", this.onPointerUp);
         e.stopPropagation();
-        if (!SelectionManager.IsSelected(this) && e.button !== 2 &&
-            Math.abs(e.clientX - this._downX) < 4 && Math.abs(e.clientY - this._downY) < 4) {
-            SelectionManager.SelectDoc(this, e.ctrlKey);
-        }
+        if (!SelectionManager.IsSelected(this) && e.button !== 2)
+            if (Math.abs(e.clientX - this._downX) < 4 && Math.abs(e.clientY - this._downY) < 4) {
+                SelectionManager.SelectDoc(this, e.ctrlKey);
+            }
     }
     stopPropagation = (e: React.SyntheticEvent) => {
         e.stopPropagation();
@@ -221,13 +211,33 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15);
     }
 
+    @action createIcon = (layoutString: string): void => {
+        let iconDoc = Documents.IconDocument(layoutString);
+        iconDoc.SetBoolean(KeyStore.IsMinimized, false);
+        iconDoc.SetNumber(KeyStore.NativeWidth, 0);
+        iconDoc.SetNumber(KeyStore.NativeHeight, 0);
+        iconDoc.Set(KeyStore.Prototype, this.props.Document);
+        iconDoc.Set(KeyStore.MaximizedDoc, this.props.Document);
+        this.props.Document.Set(KeyStore.MinimizedDoc, iconDoc);
+        this.props.addDocument && this.props.addDocument(iconDoc, false);
+    }
+
     @action
-    public minimize = (where: number[]): void => {
-        this.props.Document.SetBoolean(KeyStore.Minimized, true);
-        if (where[0] !== 0 || where[1] !== 0)
-            this.props.Document.SetNumber(KeyStore.MinimizedX, where[0]);
-        if (where[1] !== 0 || where[0] !== 0)
-            this.props.Document.SetNumber(KeyStore.MinimizedY, where[1]);
+    public minimize = (): void => {
+        this.props.Document.SetBoolean(KeyStore.IsMinimized, true);
+        this.props.Document.GetAsync(KeyStore.MinimizedDoc, mindoc => {
+            if (mindoc === undefined) {
+                this.props.Document.GetAsync(KeyStore.BackgroundLayout, field => {
+                    if (field instanceof TextField) this.createIcon(field.Data);
+                    else this.props.Document.GetAsync(KeyStore.Layout, field => {
+                        if (field instanceof TextField) this.createIcon(field.Data);
+                    });
+                });
+            }
+            else if (mindoc instanceof Document) {
+                this.props.addDocument && this.props.addDocument(mindoc, false);
+            }
+        });
     }
 
     @undoBatch
@@ -295,7 +305,6 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         }
         e.preventDefault();
 
-        !this.isMinimized() && ContextMenu.Instance.addItem({ description: "Minimize", event: () => this.minimize([0, 0]) });
         ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked });
         ContextMenu.Instance.addItem({ description: "Fields", event: this.fieldsClicked });
         ContextMenu.Instance.addItem({ description: "Center", event: () => this.props.focus(this.props.Document) });
@@ -309,9 +318,6 @@ export class DocumentView extends React.Component<DocumentViewProps> {
             SelectionManager.SelectDoc(this, false);
     }
 
-    @action
-    expand = (e: React.MouseEvent) => { this.props.Document.SetBoolean(KeyStore.Minimized, false); SelectionManager.SelectDoc(this, e.ctrlKey); }
-    isMinimized = () => this.props.Document.GetBoolean(KeyStore.Minimized, false);
     isSelected = () => SelectionManager.IsSelected(this);
     select = (ctrlPressed: boolean) => SelectionManager.SelectDoc(this, ctrlPressed);
 
@@ -319,27 +325,12 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     @computed get nativeHeight() { return this.props.Document.GetNumber(KeyStore.NativeHeight, 0); }
     @computed get contents() { return (<DocumentContentsView {...this.props} isSelected={this.isSelected} select={this.select} layoutKey={KeyStore.Layout} />); }
 
-    @computed get minimizedIcon() {
-        let button = this.layout.indexOf("PDFBox") !== -1 ? faFilePdf :
-            this.layout.indexOf("ImageBox") !== -1 ? faImage :
-                this.layout.indexOf("Formatted") !== -1 ? faStickyNote :
-                    this.layout.indexOf("Video") !== -1 ? faFilm :
-                        this.layout.indexOf("Collection") !== -1 ? faObjectGroup :
-                            faCaretUp;
-        return <FontAwesomeIcon icon={button} style={{ width: MINIMIZED_ICON_SIZE, height: MINIMIZED_ICON_SIZE }} className="documentView-minimizedIcon" />
-    }
 
     render() {
         var scaling = this.props.ContentScaling();
         var nativeHeight = this.nativeHeight > 0 ? this.nativeHeight.toString() + "px" : "100%";
         var nativeWidth = this.nativeWidth > 0 ? this.nativeWidth.toString() + "px" : "100%";
 
-        if (this.isMinimized()) {
-            return (
-                <div className="minimized-box" ref={this._mainCont} onClick={this.expand} onDrop={this.onDrop} onPointerDown={this.onPointerDown} >
-                    {this.minimizedIcon}
-                </div>);
-        }
         return (
             <div className={`documentView-node${this.props.isTopMost ? "-topmost" : ""}`}
                 ref={this._mainCont}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index e9f6950ff..93e385821 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -23,6 +23,8 @@ import { returnFalse, emptyDocFunction, emptyFunction, returnOne } from "../../.
 import { CollectionView } from "../collections/CollectionView";
 import { CollectionPDFView } from "../collections/CollectionPDFView";
 import { CollectionVideoView } from "../collections/CollectionVideoView";
+import { IconField } from "../../../fields/IconFIeld";
+import { IconBox } from "./IconBox";
 
 
 //
@@ -72,6 +74,9 @@ export class FieldView extends React.Component<FieldViewProps> {
         else if (field instanceof ImageField) {
             return <ImageBox {...this.props} />;
         }
+        else if (field instanceof IconField) {
+            return <IconBox {...this.props} />;
+        }
         else if (field instanceof VideoField) {
             return <VideoBox {...this.props} />;
         }
diff --git a/src/client/views/nodes/IconBox.scss b/src/client/views/nodes/IconBox.scss
new file mode 100644
index 000000000..ce0ee2e09
--- /dev/null
+++ b/src/client/views/nodes/IconBox.scss
@@ -0,0 +1,12 @@
+
+@import "../globalCssVariables";
+.iconBox-container {
+    position: absolute;
+    left:0;
+    top:0;
+    svg {
+        width: 100% !important;
+        height: 100%;
+        background: white;
+    }
+}
\ No newline at end of file
diff --git a/src/client/views/nodes/IconBox.tsx b/src/client/views/nodes/IconBox.tsx
new file mode 100644
index 000000000..5ada2186d
--- /dev/null
+++ b/src/client/views/nodes/IconBox.tsx
@@ -0,0 +1,90 @@
+import React = require("react");
+import { library } from '@fortawesome/fontawesome-svg-core';
+import { faCaretUp, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { action, computed } from "mobx";
+import { observer } from "mobx-react";
+import { Document } from '../../../fields/Document';
+import { IconField } from "../../../fields/IconFIeld";
+import { KeyStore } from "../../../fields/KeyStore";
+import { SelectionManager } from "../../util/SelectionManager";
+import { FieldView, FieldViewProps } from './FieldView';
+import "./IconBox.scss";
+
+
+library.add(faCaretUp);
+library.add(faObjectGroup);
+library.add(faStickyNote);
+library.add(faFilePdf);
+library.add(faFilm);
+
+@observer
+export class IconBox extends React.Component<FieldViewProps> {
+    public static LayoutString() { return FieldView.LayoutString(IconBox); }
+
+    @computed get maximized() { return this.props.Document.GetT(KeyStore.MaximizedDoc, Document); }
+    @computed get layout(): string { return this.props.Document.GetData(this.props.fieldKey, IconField, "<p>Error loading layout data</p>" as string); }
+    @computed get minimizedIcon() { return IconBox.DocumentIcon(this.layout); }
+
+    public static DocumentIcon(layout: string) {
+        let button = layout.indexOf("PDFBox") !== -1 ? faFilePdf :
+            layout.indexOf("ImageBox") !== -1 ? faImage :
+                layout.indexOf("Formatted") !== -1 ? faStickyNote :
+                    layout.indexOf("Video") !== -1 ? faFilm :
+                        layout.indexOf("Collection") !== -1 ? faObjectGroup :
+                            faCaretUp;
+        return <FontAwesomeIcon icon={button} className="documentView-minimizedIcon" />
+    }
+
+    animateTransition(icon: number[], targ: number[], width: number, height: number, stime: number, target: Document, maximizing: boolean) {
+        setTimeout(() => {
+            let now = Date.now();
+            let progress = Math.min(1, (now - stime) / 200);
+            let pval = maximizing ?
+                [icon[0] + (targ[0] - icon[0]) * progress, icon[1] + (targ[1] - icon[1]) * progress] :
+                [targ[0] + (icon[0] - targ[0]) * progress, targ[1] + (icon[1] - targ[1]) * progress];
+            target.SetNumber(KeyStore.Width, maximizing ? 25 + (width - 25) * progress : width + (25 - width) * progress);
+            target.SetNumber(KeyStore.Height, maximizing ? 25 + (height - 25) * progress : height + (25 - height) * progress);
+            target.SetNumber(KeyStore.X, pval[0]);
+            target.SetNumber(KeyStore.Y, pval[1]);
+            if (now < stime + 200) {
+                this.animateTransition(icon, targ, width, height, stime, target, maximizing);
+            }
+            else {
+                if (!maximizing) {
+                    target.SetBoolean(KeyStore.IsMinimized, true);
+                    target.SetNumber(KeyStore.X, targ[0]);
+                    target.SetNumber(KeyStore.Y, targ[1]);
+                    target.SetNumber(KeyStore.Width, width);
+                    target.SetNumber(KeyStore.Height, height);
+                }
+                this._completed = true;
+            }
+        },
+            2);
+    }
+
+    _completed = true;
+
+    @action
+    public toggleMinimize = (): void => {
+        SelectionManager.DeselectAll();
+        if (this.maximized instanceof Document && this._completed) {
+            this._completed = false;
+            let minimized = this.maximized.GetBoolean(KeyStore.IsMinimized, false);
+            this.maximized.SetBoolean(KeyStore.IsMinimized, false);
+            this.animateTransition(
+                [this.props.Document.GetNumber(KeyStore.X, 0), this.props.Document.GetNumber(KeyStore.Y, 0)],
+                [this.maximized.GetNumber(KeyStore.X, 0), this.maximized.GetNumber(KeyStore.Y, 0)],
+                this.maximized.GetNumber(KeyStore.Width, 0), this.maximized.GetNumber(KeyStore.Width, 0),
+                Date.now(), this.maximized, minimized);
+        }
+    }
+
+    render() {
+        return (
+            <div className="iconBox-container" onClick={this.toggleMinimize} >
+                {this.minimizedIcon}
+            </div>);
+    }
+}
\ No newline at end of file
diff --git a/src/fields/IconFIeld.ts b/src/fields/IconFIeld.ts
new file mode 100644
index 000000000..a6694cc49
--- /dev/null
+++ b/src/fields/IconFIeld.ts
@@ -0,0 +1,25 @@
+import { BasicField } from "./BasicField";
+import { FieldId } from "./Field";
+import { Types } from "../server/Message";
+
+export class IconField extends BasicField<string> {
+    constructor(data: string = "", id?: FieldId, save: boolean = true) {
+        super(data, save, id);
+    }
+
+    ToScriptString(): string {
+        return `new IconField("${this.Data}")`;
+    }
+
+    Copy() {
+        return new IconField(this.Data);
+    }
+
+    ToJson() {
+        return {
+            type: Types.Icon,
+            data: this.Data,
+            id: this.Id
+        };
+    }
+}
\ No newline at end of file
diff --git a/src/fields/KeyStore.ts b/src/fields/KeyStore.ts
index ff2f31003..a347f8bcf 100644
--- a/src/fields/KeyStore.ts
+++ b/src/fields/KeyStore.ts
@@ -4,8 +4,6 @@ export namespace KeyStore {
     export const Prototype = new Key("Prototype");
     export const X = new Key("X");
     export const Y = new Key("Y");
-    export const MinimizedX = new Key("MinimizedX");
-    export const MinimizedY = new Key("MinimizedY");
     export const Page = new Key("Page");
     export const Title = new Key("Title");
     export const Author = new Key("Author");
@@ -47,14 +45,16 @@ export namespace KeyStore {
     export const OptionalRightCollection = new Key("OptionalRightCollection");
     export const Archives = new Key("Archives");
     export const Workspaces = new Key("Workspaces");
-    export const Minimized = new Key("Minimized");
+    export const IsMinimized = new Key("IsMinimized");
+    export const MinimizedDoc = new Key("MinimizedDoc");
+    export const MaximizedDoc = new Key("MaximizedDoc");
     export const CopyDraggedItems = new Key("CopyDraggedItems");
 
-    export const KeyList: Key[] = [Prototype, X, Y, MinimizedX, MinimizedY, Page, Title, Author, PanX, PanY, Scale, NativeWidth, NativeHeight,
+    export const KeyList: Key[] = [Prototype, X, Y, Page, Title, Author, PanX, PanY, Scale, NativeWidth, NativeHeight,
         Width, Height, ZIndex, Zoom, Data, Annotations, ViewType, Layout, BackgroundColor, BackgroundLayout, OverlayLayout, LayoutKeys,
         LayoutFields, ColumnsKey, SchemaSplitPercentage, Caption, ActiveWorkspace, DocumentText, BrushingDocs, LinkedToDocs, LinkedFromDocs,
         LinkDescription, LinkTags, Thumbnail, ThumbnailPage, CurPage, AnnotationOn, NumPages, Ink, Cursors, OptionalRightCollection,
-        Archives, Workspaces, Minimized, CopyDraggedItems
+        Archives, Workspaces, IsMinimized, MinimizedDoc, MaximizedDoc, CopyDraggedItems
     ];
     export function KeyLookup(keyid: string) {
         for (const key of KeyList) {
diff --git a/src/server/Message.ts b/src/server/Message.ts
index bbe4ffcad..15916ef12 100644
--- a/src/server/Message.ts
+++ b/src/server/Message.ts
@@ -14,7 +14,7 @@ export class Message<T> {
 }
 
 export enum Types {
-    Number, List, Key, Image, Web, Document, Text, RichText, DocumentReference,
+    Number, List, Key, Image, Web, Document, Text, Icon, RichText, DocumentReference,
     Html, Video, Audio, Ink, PDF, Tuple, HistogramOp, Boolean, Script,
 }
 
diff --git a/src/server/ServerUtil.ts b/src/server/ServerUtil.ts
index 818230c1a..79ca5e55d 100644
--- a/src/server/ServerUtil.ts
+++ b/src/server/ServerUtil.ts
@@ -18,6 +18,7 @@ import { NumberField } from "./../fields/NumberField";
 import { RichTextField } from "./../fields/RichTextField";
 import { TextField } from "./../fields/TextField";
 import { Transferable, Types } from "./Message";
+import { IconField } from "../fields/IconFIeld";
 
 export class ServerUtils {
     public static prepend(extension: string): string {
@@ -37,6 +38,7 @@ export class ServerUtils {
             case Types.Boolean: return new BooleanField(json.data, json.id, false);
             case Types.Number: return new NumberField(json.data, json.id, false);
             case Types.Text: return new TextField(json.data, json.id, false);
+            case Types.Icon: return new IconField(json.data, json.id, false);
             case Types.Html: return new HtmlField(json.data, json.id, false);
             case Types.Web: return new WebField(new URL(json.data), json.id, false);
             case Types.RichText: return new RichTextField(json.data, json.id, false);
-- 
cgit v1.2.3-70-g09d2


From 49131cc84b0f3e739edb5ffcd64f3acc9469f658 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 23 Apr 2019 12:17:12 -0400
Subject: fixes to zoom scaling, moved and fixed icon stuff into
 CollectionFreeFormDocumentView.  several smaller bugs.

---
 src/client/views/DocumentDecorations.tsx           |  41 ++++-
 src/client/views/Main.tsx                          |   1 +
 .../views/collections/CollectionBaseView.tsx       |   4 +-
 .../views/collections/CollectionDockingView.tsx    |   1 +
 .../views/collections/CollectionSchemaView.tsx     |   3 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |   1 +
 .../views/nodes/CollectionFreeFormDocumentView.tsx | 174 +++++++++++++++-----
 src/client/views/nodes/DocumentView.tsx            | 180 +++++----------------
 src/client/views/nodes/ImageBox.tsx                |   5 +-
 9 files changed, 215 insertions(+), 195 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index d704b6c47..95910c7be 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -18,6 +18,7 @@ import React = require("react");
 import { CompileScript } from "../util/Scripting";
 import { IconBox } from "./nodes/IconBox";
 import { FieldValue, Field } from "../../fields/Field";
+import { Documents } from "../documents/Documents";
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -134,11 +135,12 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
     @action
     onBackgroundMove = (e: PointerEvent): void => {
         let dragDocView = SelectionManager.SelectedDocuments()[0];
-        const [left, top] = dragDocView.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
+        const [left, top] = dragDocView.props.ScreenToLocalTransform().scale(dragDocView.props.ContentScaling()).inverse().transformPoint(0, 0);
         let dragData = new DragManager.DocumentDragData(SelectionManager.SelectedDocuments().map(dv => dv.props.Document));
+        const [xoff, yoff] = dragDocView.props.ScreenToLocalTransform().scale(dragDocView.props.ContentScaling()).transformDirection(e.x - left, e.y - top);
+        dragData.xOffset = xoff;
+        dragData.yOffset = yoff;
         dragData.aliasOnDrop = false;
-        dragData.xOffset = e.x - left;
-        dragData.yOffset = e.y - top;
         let move = SelectionManager.SelectedDocuments()[0].props.moveDocument;
         dragData.moveDocument = move;
         this.Interacting = this._dragging = true;
@@ -213,12 +215,39 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             this._minimizedX = snapped ? selDocPos[0] + 4 : e.clientX;
             this._minimizedY = snapped ? selDocPos[1] - 18 : e.clientY;
             let selectedDocs = SelectionManager.SelectedDocuments().map(sd => sd);
-            Promise.all(selectedDocs.map(async selDoc => await selDoc.getIconDoc())).then(minDocSet =>
+            Promise.all(selectedDocs.map(async selDoc => await this.getIconDoc(selDoc))).then(minDocSet =>
                 this.moveIconDocs(SelectionManager.SelectedDocuments())
             );
             this._iconifying = snapped;
         }
     }
+
+
+    @action createIcon = (docView: DocumentView, layoutString: string): Document => {
+        let doc = docView.props.Document;
+        let iconDoc = Documents.IconDocument(layoutString);
+        iconDoc.SetText(KeyStore.Title, "ICON" + doc.Title)
+        iconDoc.SetBoolean(KeyStore.IsMinimized, false);
+        iconDoc.SetNumber(KeyStore.NativeWidth, 0);
+        iconDoc.SetNumber(KeyStore.NativeHeight, 0);
+        iconDoc.SetNumber(KeyStore.X, doc.GetNumber(KeyStore.X, 0));
+        iconDoc.SetNumber(KeyStore.Y, doc.GetNumber(KeyStore.Y, 0) - 24);
+        iconDoc.Set(KeyStore.Prototype, doc);
+        iconDoc.Set(KeyStore.MaximizedDoc, doc);
+        doc.Set(KeyStore.MinimizedDoc, iconDoc);
+        docView.props.addDocument && docView.props.addDocument(iconDoc, false);
+        return iconDoc;
+    }
+    @action
+    public getIconDoc = async (docView: DocumentView): Promise<Document | undefined> => {
+        let doc = docView.props.Document;
+        return await doc.GetTAsync(KeyStore.MinimizedDoc, Document).then(async mindoc =>
+            mindoc ? mindoc :
+                await doc.GetTAsync(KeyStore.BackgroundLayout, TextField).then(async field =>
+                    (field instanceof TextField) ? this.createIcon(docView, field.Data) :
+                        await doc.GetTAsync(KeyStore.Layout, TextField).then(field =>
+                            (field instanceof TextField) ? this.createIcon(docView, field.Data) : undefined)));
+    }
     @action
     onMinimizeUp = (e: PointerEvent): void => {
         e.stopPropagation();
@@ -226,7 +255,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             document.removeEventListener("pointermove", this.onMinimizeMove);
             document.removeEventListener("pointerup", this.onMinimizeUp);
             let selectedDocs = SelectionManager.SelectedDocuments().map(sd => sd);
-            Promise.all(selectedDocs.map(async selDoc => await selDoc.getIconDoc())).then(minDocSet => {
+            Promise.all(selectedDocs.map(async selDoc => await this.getIconDoc(selDoc))).then(minDocSet => {
                 let minDocs = minDocSet.filter(minDoc => minDoc instanceof Document).map(minDoc => minDoc as Document);
                 minDocs.map(minDoc => {
                     minDoc.SetNumber(KeyStore.X, minDocs[0].GetNumber(KeyStore.X, 0));
@@ -238,7 +267,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                     }
                 });
                 runInAction(() => this._minimizedX = this._minimizedY = 0);
-                if (!this._iconifying) selectedDocs[0].toggleIcon();
+                if (!this._iconifying) selectedDocs[0].props.toggleMinimized();
                 this._iconifying = false;
             });
         }
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 09ef30f6b..934616aca 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -187,6 +187,7 @@ export class Main extends React.Component {
                 <div ref={measureRef} id="mainContent-div">
                     {!mainCont ? (null) :
                         <DocumentView Document={mainCont}
+                            toggleMinimized={emptyFunction}
                             addDocument={undefined}
                             removeDocument={undefined}
                             ScreenToLocalTransform={Transform.Identity}
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 9ae2993be..962cb9b65 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -94,7 +94,6 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
             doc.SetOnPrototype(KeyStore.AnnotationOn, this.props.Document);
         }
         if (!this.createsCycle(doc, this.props.Document)) {
-            doc.SetNumber(KeyStore.ZoomBasis, this.props.Document.GetNumber(KeyStore.Scale, 1));
             let value = this.props.Document.Get(this.props.fieldKey) as ListField<Document>;
             if (value) {
                 if (!value.Data.some(v => v.Id === doc.Id) || allowDuplicates) {
@@ -103,6 +102,9 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
             } else {
                 this.props.Document.Set(this.props.fieldKey, new ListField([doc]));
             }
+            // set the ZoomBasis only if hasn't already been set -- bcz: maybe set/resetting the ZoomBasis should be a parameter to addDocument?
+            doc.GetTAsync(KeyStore.ZoomBasis, NumberField, field => !field &&
+                doc.SetNumber(KeyStore.ZoomBasis, this.props.Document.GetNumber(KeyStore.Scale, 1)));
         }
         return true;
         // bcz: What is this code trying to do?
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index e4c647635..1ea18ed42 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -350,6 +350,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
             <div className="collectionDockingView-content" ref={this._mainCont}
                 style={{ transform: `translate(${this.previewPanelCenteringOffset}px, 0px)` }}>
                 <DocumentView key={this._document!.Id} Document={this._document!}
+                    toggleMinimized={emptyFunction}
                     addDocument={undefined}
                     removeDocument={undefined}
                     ContentScaling={this.contentScaling}
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 90077b053..cb7a67991 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -62,7 +62,7 @@ export class CollectionSchemaView extends CollectionSubView {
 
     @computed get splitPercentage() { return this.props.Document.GetNumber(KeyStore.SchemaSplitPercentage, 0); }
     @computed get columns() { return this.props.Document.GetList(KeyStore.ColumnsKey, [] as Key[]); }
-    @computed get borderWidth() { return COLLECTION_BORDER_WIDTH; }
+    @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
 
     renderCell = (rowProps: CellInfo) => {
         let props: FieldViewProps = {
@@ -266,6 +266,7 @@ export class CollectionSchemaView extends CollectionSubView {
             <div className="collectionSchemaView-previewRegion" style={{ width: `${this.previewRegionWidth}px` }}>
                 <div className="collectionSchemaView-previewDoc" style={{ transform: `translate(${this.previewPanelCenteringOffset}px, 0px)` }}>
                     <DocumentView Document={this.previewDocument} isTopMost={false} selectOnLoad={false}
+                        toggleMinimized={emptyFunction}
                         addDocument={this.props.addDocument} removeDocument={this.props.removeDocument}
                         ScreenToLocalTransform={this.getPreviewTransform}
                         ContentScaling={this.previewContentScaling}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 117343ef3..56d54696d 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -247,6 +247,7 @@ export class CollectionFreeFormView extends CollectionSubView {
     getDocumentViewProps(document: Document): DocumentViewProps {
         return {
             Document: document,
+            toggleMinimized: emptyFunction,
             addDocument: this.props.addDocument,
             removeDocument: this.props.removeDocument,
             moveDocument: this.props.moveDocument,
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 9fa6a4f51..3a4425358 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -1,12 +1,17 @@
-import { computed, trace } from "mobx";
+import { computed, trace, action } from "mobx";
 import { observer } from "mobx-react";
 import { KeyStore } from "../../../fields/KeyStore";
 import { NumberField } from "../../../fields/NumberField";
+import { Document } from "../../../fields/Document";
 import { Transform } from "../../util/Transform";
 import { DocumentView, DocumentViewProps } from "./DocumentView";
 import "./DocumentView.scss";
 import React = require("react");
 import { OmitKeys } from "../../../Utils";
+import { SelectionManager } from "../../util/SelectionManager";
+import { ListField } from "../../../fields/ListField";
+import { BooleanField } from "../../../fields/BooleanField";
+import { matchedData } from "express-validator/filter";
 
 export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
 }
@@ -14,55 +19,48 @@ export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
 @observer
 export class CollectionFreeFormDocumentView extends React.Component<CollectionFreeFormDocumentViewProps> {
     private _mainCont = React.createRef<HTMLDivElement>();
+    private _downX: number = 0;
+    private _downY: number = 0;
 
-    @computed
-    get transform(): string {
+    @computed get transform() {
         return `scale(${this.props.ContentScaling()}, ${this.props.ContentScaling()}) translate(${this.X}px, ${this.Y}px) scale(${this.zoom}, ${this.zoom}) `;
     }
-
-    @computed get zoom(): number { return 1 / this.props.Document.GetNumber(KeyStore.ZoomBasis, 1); }
-    @computed get zIndex(): number { return this.props.Document.GetNumber(KeyStore.ZIndex, 0); }
-    @computed get width(): number { return this.props.Document.Width(); }
-    @computed get height(): number { return this.props.Document.Height(); }
-    @computed get nativeWidth(): number { return this.props.Document.GetNumber(KeyStore.NativeWidth, 0); }
-    @computed get nativeHeight(): number { return this.props.Document.GetNumber(KeyStore.NativeHeight, 0); }
-
+    @computed get X() { return this.props.Document.GetNumber(KeyStore.X, 0); }
+    @computed get Y() { return this.props.Document.GetNumber(KeyStore.Y, 0); }
+    @computed get zoom() { return 1 / this.props.Document.GetNumber(KeyStore.ZoomBasis, 1); }
+    @computed get nativeWidth() { return this.props.Document.GetNumber(KeyStore.NativeWidth, 0); }
+    @computed get nativeHeight() { return this.props.Document.GetNumber(KeyStore.NativeHeight, 0); }
+    @computed get width() { return this.props.Document.Width(); }
+    @computed get height() { return this.props.Document.Height(); }
+    @computed get zIndex() { return this.props.Document.GetNumber(KeyStore.ZIndex, 0); }
     set width(w: number) {
         this.props.Document.SetData(KeyStore.Width, w, NumberField);
         if (this.nativeWidth && this.nativeHeight) {
             this.props.Document.SetNumber(KeyStore.Height, this.nativeHeight / this.nativeWidth * w);
         }
     }
-
     set height(h: number) {
         this.props.Document.SetData(KeyStore.Height, h, NumberField);
         if (this.nativeWidth && this.nativeHeight) {
             this.props.Document.SetNumber(KeyStore.Width, this.nativeWidth / this.nativeHeight * h);
         }
     }
-
     set zIndex(h: number) {
         this.props.Document.SetData(KeyStore.ZIndex, h, NumberField);
     }
 
-    get X() {
-        return this.props.Document.GetNumber(KeyStore.X, 0);
-    }
-    get Y() {
-        return this.props.Document.GetNumber(KeyStore.Y, 0);
-    }
-    getTransform = (): Transform =>
-        this.props.ScreenToLocalTransform()
-            .translate(-this.X, -this.Y)
-            .scale(1 / this.contentScaling()).scale(1 / this.zoom)
-
     contentScaling = () => (this.nativeWidth > 0 ? this.width / this.nativeWidth : 1);
     panelWidth = () => this.props.PanelWidth();
     panelHeight = () => this.props.PanelHeight();
+    toggleMinimized = () => this.toggleIcon();
+    getTransform = (): Transform => this.props.ScreenToLocalTransform()
+        .translate(-this.X, -this.Y)
+        .scale(1 / this.contentScaling()).scale(1 / this.zoom)
 
     @computed
     get docView() {
         return <DocumentView {...OmitKeys(this.props, ['zoomFade'])}
+            toggleMinimized={this.toggleMinimized}
             ContentScaling={this.contentScaling}
             ScreenToLocalTransform={this.getTransform}
             PanelWidth={this.panelWidth}
@@ -70,30 +68,120 @@ export class CollectionFreeFormDocumentView extends React.Component<CollectionFr
         />;
     }
 
+    animateBetweenIcon(first: boolean, icon: number[], targ: number[], width: number, height: number, stime: number, target: Document, maximizing: boolean) {
+        setTimeout(() => {
+            let now = Date.now();
+            let progress = Math.min(1, (now - stime) / 200);
+            let pval = maximizing ?
+                [icon[0] + (targ[0] - icon[0]) * progress, icon[1] + (targ[1] - icon[1]) * progress] :
+                [targ[0] + (icon[0] - targ[0]) * progress, targ[1] + (icon[1] - targ[1]) * progress];
+            target.SetNumber(KeyStore.Width, maximizing ? 25 + (width - 25) * progress : width + (25 - width) * progress);
+            target.SetNumber(KeyStore.Height, maximizing ? 25 + (height - 25) * progress : height + (25 - height) * progress);
+            target.SetNumber(KeyStore.X, pval[0]);
+            target.SetNumber(KeyStore.Y, pval[1]);
+            if (first) {
+                target.SetBoolean(KeyStore.IsMinimized, false);
+            }
+            if (now < stime + 200) {
+                this.animateBetweenIcon(false, icon, targ, width, height, stime, target, maximizing);
+            }
+            else {
+                if (!maximizing) {
+                    target.SetBoolean(KeyStore.IsMinimized, true);
+                    target.SetNumber(KeyStore.X, targ[0]);
+                    target.SetNumber(KeyStore.Y, targ[1]);
+                    target.SetNumber(KeyStore.Width, width);
+                    target.SetNumber(KeyStore.Height, height);
+                }
+                (target as any).isIconAnimating = false;
+            }
+        },
+            2);
+    }
+    @action
+    public toggleIcon = async (): Promise<void> => {
+        SelectionManager.DeselectAll();
+        let isMinimized: boolean | undefined;
+        let minDoc = await this.props.Document.GetTAsync(KeyStore.MinimizedDoc, Document);
+        if (!minDoc) return;
+        let minimizedDocSet = await minDoc.GetTAsync(KeyStore.LinkTags, ListField);
+        if (!minimizedDocSet) return;
+        minimizedDocSet.Data.map(async minimizedDoc => {
+            if (minimizedDoc instanceof Document) {
+                this.props.addDocument && this.props.addDocument(minimizedDoc, false);
+                let maximizedDoc = await minimizedDoc.GetTAsync(KeyStore.MaximizedDoc, Document);
+                if (maximizedDoc instanceof Document && !(maximizedDoc as any).isIconAnimating) {
+                    (maximizedDoc as any).isIconAnimating = true;
+                    if (isMinimized === undefined) {
+                        let maximizedDocMinimizedState = await maximizedDoc.GetTAsync(KeyStore.IsMinimized, BooleanField);
+                        isMinimized = (maximizedDocMinimizedState && maximizedDocMinimizedState.Data) ? true : false;
+                    }
+                    let minx = await minimizedDoc.GetTAsync(KeyStore.X, NumberField);
+                    let miny = await minimizedDoc.GetTAsync(KeyStore.Y, NumberField);
+                    let maxx = await maximizedDoc.GetTAsync(KeyStore.X, NumberField);
+                    let maxy = await maximizedDoc.GetTAsync(KeyStore.Y, NumberField);
+                    let maxw = await maximizedDoc.GetTAsync(KeyStore.Width, NumberField);
+                    let maxh = await maximizedDoc.GetTAsync(KeyStore.Height, NumberField);
+                    if (minx !== undefined && miny !== undefined && maxx !== undefined && maxy !== undefined &&
+                        maxw !== undefined && maxh !== undefined)
+                        this.animateBetweenIcon(
+                            true,
+                            [minx.Data, miny.Data], [maxx.Data, maxy.Data], maxw.Data, maxh.Data,
+                            Date.now(), maximizedDoc, isMinimized);
+                }
+
+            }
+        })
+    }
+    onPointerDown = (e: React.PointerEvent): void => {
+        e.stopPropagation();
+        this._downX = e.clientX;
+        this._downY = e.clientY;
+        document.removeEventListener("pointerup", this.onPointerUp);
+        document.addEventListener("pointerup", this.onPointerUp);
+    }
+    onPointerUp = (e: PointerEvent): void => {
+        document.removeEventListener("pointerup", this.onPointerUp);
+        e.stopPropagation();
+        if (Math.abs(e.clientX - this._downX) < 4 && Math.abs(e.clientY - this._downY) < 4) {
+            this.props.Document.GetTAsync(KeyStore.MaximizedDoc, Document).then(maxdoc => {
+                if (maxdoc instanceof Document) {   // bcz: need a better way to associate behaviors with click events on widget-documents
+                    SelectionManager.DeselectAll();
+                    this.props.addDocument && this.props.addDocument(maxdoc, false);
+                    this.toggleIcon();
+                }
+            });
+        }
+    }
+
     render() {
+        let maximizedDoc = this.props.Document.GetT(KeyStore.MaximizedDoc, Document);
         let zoomFade = 1;
         //var zoom = doc.GetNumber(KeyStore.ZoomBasis, 1);
-        // let transform = this.getTransform().scale(this.contentScaling()).inverse();
-        // var [sptX, sptY] = transform.transformPoint(0, 0);
-        // let [bptX, bptY] = transform.transformPoint(this.props.PanelWidth(), this.props.PanelHeight());
-        // let w = bptX - sptX;
-        // //zoomFade = area < 100 || area > 800 ? Math.max(0, Math.min(1, 2 - 5 * (zoom < this.scale ? this.scale / zoom : zoom / this.scale))) : 1;
-        // let fadeUp = .75 * 1800;
-        // let fadeDown = .075 * 1800;
-        // zoomFade = w < fadeDown  /* || w > fadeUp */ ? Math.max(0, Math.min(1, 2 - (w < fadeDown ? fadeDown / w : w / fadeUp))) : 1;
+        let transform = this.getTransform().scale(this.contentScaling()).inverse();
+        var [sptX, sptY] = transform.transformPoint(0, 0);
+        let [bptX, bptY] = transform.transformPoint(this.props.PanelWidth(), this.props.PanelHeight());
+        let w = bptX - sptX;
+        //zoomFade = area < 100 || area > 800 ? Math.max(0, Math.min(1, 2 - 5 * (zoom < this.scale ? this.scale / zoom : zoom / this.scale))) : 1;
+        const screenWidth = 1800;
+        let fadeUp = .75 * screenWidth;
+        let fadeDown = (maximizedDoc ? .0075 : .075) * screenWidth;
+        zoomFade = w < fadeDown  /* || w > fadeUp */ ? Math.max(0, Math.min(1, 2 - (w < fadeDown ? fadeDown / w : w / fadeUp))) : 1;
 
         return (
-            <div className="collectionFreeFormDocumentView-container" ref={this._mainCont} style={{
-                opacity: zoomFade,
-                transformOrigin: "left top",
-                transform: this.transform,
-                pointerEvents: (zoomFade < 0.09 ? "none" : "all"),
-                width: this.width,
-                height: this.height,
-                position: "absolute",
-                zIndex: this.zIndex,
-                backgroundColor: "transparent"
-            }} >
+            <div className="collectionFreeFormDocumentView-container" ref={this._mainCont}
+                onPointerDown={this.onPointerDown}
+                style={{
+                    opacity: zoomFade,
+                    transformOrigin: "left top",
+                    transform: this.transform,
+                    pointerEvents: (zoomFade < 0.09 ? "none" : "all"),
+                    width: this.width,
+                    height: this.height,
+                    position: "absolute",
+                    zIndex: this.zIndex,
+                    backgroundColor: "transparent"
+                }} >
                 {this.docView}
             </div>
         );
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 2f8ac9f20..8922e4b81 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -5,8 +5,6 @@ import { Field, Opt } from "../../../fields/Field";
 import { Key } from "../../../fields/Key";
 import { KeyStore } from "../../../fields/KeyStore";
 import { ListField } from "../../../fields/ListField";
-import { NumberField } from "../../../fields/NumberField";
-import { TextField } from "../../../fields/TextField";
 import { ServerUtils } from "../../../server/ServerUtil";
 import { emptyFunction, Utils } from "../../../Utils";
 import { Documents } from "../../documents/Documents";
@@ -40,6 +38,7 @@ export interface DocumentViewProps {
     selectOnLoad: boolean;
     parentActive: () => boolean;
     whenActiveChanged: (isActive: boolean) => void;
+    toggleMinimized: () => void;
 }
 export interface JsxArgs extends DocumentViewProps {
     Keys: { [name: string]: Key };
@@ -83,7 +82,6 @@ export function FakeJsxArgs(keys: string[], fields: string[] = []): JsxArgs {
 
 @observer
 export class DocumentView extends React.Component<DocumentViewProps> {
-    static _incompleteAnimations: Map<string, boolean> = new Map<string, boolean>();
     private _downX: number = 0;
     private _downY: number = 0;
     private _mainCont = React.createRef<HTMLDivElement>();
@@ -96,42 +94,16 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     @computed get layoutKeys(): Key[] { return this.props.Document.GetData(KeyStore.LayoutKeys, ListField, new Array<Key>()); }
     @computed get layoutFields(): Key[] { return this.props.Document.GetData(KeyStore.LayoutFields, ListField, new Array<Key>()); }
 
-    onPointerDown = (e: React.PointerEvent): void => {
-        this._downX = e.clientX;
-        this._downY = e.clientY;
-        if (CollectionFreeFormView.RIGHT_BTN_DRAG && (e.button === 2 || (e.button === 0 && e.altKey)) && !this.isSelected()) {
-            return;
-        }
-        if (e.shiftKey && e.buttons === 2) {
-            if (this.props.isTopMost) {
-                this.startDragging(e.pageX, e.pageY, e.altKey || e.ctrlKey);
-            } else {
-                CollectionDockingView.Instance.StartOtherDrag([this.props.Document], e);
-            }
-            e.stopPropagation();
-        } else {
-            let maxdoc = this.props.Document.GetT(KeyStore.MaximizedDoc, Document);
-            if (this.active ||
-                maxdoc instanceof Document // bcz: need a better way of allowing a document to handle pointer events when its not active (ie. be a top-level widget)
-            ) {
-                e.stopPropagation();
-                document.removeEventListener("pointermove", this.onPointerMove);
-                document.addEventListener("pointermove", this.onPointerMove);
-                document.removeEventListener("pointerup", this.onPointerUp);
-                document.addEventListener("pointerup", this.onPointerUp);
-            }
-        }
-    }
-
+    @action
     componentDidMount() {
         if (this._mainCont.current) {
             this._dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, {
                 handlers: { drop: this.drop.bind(this) }
             });
         }
-        runInAction(() => DocumentManager.Instance.DocumentViews.push(this));
+        DocumentManager.Instance.DocumentViews.push(this);
     }
-
+    @action
     componentDidUpdate() {
         if (this._dropDisposer) {
             this._dropDisposer();
@@ -142,12 +114,16 @@ export class DocumentView extends React.Component<DocumentViewProps> {
             });
         }
     }
-
+    @action
     componentWillUnmount() {
         if (this._dropDisposer) {
             this._dropDisposer();
         }
-        runInAction(() => DocumentManager.Instance.DocumentViews.splice(DocumentManager.Instance.DocumentViews.indexOf(this), 1));
+        DocumentManager.Instance.DocumentViews.splice(DocumentManager.Instance.DocumentViews.indexOf(this), 1);
+    }
+
+    stopPropagation = (e: React.SyntheticEvent) => {
+        e.stopPropagation();
     }
 
     startDragging(x: number, y: number, dropAliasOfDraggedDoc: boolean) {
@@ -168,43 +144,51 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         }
     }
 
-    onPointerMove = (e: PointerEvent): void => {
-        if (e.cancelBubble) {
+    onPointerDown = (e: React.PointerEvent): void => {
+        this._downX = e.clientX;
+        this._downY = e.clientY;
+        if (CollectionFreeFormView.RIGHT_BTN_DRAG && (e.button === 2 || (e.button === 0 && e.altKey)) && !this.isSelected()) {
             return;
         }
-        if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) {
+        if (e.shiftKey && e.buttons === 2) {
+            if (this.props.isTopMost) {
+                this.startDragging(e.pageX, e.pageY, e.altKey || e.ctrlKey);
+            } else {
+                CollectionDockingView.Instance.StartOtherDrag([this.props.Document], e);
+            }
+            e.stopPropagation();
+        } else if (this.active) {
             document.removeEventListener("pointermove", this.onPointerMove);
+            document.addEventListener("pointermove", this.onPointerMove);
             document.removeEventListener("pointerup", this.onPointerUp);
-            if (!e.altKey && (!this.topMost || e.buttons === 2)) {
-                this.startDragging(this._downX, this._downY, e.ctrlKey || e.altKey);
+            document.addEventListener("pointerup", this.onPointerUp);
+        }
+    }
+    onPointerMove = (e: PointerEvent): void => {
+        if (!e.cancelBubble) {
+            if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) {
+                document.removeEventListener("pointermove", this.onPointerMove);
+                document.removeEventListener("pointerup", this.onPointerUp);
+                if (!e.altKey && (!this.topMost || e.buttons === 2)) {
+                    this.startDragging(this._downX, this._downY, e.ctrlKey || e.altKey);
+                }
             }
+            e.stopPropagation();
+            e.preventDefault();
         }
-        e.stopPropagation();
-        e.preventDefault();
     }
     onPointerUp = (e: PointerEvent): void => {
         document.removeEventListener("pointermove", this.onPointerMove);
         document.removeEventListener("pointerup", this.onPointerUp);
-        e.stopPropagation();
         if (!SelectionManager.IsSelected(this) && e.button !== 2 &&
             Math.abs(e.clientX - this._downX) < 4 && Math.abs(e.clientY - this._downY) < 4) {
-            this.props.Document.GetTAsync(KeyStore.MaximizedDoc, Document).then(maxdoc => {
-                if (maxdoc instanceof Document) {   // bcz: need a better way to associate behaviors with click events on widget-documents
-                    this.props.addDocument && this.props.addDocument(maxdoc, false);
-                    this.toggleIcon();
-                } else
-                    SelectionManager.SelectDoc(this, e.ctrlKey);
-            });
+            SelectionManager.SelectDoc(this, e.ctrlKey);
         }
     }
-    stopPropagation = (e: React.SyntheticEvent) => {
-        e.stopPropagation();
-    }
 
     deleteClicked = (): void => {
         this.props.removeDocument && this.props.removeDocument(this.props.Document);
     }
-
     fieldsClicked = (e: React.MouseEvent): void => {
         let kvp = Documents.KVPDocument(this.props.Document, { width: 300, height: 300 });
         CollectionDockingView.Instance.AddRightSplit(kvp);
@@ -215,7 +199,6 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         ContextMenu.Instance.addItem({ description: "Close Full Screen", event: this.closeFullScreenClicked });
         ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15);
     }
-
     closeFullScreenClicked = (e: React.MouseEvent): void => {
         CollectionDockingView.Instance.CloseFullScreen();
         ContextMenu.Instance.clearItems();
@@ -223,92 +206,6 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15);
     }
 
-    @action createIcon = (layoutString: string): Document => {
-        let iconDoc = Documents.IconDocument(layoutString);
-        iconDoc.SetText(KeyStore.Title, "ICON" + this.props.Document.Title)
-        iconDoc.SetBoolean(KeyStore.IsMinimized, false);
-        iconDoc.SetNumber(KeyStore.NativeWidth, 0);
-        iconDoc.SetNumber(KeyStore.NativeHeight, 0);
-        iconDoc.SetNumber(KeyStore.X, this.props.Document.GetNumber(KeyStore.X, 0));
-        iconDoc.SetNumber(KeyStore.Y, this.props.Document.GetNumber(KeyStore.Y, 0) - 24);
-        iconDoc.Set(KeyStore.Prototype, this.props.Document);
-        iconDoc.Set(KeyStore.MaximizedDoc, this.props.Document);
-        this.props.Document.Set(KeyStore.MinimizedDoc, iconDoc);
-        this.props.addDocument && this.props.addDocument(iconDoc, false);
-        return iconDoc;
-    }
-
-    animateBetweenIcon(icon: number[], targ: number[], width: number, height: number, stime: number, target: Document, maximizing: boolean) {
-        setTimeout(() => {
-            let now = Date.now();
-            let progress = Math.min(1, (now - stime) / 200);
-            let pval = maximizing ?
-                [icon[0] + (targ[0] - icon[0]) * progress, icon[1] + (targ[1] - icon[1]) * progress] :
-                [targ[0] + (icon[0] - targ[0]) * progress, targ[1] + (icon[1] - targ[1]) * progress];
-            target.SetNumber(KeyStore.Width, maximizing ? 25 + (width - 25) * progress : width + (25 - width) * progress);
-            target.SetNumber(KeyStore.Height, maximizing ? 25 + (height - 25) * progress : height + (25 - height) * progress);
-            target.SetNumber(KeyStore.X, pval[0]);
-            target.SetNumber(KeyStore.Y, pval[1]);
-            if (now < stime + 200) {
-                this.animateBetweenIcon(icon, targ, width, height, stime, target, maximizing);
-            }
-            else {
-                if (!maximizing) {
-                    target.SetBoolean(KeyStore.IsMinimized, true);
-                    target.SetNumber(KeyStore.X, targ[0]);
-                    target.SetNumber(KeyStore.Y, targ[1]);
-                    target.SetNumber(KeyStore.Width, width);
-                    target.SetNumber(KeyStore.Height, height);
-                }
-                DocumentView._incompleteAnimations.set(target.Id, false);
-            }
-        },
-            2);
-    }
-
-    @action
-    public toggleIcon = async (): Promise<void> => {
-        SelectionManager.DeselectAll();
-        let isMinimized: boolean | undefined;
-        let minDoc = await this.props.Document.GetTAsync(KeyStore.MinimizedDoc, Document);
-        if (!minDoc) return;
-        let minimizedDocSet = await minDoc.GetTAsync(KeyStore.LinkTags, ListField);
-        if (!minimizedDocSet) return;
-        minimizedDocSet.Data.map(async minimizedDoc => {
-            if (minimizedDoc instanceof Document) {
-                this.props.addDocument && this.props.addDocument(minimizedDoc, false);
-                let maximizedDoc = await minimizedDoc.GetTAsync(KeyStore.MaximizedDoc, Document);
-                if (maximizedDoc instanceof Document && !DocumentView._incompleteAnimations.get(maximizedDoc.Id)) {
-                    DocumentView._incompleteAnimations.set(maximizedDoc.Id, true);
-                    isMinimized = isMinimized === undefined ? maximizedDoc.GetBoolean(KeyStore.IsMinimized, false) : isMinimized;
-                    maximizedDoc.SetBoolean(KeyStore.IsMinimized, false);
-                    let minx = await minimizedDoc.GetTAsync(KeyStore.X, NumberField);
-                    let miny = await minimizedDoc.GetTAsync(KeyStore.Y, NumberField);
-                    let maxx = await maximizedDoc.GetTAsync(KeyStore.X, NumberField);
-                    let maxy = await maximizedDoc.GetTAsync(KeyStore.Y, NumberField);
-                    let maxw = await maximizedDoc.GetTAsync(KeyStore.Width, NumberField);
-                    let maxh = await maximizedDoc.GetTAsync(KeyStore.Height, NumberField);
-                    if (minx !== undefined && miny !== undefined && maxx !== undefined && maxy !== undefined &&
-                        maxw !== undefined && maxh !== undefined)
-                        this.animateBetweenIcon(
-                            [minx.Data, miny.Data], [maxx.Data, maxy.Data], maxw.Data, maxh.Data,
-                            Date.now(), maximizedDoc, isMinimized);
-                }
-
-            }
-        })
-    }
-
-    @action
-    public getIconDoc = async (): Promise<Document | undefined> => {
-        return await this.props.Document.GetTAsync(KeyStore.MinimizedDoc, Document).then(async mindoc =>
-            mindoc ? mindoc :
-                await this.props.Document.GetTAsync(KeyStore.BackgroundLayout, TextField).then(async field =>
-                    (field instanceof TextField) ? this.createIcon(field.Data) :
-                        await this.props.Document.GetTAsync(KeyStore.Layout, TextField).then(field =>
-                            (field instanceof TextField) ? this.createIcon(field.Data) : undefined)));
-    }
-
     @undoBatch
     @action
     drop = (e: Event, de: DragManager.DropEvent) => {
@@ -353,6 +250,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         }
     }
 
+    @action
     onDrop = (e: React.DragEvent) => {
         let text = e.dataTransfer.getData("text/plain");
         if (!e.isDefaultPrevented() && text && text.startsWith("<div")) {
@@ -389,12 +287,10 @@ export class DocumentView extends React.Component<DocumentViewProps> {
 
     isSelected = () => SelectionManager.IsSelected(this);
     select = (ctrlPressed: boolean) => SelectionManager.SelectDoc(this, ctrlPressed);
-
     @computed get nativeWidth() { return this.props.Document.GetNumber(KeyStore.NativeWidth, 0); }
     @computed get nativeHeight() { return this.props.Document.GetNumber(KeyStore.NativeHeight, 0); }
     @computed get contents() { return (<DocumentContentsView {...this.props} isSelected={this.isSelected} select={this.select} layoutKey={KeyStore.Layout} />); }
 
-
     render() {
         var scaling = this.props.ContentScaling();
         var nativeHeight = this.nativeHeight > 0 ? this.nativeHeight.toString() + "px" : "100%";
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 5d9aefd61..a16fd5007 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -16,7 +16,7 @@ import { FieldView, FieldViewProps } from './FieldView';
 import "./ImageBox.scss";
 import React = require("react");
 import { InkingControl } from '../InkingControl';
-import { InkTool } from '../../../fields/InkField';
+import { NumberField } from '../../../fields/NumberField';
 
 @observer
 export class ImageBox extends React.Component<FieldViewProps> {
@@ -42,7 +42,8 @@ export class ImageBox extends React.Component<FieldViewProps> {
         var w = this._imgRef.current!.naturalWidth;
         if (this._photoIndex === 0) {
             this.props.Document.SetNumber(KeyStore.NativeHeight, this.props.Document.GetNumber(KeyStore.NativeWidth, 0) * h / w);
-            this.props.Document.SetNumber(KeyStore.Height, this.props.Document.Width() * h / w);
+            this.props.Document.GetTAsync(KeyStore.Width, NumberField, field =>
+                field && this.props.Document.SetNumber(KeyStore.Height, field.Data * h / w));
         }
     }
 
-- 
cgit v1.2.3-70-g09d2


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

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

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

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


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

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

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

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


From 6b116d69a5b1a991c7aa00e2b23af3f8db7c7d77 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 30 Apr 2019 09:27:24 -0400
Subject: fixed schema column default/persistence

---
 src/client/documents/Documents.ts                  |  8 ++++---
 .../views/collections/CollectionSchemaView.tsx     | 28 ++++++++++++----------
 src/fields/Document.ts                             |  2 +-
 3 files changed, 22 insertions(+), 16 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index a7514f1d6..847f604d0 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -60,6 +60,7 @@ export interface DocumentOptions {
     copyDraggedItems?: boolean;
     documentText?: string;
     borderRounding?: number;
+    columnsKey?: Array<Key>;
 }
 
 export namespace Documents {
@@ -116,6 +117,7 @@ export namespace Documents {
         if (options.layoutKeys !== undefined) { doc.Set(KeyStore.LayoutKeys, new ListField(options.layoutKeys)); }
         if (options.copyDraggedItems !== undefined) { doc.SetBoolean(KeyStore.CopyDraggedItems, options.copyDraggedItems); }
         if (options.borderRounding !== undefined) { doc.SetNumber(KeyStore.BorderRounding, options.borderRounding); }
+        if (options.columnsKey !== undefined) { doc.SetData(KeyStore.ColumnsKey, options.columnsKey, ListField); }
         return doc;
     }
 
@@ -271,13 +273,13 @@ export namespace Documents {
         if (!makePrototype) {
             return SetInstanceOptions(collProto, { ...options, viewType: CollectionViewType.Freeform }, [documents, ListField], id);
         }
-        return assignToDelegate(SetInstanceOptions(collProto, { ...options, viewType: CollectionViewType.Freeform }, [documents, ListField], id).MakeDelegate(), options);
+        return assignToDelegate(SetInstanceOptions(collProto, { columnsKey: [KeyStore.Title], ...options, viewType: CollectionViewType.Freeform }, [documents, ListField], id).MakeDelegate(), options);
     }
     export function SchemaDocument(documents: Array<Document>, options: DocumentOptions, id?: string) {
-        return assignToDelegate(SetInstanceOptions(collProto, { ...options, viewType: CollectionViewType.Schema }, [documents, ListField], id), options);
+        return assignToDelegate(SetInstanceOptions(collProto, { columnsKey: [KeyStore.Title], ...options, viewType: CollectionViewType.Schema }, [documents, ListField], id), options);
     }
     export function TreeDocument(documents: Array<Document>, options: DocumentOptions, id?: string) {
-        return assignToDelegate(SetInstanceOptions(collProto, { ...options, viewType: CollectionViewType.Tree }, [documents, ListField], id), options);
+        return assignToDelegate(SetInstanceOptions(collProto, { columnsKey: [KeyStore.Title], ...options, viewType: CollectionViewType.Tree }, [documents, ListField], id), options);
     }
     export function DockDocument(config: string, options: DocumentOptions, id?: string) {
         return assignToDelegate(SetInstanceOptions(collProto, { ...options, viewType: CollectionViewType.Docking }, [config, TextField], id), options);
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index b6d5f1bfa..b3cc3fbd5 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -2,13 +2,13 @@ import React = require("react");
 import { library } from '@fortawesome/fontawesome-svg-core';
 import { faCog, faPlus } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, observable, untracked } from "mobx";
+import { action, computed, observable, untracked, runInAction } from "mobx";
 import { observer } from "mobx-react";
 import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table";
 import { MAX_ROW_HEIGHT } from '../../views/globalCssVariables.scss'
 import "react-table/react-table.css";
 import { Document } from "../../../fields/Document";
-import { Field, Opt } from "../../../fields/Field";
+import { Field, Opt, FieldWaiting } from "../../../fields/Field";
 import { Key } from "../../../fields/Key";
 import { KeyStore } from "../../../fields/KeyStore";
 import { ListField } from "../../../fields/ListField";
@@ -165,18 +165,22 @@ export class CollectionSchemaView extends CollectionSubView {
         super.CreateDropTarget(ele);
     }
 
-    @action
     toggleKey = (key: Key) => {
-        this.props.Document.GetOrCreateAsync<ListField<Key>>(KeyStore.ColumnsKey, ListField,
-            (field) => {
-                const index = field.Data.indexOf(key);
-                if (index === -1) {
-                    this.columns.push(key);
-                } else {
-                    this.columns.splice(index, 1);
+        this.props.Document.GetTAsync<ListField<Key>>(KeyStore.ColumnsKey, ListField).then(field =>
+            runInAction(() => {
+                if (field !== FieldWaiting) {
+                    if (field) {
+                        const index = field.Data.indexOf(key);
+                        if (index === -1) {
+                            this.columns.push(key);
+                        } else {
+                            this.columns.splice(index, 1);
+                        }
+                    } else {
+                        this.props.Document.SetData(KeyStore.ColumnsKey, [key], ListField);
+                    }
                 }
-
-            });
+            }));
     }
 
     //toggles preview side-panel of schema
diff --git a/src/fields/Document.ts b/src/fields/Document.ts
index 2797efc09..55ac731dd 100644
--- a/src/fields/Document.ts
+++ b/src/fields/Document.ts
@@ -204,7 +204,7 @@ export class Document extends Field {
         callback: (field: T) => void
     ): void {
         //This currently doesn't deal with prototypes
-        if (this._proxies.has(key.Id)) {
+        if (this._proxies.has(key.Id) || this.fields.has(key.Id)) {
             Server.GetDocumentField(this, key, field => {
                 if (field && field instanceof ctor) {
                     callback(field);
-- 
cgit v1.2.3-70-g09d2

