From 0bc5f59932edae2d32ac378db1afc2733044eb9c Mon Sep 17 00:00:00 2001
From: Hannah Chow <hannah_chow@brown.edu>
Date: Tue, 9 Apr 2019 19:07:31 -0400
Subject: all styling stuff done

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

(limited to 'src/client/views/nodes/LinkBox.tsx')

diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx
index b016a3d48..ca1b97eba 100644
--- a/src/client/views/nodes/LinkBox.tsx
+++ b/src/client/views/nodes/LinkBox.tsx
@@ -110,8 +110,8 @@ export class LinkBox extends React.Component<Props> {
                 </div>
 
                 <div className="button-container">
-                    <div title="Follow Link" className="button" onPointerDown={this.onViewButtonPressed}>
-                        <FontAwesomeIcon className="fa-icon-view" icon="eye" size="sm" /></div>
+                    {/* <div title="Follow Link" className="button" onPointerDown={this.onViewButtonPressed}>
+                        <FontAwesomeIcon className="fa-icon-view" icon="eye" size="sm" /></div> */}
                     <div title="Edit Link" className="button" onPointerDown={this.onEditButtonPressed}>
                         <FontAwesomeIcon className="fa-icon-edit" icon="edit" size="sm" /></div>
                     <div title="Delete Link" className="button" onPointerDown={this.onDeleteButtonPressed}>
-- 
cgit v1.2.3-70-g09d2


From f8d4fa3d161da88e63e51c4a8940a3c44d0ae62e Mon Sep 17 00:00:00 2001
From: Hannah Chow <hannah_chow@brown.edu>
Date: Tue, 9 Apr 2019 22:01:44 -0400
Subject: for now

---
 src/client/views/DocumentDecorations.scss          |   9 +-
 src/client/views/DocumentDecorations.tsx           |   3 +-
 .../collectionFreeForm/CollectionFreeFormView.scss | 140 ++++++++++++---------
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  15 ++-
 src/client/views/nodes/LinkBox.tsx                 |   1 +
 src/fields/KeyStore.ts                             |   1 +
 6 files changed, 102 insertions(+), 67 deletions(-)

(limited to 'src/client/views/nodes/LinkBox.tsx')

diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss
index ecc738076..3871be35b 100644
--- a/src/client/views/DocumentDecorations.scss
+++ b/src/client/views/DocumentDecorations.scss
@@ -69,6 +69,7 @@
     }
 }
 
+
 .documentDecorations-closeButton {
     background: $alt-accent;
     opacity: 0.8;
@@ -125,6 +126,10 @@
 //     }
 // }
 
+.linkFlyout {
+    grid-column: 2/4;
+}
+
 .linkButton-empty:hover {
     background: $main-accent;
     transform: scale(1.05);
@@ -162,10 +167,6 @@
     transform: scale(1.05);
 }
 
-.linkButton-tray {
-    grid-column: 1/4;
-}
-
 .linkButton-empty {
     height: 20px;
     width: 20px;
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index bb4437a6a..4a329dd36 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -442,9 +442,10 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 <div id="documentDecorations-bottomRightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                 <div className="link-button-container">
                     <div title="View Links" className="linkFlyout" ref={this._linkButton}> {linkButton}  </div>
-                    <div className="linkButton-linker" ref={this._linkerButton} onPointerDown={this.onLinkerButtonDown}>
+                    <div title="Drag Link" className="linkButton-linker" ref={this._linkerButton} onPointerDown={this.onLinkerButtonDown}>
                         <FontAwesomeIcon className="fa-icon-link" icon="link" size="sm" />
                     </div>
+
                 </div>
             </div >
         </div>
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
index 81f2146e4..f9d786c9b 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
@@ -1,92 +1,110 @@
 @import "../../global_variables";
+
 .collectionfreeformview-measure {
     position: absolute;
     top: 0;
     left: 0;
     width: 100%;
     height: 100%;
-  }
-.collectionfreeformview {
-  position: absolute;
-  top: 0;
-  left: 0;
-  width: 100%;
-  height: 100%;
-  transform-origin: left top;
 }
-.collectionfreeformview-container {
-  .collectionfreeformview > .jsx-parser {
+
+.collectionfreeformview-ease {
     position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
     height: 100%;
+    transform-origin: left top;
+    transition: transform 2s;
+}
+
+.collectionfreeformview-none {
+    position: absolute;
+    top: 0;
+    left: 0;
     width: 100%;
-  }
+    height: 100%;
+    transform-origin: left top;
+}
+
+.collectionfreeformview-container {
+    .collectionfreeformview>.jsx-parser {
+        position: absolute;
+        height: 100%;
+        width: 100%;
+    }
 
-  //nested freeform views
-  // .collectionfreeformview-container {
+    //nested freeform views
+    // .collectionfreeformview-container {
     // background-image: linear-gradient(to right, $light-color-secondary 1px, transparent 1px),
     //   linear-gradient(to bottom, $light-color-secondary 1px, transparent 1px);
     // background-size: 30px 30px;
-  // }
+    // }
 
-  box-shadow: $intermediate-color 0.2vw 0.2vw 0.8vw;
-  border: 0px solid $light-color-secondary;
-  border-radius: $border-radius;
-  box-sizing: border-box;
-  position: absolute;
-  overflow: hidden;
-  top: 0;
-  left: 0;
-  width: 100%;
-  height: 100%;
-}
-.collectionfreeformview-overlay {
-  .collectionfreeformview > .jsx-parser {
+    box-shadow: $intermediate-color 0.2vw 0.2vw 0.8vw;
+    border: 0px solid $light-color-secondary;
+    border-radius: $border-radius;
+    box-sizing: border-box;
     position: absolute;
+    overflow: hidden;
+    top: 0;
+    left: 0;
+    width: 100%;
     height: 100%;
-  }
-  .formattedTextBox-cont {
-    background: $light-color-secondary;
-  }
- 
-  opacity: 0.99;
-  border: 0px solid transparent;
-  border-radius: $border-radius;
-  box-sizing: border-box;
-  position:absolute;
-  overflow: hidden;
-  top: 0;
-  left: 0;
-  width: 100%;
-  height: 100%;
-  .collectionfreeformview {
+}
+
+.collectionfreeformview-overlay {
+    .collectionfreeformview>.jsx-parser {
+        position: absolute;
+        height: 100%;
+    }
+
     .formattedTextBox-cont {
-        background:yellow;
+        background: $light-color-secondary;
+    }
+
+    opacity: 0.99;
+    border: 0px solid transparent;
+    border-radius: $border-radius;
+    box-sizing: border-box;
+    position:absolute;
+    overflow: hidden;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+
+    .collectionfreeformview {
+        .formattedTextBox-cont {
+            background: yellow;
+        }
     }
-  }
 }
 
 // selection border...?
 .border {
-  border-style: solid;
-  box-sizing: border-box;
-  width: 98%;
-  height: 98%;
-  border-radius: $border-radius;
+    border-style: solid;
+    box-sizing: border-box;
+    width: 98%;
+    height: 98%;
+    border-radius: $border-radius;
 }
 
 //this is an animation for the blinking cursor!
 @keyframes blink {
-  0% {
-    opacity: 0;
-  }
-  49% {
-    opacity: 0;
-  }
-  50% {
-    opacity: 1;
-  }
+    0% {
+        opacity: 0;
+    }
+
+    49% {
+        opacity: 0;
+    }
+
+    50% {
+        opacity: 1;
+    }
 }
 
 #prevCursor {
-  animation: blink 1s infinite;
-}
+    animation: blink 1s infinite;
+}
\ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 1feb30db1..4562fd8a7 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -206,6 +206,7 @@ export class CollectionFreeFormView extends CollectionSubView {
         const newPanY = Math.min((1 - 1 / x1) * this.nativeHeight, Math.max(0, panY));
         this.props.Document.SetNumber(KeyStore.PanX, this.isAnnotationOverlay ? newPanX : panX);
         this.props.Document.SetNumber(KeyStore.PanY, this.isAnnotationOverlay ? newPanY : panY);
+
     }
 
     @action
@@ -249,10 +250,16 @@ export class CollectionFreeFormView extends CollectionSubView {
     }
 
     focusDocument = (doc: Document) => {
+        this.props.Document.SetText(KeyStore.PanTransformType, "Ease");
         let x = doc.GetNumber(KeyStore.X, 0) + doc.GetNumber(KeyStore.Width, 0) / 2;
         let y = doc.GetNumber(KeyStore.Y, 0) + doc.GetNumber(KeyStore.Height, 0) / 2;
         this.SetPan(x, y);
         this.props.focus(this.props.Document);
+        //     if(this.props.Document.GetText(KeyStore.PanTransformType, "") === "Ease") {
+        //         setTimeout(function(){
+        //              this.props.Document.SetText(KeyStore.PanTransformType, "None");
+        //         }.bind(this),5000);  // wait 5 seconds, then reset to false
+        //    }
     }
 
     getDocumentViewProps(document: Document): DocumentViewProps {
@@ -311,6 +318,12 @@ export class CollectionFreeFormView extends CollectionSubView {
         const panx: number = -this.props.Document.GetNumber(KeyStore.PanX, 0);
         const pany: number = -this.props.Document.GetNumber(KeyStore.PanY, 0);
 
+        if (this.props.Document.GetText(KeyStore.PanTransformType, "") === "Ease") {
+            var freeformclass = "collectionfreeformview-ease";
+        } else {
+            var freeformclass = "collectionfreeformview-none";
+        }
+
         return (
             <Measure onResize={(r: any) => runInAction(() => { this._pwidth = r.entry.width; this._pheight = r.entry.height })}>
                 {({ measureRef }) => (
@@ -324,7 +337,7 @@ export class CollectionFreeFormView extends CollectionSubView {
                                 getContainerTransform={this.getContainerTransform} getTransform={this.getTransform}>
                                 <PreviewCursor container={this} addLiveTextDocument={this.addLiveTextBox}
                                     getContainerTransform={this.getContainerTransform} getTransform={this.getTransform} >
-                                    <div className="collectionfreeformview" ref={this._canvasRef}
+                                    <div className={freeformclass} ref={this._canvasRef}
                                         style={{ transform: `translate(${dx}px, ${dy}px) scale(${this.zoomScaling}, ${this.zoomScaling}) translate(${panx}px, ${pany}px)` }}>
                                         {this.backgroundView}
                                         <CollectionFreeFormLinksView {...this.props}>
diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx
index ca1b97eba..396f5f577 100644
--- a/src/client/views/nodes/LinkBox.tsx
+++ b/src/client/views/nodes/LinkBox.tsx
@@ -54,6 +54,7 @@ export class LinkBox extends React.Component<Props> {
                             }
                             let contextView = DocumentManager.Instance.getDocumentView(contextDoc);
                             if (contextView) {
+                                contextDoc.SetText(KeyStore.PanTransformType, "Ease");
                                 contextView.props.focus(contextDoc);
                             } else {
                                 CollectionDockingView.Instance.AddRightSplit(contextDoc);
diff --git a/src/fields/KeyStore.ts b/src/fields/KeyStore.ts
index 425408273..3a57d0f0a 100644
--- a/src/fields/KeyStore.ts
+++ b/src/fields/KeyStore.ts
@@ -47,6 +47,7 @@ export namespace KeyStore {
     export const Workspaces = new Key("Workspaces");
     export const Minimized = new Key("Minimized");
     export const CopyDraggedItems = new Key("CopyDraggedItems");
+    export const PanTransformType = new Key("PanTransformType");
 
     export const KeyList: Key[] = [Prototype, X, Y, Page, Title, Author, PanX, PanY, Scale, NativeWidth, NativeHeight,
         Width, Height, ZIndex, Data, Annotations, ViewType, Layout, BackgroundColor, BackgroundLayout, OverlayLayout, LayoutKeys,
-- 
cgit v1.2.3-70-g09d2


From f01b842a5d6ef6b9deb9807fa0c3a8cd2c81a25a Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Fri, 26 Apr 2019 17:08:38 -0400
Subject: TreeView and others

---
 src/client/documents/Documents.ts                  |  3 +-
 src/client/views/collections/CollectionView.tsx    |  9 ++-
 .../collections/collectionFreeForm/MarqueeView.tsx | 80 +++++++++++-----------
 src/client/views/nodes/LinkBox.tsx                 | 77 +++++++++------------
 src/new_fields/Doc.ts                              |  2 +-
 src/new_fields/InkField.ts                         |  7 +-
 src/new_fields/Types.ts                            |  4 ++
 7 files changed, 91 insertions(+), 91 deletions(-)

(limited to 'src/client/views/nodes/LinkBox.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index ed76f32ff..9511027d3 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -29,11 +29,12 @@ import { Cast } from "../../new_fields/Types";
 import { IconField } from "../../new_fields/IconField";
 import { listSpec } from "../../new_fields/Schema";
 import { DocServer } from "../DocServer";
+import { StrokeData, InkField } from "../../new_fields/InkField";
 
 export interface DocumentOptions {
     x?: number;
     y?: number;
-    // ink?: Map<string, StrokeData>;
+    ink?: InkField;
     width?: number;
     height?: number;
     nativeWidth?: number;
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 675e720e2..e7bf1e121 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -7,7 +7,6 @@ import { CollectionDockingView } from './CollectionDockingView';
 import { CollectionTreeView } from './CollectionTreeView';
 import { ContextMenu } from '../ContextMenu';
 import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils';
-import { KeyStore } from '../../../fields/KeyStore';
 import { observer } from 'mobx-react';
 import { undoBatch } from '../../util/UndoManager';
 import { trace } from 'mobx';
@@ -29,13 +28,13 @@ 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?
+    get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldKey === "annotations"; } // bcz: ? Why do we need to compare Id's?
 
     onContextMenu = (e: React.MouseEvent): void => {
         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)) });
+            ContextMenu.Instance.addItem({ description: "Freeform", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Freeform) });
+            ContextMenu.Instance.addItem({ description: "Schema", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Schema) });
+            ContextMenu.Instance.addItem({ description: "Treeview", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Tree) });
         }
     }
 
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index c6681e014..644a8784c 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -1,10 +1,6 @@
 import { action, computed, observable } from "mobx";
 import { observer } from "mobx-react";
-import { Document } from "../../../../fields/Document";
-import { FieldWaiting } from "../../../../fields/Field";
-import { InkField, StrokeData } from "../../../../fields/InkField";
-import { KeyStore } from "../../../../fields/KeyStore";
-import { Documents } from "../../../documents/Documents";
+import { Docs } from "../../../documents/Documents";
 import { SelectionManager } from "../../../util/SelectionManager";
 import { Transform } from "../../../util/Transform";
 import { undoBatch } from "../../../util/UndoManager";
@@ -14,16 +10,19 @@ import { CollectionFreeFormView } from "./CollectionFreeFormView";
 import "./MarqueeView.scss";
 import React = require("react");
 import { Utils } from "../../../../Utils";
+import { Doc } from "../../../../new_fields/Doc";
+import { NumCast, Cast } from "../../../../new_fields/Types";
+import { InkField, StrokeData } from "../../../../new_fields/InkField";
 
 interface MarqueeViewProps {
     getContainerTransform: () => Transform;
     getTransform: () => Transform;
     container: CollectionFreeFormView;
-    addDocument: (doc: Document, allowDuplicates: false) => boolean;
-    activeDocuments: () => Document[];
-    selectDocuments: (docs: Document[]) => void;
-    removeDocument: (doc: Document) => boolean;
-    addLiveTextDocument: (doc: Document) => void;
+    addDocument: (doc: Doc, allowDuplicates: false) => boolean;
+    activeDocuments: () => Doc[];
+    selectDocuments: (docs: Doc[]) => void;
+    removeDocument: (doc: Doc) => boolean;
+    addLiveTextDocument: (doc: Doc) => void;
 }
 
 @observer
@@ -49,7 +48,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
     onKeyPress = (e: KeyboardEvent) => {
         //make textbox and add it to this collection
         let [x, y] = this.props.getTransform().transformPoint(this._downX, this._downY);
-        let newBox = Documents.TextDocument({ width: 200, height: 100, x: x, y: y, title: "-typed text-" });
+        let newBox = Docs.TextDocument({ width: 200, height: 100, x: x, y: y, title: "-typed text-" });
         this.props.addLiveTextDocument(newBox);
         e.stopPropagation();
     }
@@ -64,8 +63,9 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             document.addEventListener("pointerup", this.onPointerUp, true);
             document.addEventListener("keydown", this.marqueeCommand, true);
         }
-        if (e.altKey)
+        if (e.altKey) {
             e.preventDefault();
+        }
     }
 
     @action
@@ -80,8 +80,9 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                 e.preventDefault();
             }
         }
-        if (e.altKey)
+        if (e.altKey) {
             e.preventDefault();
+        }
     }
 
     @action
@@ -94,8 +95,9 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             this.props.selectDocuments(mselect.length ? mselect : [this.props.container.props.Document]);
         }
         this.cleanupInteractions(true);
-        if (e.altKey)
+        if (e.altKey) {
             e.preventDefault();
+        }
     }
 
     @action
@@ -127,11 +129,11 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
     @undoBatch
     @action
     marqueeCommand = (e: KeyboardEvent) => {
-        if (e.key === "Backspace" || e.key === "Delete" || e.key == "d") {
+        if (e.key === "Backspace" || e.key === "Delete" || e.key === "d") {
             this.marqueeSelect().map(d => this.props.removeDocument(d));
-            let ink = this.props.container.props.Document.GetT(KeyStore.Ink, InkField);
-            if (ink && ink !== FieldWaiting) {
-                this.marqueeInkDelete(ink.Data);
+            let ink = Cast(this.props.container.props.Document.ink, InkField);
+            if (ink) {
+                this.marqueeInkDelete(ink.inkData);
             }
             this.cleanupInteractions(true);
             e.stopPropagation();
@@ -141,33 +143,33 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             let bounds = this.Bounds;
             let selected = this.marqueeSelect().map(d => {
                 this.props.removeDocument(d);
-                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.x = NumCast(d.X) - bounds.left - bounds.width / 2;
+                d.y = NumCast(d.Y) - bounds.top - bounds.height / 2;
+                d.page = -1;
                 return d;
             });
-            let ink = this.props.container.props.Document.GetT(KeyStore.Ink, InkField);
-            let inkData = ink && ink !== FieldWaiting ? ink.Data : undefined;
-            let zoomBasis = this.props.container.props.Document.GetNumber(KeyStore.Scale, 1);
-            let newCollection = Documents.FreeformDocument(selected, {
+            let ink = Cast(this.props.container.props.Document.ink, InkField);
+            let inkData = ink ? ink.inkData : undefined;
+            let zoomBasis = NumCast(this.props.container.props.Document.scale, 1);
+            let newCollection = Docs.FreeformDocument(selected, {
                 x: bounds.left,
                 y: bounds.top,
-                panx: 0,
-                pany: 0,
+                panX: 0,
+                panY: 0,
                 borderRounding: e.key === "e" ? -1 : undefined,
                 backgroundColor: selected.length ? "white" : "",
                 scale: zoomBasis,
                 width: bounds.width * zoomBasis,
                 height: bounds.height * zoomBasis,
-                ink: inkData ? this.marqueeInkSelect(inkData) : undefined,
+                ink: inkData ? new InkField(this.marqueeInkSelect(inkData)) : undefined,
                 title: "a nested collection"
             });
 
             this.marqueeInkDelete(inkData);
             SelectionManager.DeselectAll();
             if (e.key === "r") {
-                let summary = Documents.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" });
-                summary.GetPrototype()!.CreateLink(newCollection.GetPrototype()!);
+                let summary = Docs.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" });
+                Doc.MakeLink(summary.proto!, newCollection.proto!);
                 this.props.addLiveTextDocument(summary);
                 e.preventDefault();
             }
@@ -182,9 +184,9 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             let bounds = this.Bounds;
             let selected = this.marqueeSelect();
             SelectionManager.DeselectAll();
-            let summary = Documents.TextDocument({ x: bounds.left + bounds.width + 25, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" });
+            let summary = Docs.TextDocument({ x: bounds.left + bounds.width + 25, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" });
             this.props.addLiveTextDocument(summary);
-            selected.map(select => summary.GetPrototype()!.CreateLink(select.GetPrototype()!));
+            selected.forEach(select => Doc.MakeLink(summary.proto!, select.proto!));
 
             this.cleanupInteractions(true);
         }
@@ -219,19 +221,19 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             let idata = new Map();
             ink.forEach((value: StrokeData, key: string, map: any) =>
                 !InkingCanvas.IntersectStrokeRect(value, this.Bounds) && idata.set(key, value));
-            this.props.container.props.Document.SetDataOnPrototype(KeyStore.Ink, idata, InkField);
+            Doc.SetOnPrototype(this.props.container.props.Document, "ink", new InkField(idata));
         }
     }
 
     marqueeSelect() {
         let selRect = this.Bounds;
-        let selection: Document[] = [];
+        let selection: Doc[] = [];
         this.props.activeDocuments().map(doc => {
-            var z = doc.GetNumber(KeyStore.ZoomBasis, 1);
-            var x = doc.GetNumber(KeyStore.X, 0);
-            var y = doc.GetNumber(KeyStore.Y, 0);
-            var w = doc.Width() / z;
-            var h = doc.Height() / z;
+            var z = NumCast(doc.zoomBasis, 1);
+            var x = NumCast(doc.x);
+            var y = NumCast(doc.y);
+            var w = NumCast(doc.width) / z;
+            var h = NumCast(doc.height) / z;
             if (this.intersectRect({ left: x, top: y, width: w, height: h }, selRect)) {
                 selection.push(doc);
             }
diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx
index 1c0e316e8..9bb90de0d 100644
--- a/src/client/views/nodes/LinkBox.tsx
+++ b/src/client/views/nodes/LinkBox.tsx
@@ -2,15 +2,14 @@ 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 { 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 { undoBatch } from "../../util/UndoManager";
 import { CollectionDockingView } from "../collections/CollectionDockingView";
 import './LinkBox.scss';
 import React = require("react");
+import { Doc } from '../../../new_fields/Doc';
+import { Cast, NumCast } from '../../../new_fields/Types';
+import { listSpec } from '../../../new_fields/Schema';
 
 
 library.add(faEye);
@@ -18,9 +17,9 @@ library.add(faEdit);
 library.add(faTimes);
 
 interface Props {
-    linkDoc: Document;
+    linkDoc: Doc;
     linkName: String;
-    pairedDoc: Document;
+    pairedDoc: Doc;
     type: String;
     showEditor: () => void;
 }
@@ -29,62 +28,52 @@ interface Props {
 export class LinkBox extends React.Component<Props> {
 
     @undoBatch
-    onViewButtonPressed = (e: React.PointerEvent): void => {
+    onViewButtonPressed = async (e: React.PointerEvent): Promise<void> => {
         e.stopPropagation();
         let docView = DocumentManager.Instance.getDocumentView(this.props.pairedDoc);
         if (docView) {
             docView.props.focus(docView.props.Document);
         } else {
-            this.props.pairedDoc.GetAsync(KeyStore.AnnotationOn, (contextDoc: any) => {
-                if (!contextDoc) {
-                    CollectionDockingView.Instance.AddRightSplit(this.props.pairedDoc.MakeDelegate());
-                } else if (contextDoc instanceof Document) {
-                    this.props.pairedDoc.GetTAsync(KeyStore.Page, NumberField).then((pfield: any) => {
-                        contextDoc.GetTAsync(KeyStore.CurPage, NumberField).then((cfield: any) => {
-                            if (pfield !== cfield) {
-                                contextDoc.SetNumber(KeyStore.CurPage, pfield.Data);
-                            }
-                            let contextView = DocumentManager.Instance.getDocumentView(contextDoc);
-                            if (contextView) {
-                                contextView.props.focus(contextDoc);
-                            } else {
-                                CollectionDockingView.Instance.AddRightSplit(contextDoc);
-                            }
-                        });
-                    });
+            const contextDoc = await Cast(this.props.pairedDoc.annotationOn, Doc);
+            if (!contextDoc) {
+                CollectionDockingView.Instance.AddRightSplit(Doc.MakeDelegate(this.props.pairedDoc));
+            } else {
+                const page = NumCast(this.props.pairedDoc.page, undefined);
+                const curPage = NumCast(contextDoc.curPage, undefined);
+                if (page !== curPage) {
+                    contextDoc.curPage = page;
                 }
-            });
+                let contextView = DocumentManager.Instance.getDocumentView(contextDoc);
+                if (contextView) {
+                    contextView.props.focus(contextDoc);
+                } else {
+                    CollectionDockingView.Instance.AddRightSplit(contextDoc);
+                }
+            }
         }
     }
 
     onEditButtonPressed = (e: React.PointerEvent): void => {
-        console.log("edit down");
         e.stopPropagation();
 
         this.props.showEditor();
     }
 
-    onDeleteButtonPressed = (e: React.PointerEvent): void => {
-        console.log("delete down");
+    onDeleteButtonPressed = async (e: React.PointerEvent): Promise<void> => {
         e.stopPropagation();
-        this.props.linkDoc.GetTAsync(KeyStore.LinkedFromDocs, Document, field => {
-            if (field) {
-                field.GetTAsync<ListField<Document>>(KeyStore.LinkedToDocs, ListField, field => {
-                    if (field) {
-                        field.Data.splice(field.Data.indexOf(this.props.linkDoc));
-                    }
-                });
+        const [linkedFrom, linkedTo] = await Promise.all([Cast(this.props.linkDoc.linkedFrom, Doc), Cast(this.props.linkDoc.linkedTo, Doc)]);
+        if (linkedFrom) {
+            const linkedToDocs = Cast(linkedFrom.linkedToDocs, listSpec(Doc));
+            if (linkedToDocs) {
+                linkedToDocs.splice(linkedToDocs.indexOf(this.props.linkDoc));
             }
-        });
-        this.props.linkDoc.GetTAsync(KeyStore.LinkedToDocs, Document, field => {
-            if (field) {
-                field.GetTAsync<ListField<Document>>(KeyStore.LinkedFromDocs, ListField, field => {
-                    if (field) {
-                        field.Data.splice(field.Data.indexOf(this.props.linkDoc));
-                    }
-                });
+        }
+        if (linkedTo) {
+            const linkedFromDocs = Cast(linkedTo.linkedToDocs, listSpec(Doc));
+            if (linkedFromDocs) {
+                linkedFromDocs.splice(linkedFromDocs.indexOf(this.props.linkDoc));
             }
-        });
+        }
     }
 
     render() {
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 79e5a156d..a5f495477 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -91,7 +91,7 @@ export namespace Doc {
         return Cast(Get(doc, key, ignoreProto), ctor) as T | null | undefined;
     }
     export async function SetOnPrototype(doc: Doc, key: string, value: Field) {
-        const proto = await Cast(doc.proto, Doc);
+        const proto = doc.proto;
         if (proto) {
             proto[key] = value;
         }
diff --git a/src/new_fields/InkField.ts b/src/new_fields/InkField.ts
index cdb34cedf..49e6bf61e 100644
--- a/src/new_fields/InkField.ts
+++ b/src/new_fields/InkField.ts
@@ -27,5 +27,10 @@ const strokeDataSchema = createSimpleSchema({
 
 export class InkField extends ObjectField {
     @serializable(map(object(strokeDataSchema)))
-    readonly inkData: Map<string, StrokeData> = new Map;
+    readonly inkData: Map<string, StrokeData>;
+
+    constructor(data?: Map<string, StrokeData>) {
+        super();
+        this.inkData = data || new Map;
+    }
 }
diff --git a/src/new_fields/Types.ts b/src/new_fields/Types.ts
index 079c7b76d..649dfdc3e 100644
--- a/src/new_fields/Types.ts
+++ b/src/new_fields/Types.ts
@@ -67,6 +67,10 @@ export function StrCast(field: FieldResult, defaultVal: Opt<string> = "") {
     return Cast(field, "string", defaultVal);
 }
 
+export function BoolCast(field: FieldResult, defaultVal: Opt<boolean> = undefined) {
+    return Cast(field, "boolean", defaultVal);
+}
+
 type WithoutList<T extends Field> = T extends List<infer R> ? R[] : T;
 
 export function FieldValue<T extends Field, U extends WithoutList<T>>(field: Opt<T> | Promise<Opt<T>>, defaultValue: U): WithoutList<T>;
-- 
cgit v1.2.3-70-g09d2


From 97ed2e452597d5f1f2e8d0abfc06e94b4aa5d448 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 30 Apr 2019 22:03:30 -0400
Subject: fixed template button

---
 src/client/views/DocumentDecorations.scss |  3 +--
 src/client/views/nodes/LinkBox.tsx        | 23 +++++++++++++----------
 2 files changed, 14 insertions(+), 12 deletions(-)

(limited to 'src/client/views/nodes/LinkBox.tsx')

diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss
index b00b48c9e..ecddb8b06 100644
--- a/src/client/views/DocumentDecorations.scss
+++ b/src/client/views/DocumentDecorations.scss
@@ -207,8 +207,6 @@ $linkGap : 3px;
     bottom: 0;
     left: 50px;
     pointer-events: auto;
-    background-color: $dark-color;
-    color: $light-color;
     text-transform: uppercase;
     letter-spacing: 2px;
     font-size: 75%;
@@ -227,6 +225,7 @@ $linkGap : 3px;
     height: 20px;
     border-radius: 50%;
     opacity: 0.9;
+    font-size:14;
     background-color: $dark-color;
     color: $light-color;
     text-align: center;
diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx
index 89c06e7b3..8f979fdd7 100644
--- a/src/client/views/nodes/LinkBox.tsx
+++ b/src/client/views/nodes/LinkBox.tsx
@@ -11,6 +11,7 @@ import { undoBatch } from "../../util/UndoManager";
 import { CollectionDockingView } from "../collections/CollectionDockingView";
 import './LinkBox.scss';
 import React = require("react");
+import { runInAction } from 'mobx';
 
 
 library.add(faEye);
@@ -70,20 +71,22 @@ export class LinkBox extends React.Component<Props> {
         e.stopPropagation();
         this.props.linkDoc.GetTAsync(KeyStore.LinkedFromDocs, Document, field => {
             if (field) {
-                field.GetTAsync<ListField<Document>>(KeyStore.LinkedToDocs, ListField, field => {
-                    if (field) {
-                        field.Data.splice(field.Data.indexOf(this.props.linkDoc));
-                    }
-                });
+                field.GetTAsync<ListField<Document>>(KeyStore.LinkedToDocs, ListField, field =>
+                    runInAction(() => {
+                        if (field) {
+                            field.Data.splice(field.Data.indexOf(this.props.linkDoc));
+                        }
+                    }));
             }
         });
         this.props.linkDoc.GetTAsync(KeyStore.LinkedToDocs, Document, field => {
             if (field) {
-                field.GetTAsync<ListField<Document>>(KeyStore.LinkedFromDocs, ListField, field => {
-                    if (field) {
-                        field.Data.splice(field.Data.indexOf(this.props.linkDoc));
-                    }
-                });
+                field.GetTAsync<ListField<Document>>(KeyStore.LinkedFromDocs, ListField, field =>
+                    runInAction(() => {
+                        if (field) {
+                            field.Data.splice(field.Data.indexOf(this.props.linkDoc));
+                        }
+                    }));
             }
         });
     }
-- 
cgit v1.2.3-70-g09d2


From a9b457e06990ec1c2faf8ea32ba47e9377a25fea Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Thu, 2 May 2019 21:36:32 -0400
Subject: fixed link removal

---
 src/client/views/nodes/LinkBox.tsx | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'src/client/views/nodes/LinkBox.tsx')

diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx
index b1e7fd6d7..08cfa590b 100644
--- a/src/client/views/nodes/LinkBox.tsx
+++ b/src/client/views/nodes/LinkBox.tsx
@@ -68,13 +68,13 @@ export class LinkBox extends React.Component<Props> {
         if (linkedFrom) {
             const linkedToDocs = Cast(linkedFrom.linkedToDocs, listSpec(Doc));
             if (linkedToDocs) {
-                linkedToDocs.splice(linkedToDocs.indexOf(this.props.linkDoc));
+                linkedToDocs.splice(linkedToDocs.indexOf(this.props.linkDoc), 1);
             }
         }
         if (linkedTo) {
-            const linkedFromDocs = Cast(linkedTo.linkedToDocs, listSpec(Doc));
+            const linkedFromDocs = Cast(linkedTo.linkedFromDocs, listSpec(Doc));
             if (linkedFromDocs) {
-                linkedFromDocs.splice(linkedFromDocs.indexOf(this.props.linkDoc));
+                linkedFromDocs.splice(linkedFromDocs.indexOf(this.props.linkDoc), 1);
             }
         }
     }
-- 
cgit v1.2.3-70-g09d2

