From 4f1f20a52a5c01b3046a56f37b6c7c029d3e10f0 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 13 Mar 2019 15:17:53 -0400
Subject: fixed a variety of things related to selection, dragging, marqueeing

---
 src/client/views/collections/MarqueeView.tsx | 135 +++++++++++++++++++++++++++
 1 file changed, 135 insertions(+)
 create mode 100644 src/client/views/collections/MarqueeView.tsx

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

diff --git a/src/client/views/collections/MarqueeView.tsx b/src/client/views/collections/MarqueeView.tsx
new file mode 100644
index 000000000..d9e4df1e9
--- /dev/null
+++ b/src/client/views/collections/MarqueeView.tsx
@@ -0,0 +1,135 @@
+import { action, IReactionDisposer, observable, reaction } from "mobx";
+import { observer } from "mobx-react";
+import { Document } from "../../../fields/Document";
+import { FieldWaiting, Opt } from "../../../fields/Field";
+import { KeyStore } from "../../../fields/KeyStore";
+import { ListField } from "../../../fields/ListField";
+import { Documents } from "../../documents/Documents";
+import { SelectionManager } from "../../util/SelectionManager";
+import { Transform } from "../../util/Transform";
+import { CollectionFreeFormView } from "./CollectionFreeFormView";
+import "./MarqueeView.scss";
+import React = require("react");
+
+
+interface MarqueeViewProps {
+    getMarqueeTransform: () => Transform;
+    getTransform: () => Transform;
+    container: CollectionFreeFormView;
+    addDocument: (doc: Document) => void;
+    activeDocuemnts: () => Document[];
+    selectDocuments: (docs: Document[]) => void;
+    removeDocument: (doc: Document) => boolean;
+}
+
+@observer
+export class MarqueeView extends React.Component<MarqueeViewProps>
+{
+    private _reactionDisposer: Opt<IReactionDisposer>;
+
+    @observable _lastX: number = 0;
+    @observable _lastY: number = 0;
+    @observable _downX: number = 0;
+    @observable _downY: number = 0;
+
+    componentDidMount() {
+        this._reactionDisposer = reaction(
+            () => this.props.container.MarqueeVisible,
+            (visible: boolean) => this.onPointerDown(visible, this.props.container.DownX, this.props.container.DownY))
+    }
+    componentWillUnmount() {
+        if (this._reactionDisposer) {
+            this._reactionDisposer();
+        }
+        this.cleanupInteractions();
+    }
+
+    @action
+    cleanupInteractions = () => {
+        document.removeEventListener("pointermove", this.onPointerMove, true)
+        document.removeEventListener("pointerup", this.onPointerUp, true);
+        document.removeEventListener("keydown", this.marqueeCommand, true);
+    }
+
+    @action
+    onPointerDown = (visible: boolean, downX: number, downY: number): void => {
+        if (visible) {
+            this._downX = this._lastX = downX;
+            this._downY = this._lastY = downY;
+            document.addEventListener("pointermove", this.onPointerMove, true)
+            document.addEventListener("pointerup", this.onPointerUp, true);
+            document.addEventListener("keydown", this.marqueeCommand, true);
+        }
+    }
+
+    @action
+    onPointerMove = (e: PointerEvent): void => {
+        this._lastX = e.pageX;
+        this._lastY = e.pageY;
+    }
+
+    @action
+    onPointerUp = (e: PointerEvent): void => {
+        this.cleanupInteractions();
+        if (!e.shiftKey) {
+            SelectionManager.DeselectAll();
+        }
+        this.props.selectDocuments(this.marqueeSelect());
+    }
+
+    intersectRect(r1: { left: number, top: number, width: number, height: number },
+        r2: { left: number, top: number, width: number, height: number }) {
+        return !(r2.left > r1.left + r1.width || r2.left + r2.width < r1.left || r2.top > r1.top + r1.height || r2.top + r2.height < r1.top);
+    }
+
+    get Bounds() {
+        let left = this._downX < this._lastX ? this._downX : this._lastX;
+        let top = this._downY < this._lastY ? this._downY : this._lastY;
+        let topLeft = this.props.getTransform().transformPoint(left, top);
+        let size = this.props.getTransform().transformDirection(this._lastX - this._downX, this._lastY - this._downY);
+        return { left: topLeft[0], top: topLeft[1], width: Math.abs(size[0]), height: Math.abs(size[1]) }
+    }
+
+    @action
+    marqueeCommand = (e: KeyboardEvent) => {
+        if (e.key == "Backspace") {
+            this.marqueeSelect().map(d => this.props.removeDocument(d));
+            this.cleanupInteractions();
+        }
+        if (e.key == "c") {
+            let bounds = this.Bounds;
+            let selected = this.marqueeSelect().map(m => m);
+            this.marqueeSelect().map(d => this.props.removeDocument(d));
+            //setTimeout(() => {
+            this.props.addDocument(Documents.FreeformDocument(selected.map(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, 0);
+                d.SetText(KeyStore.Title, "" + d.GetNumber(KeyStore.Width, 0) + " " + d.GetNumber(KeyStore.Height, 0));
+                return d;
+            }), { x: bounds.left, y: bounds.top, panx: 0, pany: 0, width: bounds.width, height: bounds.height, title: "a nested collection" }));
+            // }, 100);
+            this.cleanupInteractions();
+        }
+    }
+
+    marqueeSelect() {
+        let selRect = this.Bounds;
+        let selection: Document[] = [];
+        this.props.activeDocuemnts().map(doc => {
+            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);
+            if (this.intersectRect({ left: x, top: y, width: w, height: h }, selRect))
+                selection.push(doc)
+        })
+        return selection;
+    }
+
+    render() {
+        let p = this.props.getMarqueeTransform().transformPoint(this._downX < this._lastX ? this._downX : this._lastX, this._downY < this._lastY ? this._downY : this._lastY);
+        let v = this.props.getMarqueeTransform().transformDirection(this._lastX - this._downX, this._lastY - this._downY);
+        return (!this.props.container.MarqueeVisible ? (null) : <div className="marqueeView" style={{ transform: `translate(${p[0]}px, ${p[1]}px)`, width: `${Math.abs(v[0])}`, height: `${Math.abs(v[1])}` }} />);
+    }
+}
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From f089e10dfd42edc395729a6b71e42385745f364e Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Thu, 14 Mar 2019 22:21:16 -0400
Subject: marquees can now delete ink or move it to a new collection.

---
 src/client/documents/Documents.ts                  |  3 ++
 src/client/views/InkingCanvas.scss                 |  3 +-
 src/client/views/InkingCanvas.tsx                  | 22 +++++-----
 src/client/views/InkingStroke.tsx                  |  2 -
 src/client/views/Main.tsx                          |  2 +-
 .../views/collections/CollectionFreeFormView.tsx   |  4 +-
 .../views/collections/CollectionVideoView.tsx      |  6 +--
 src/client/views/collections/MarqueeView.tsx       | 47 +++++++++++++++++-----
 8 files changed, 63 insertions(+), 26 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 4e0eefcc6..8402118b8 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -24,10 +24,12 @@ import { PDFBox } from "../views/nodes/PDFBox";
 import { CollectionPDFView } from "../views/collections/CollectionPDFView";
 import { RichTextField } from "../../fields/RichTextField";
 import { CollectionVideoView } from "../views/collections/CollectionVideoView";
+import { StrokeData, InkField } from "../../fields/InkField";
 
 export interface DocumentOptions {
     x?: number;
     y?: number;
+    ink?: Map<string, StrokeData>;
     width?: number;
     height?: number;
     nativeWidth?: number;
@@ -87,6 +89,7 @@ export namespace Documents {
         if (options.backgroundColor !== undefined) { doc.SetText(KeyStore.BackgroundColor, options.backgroundColor); }
         if (options.layout !== undefined) { doc.SetText(KeyStore.Layout, options.layout); }
         if (options.layoutKeys !== undefined) { doc.Set(KeyStore.LayoutKeys, new ListField(options.layoutKeys)); }
+        if (options.ink !== undefined) { doc.Set(KeyStore.Ink, new InkField(options.ink)); }
         return doc;
     }
     function setupPrototypeOptions(protoId: string, title: string, layout: string, options: DocumentOptions): Document {
diff --git a/src/client/views/InkingCanvas.scss b/src/client/views/InkingCanvas.scss
index f654b194b..37fa3143d 100644
--- a/src/client/views/InkingCanvas.scss
+++ b/src/client/views/InkingCanvas.scss
@@ -1,8 +1,9 @@
 .inking-canvas {
-    position: fixed;
+    position: absolute;
     top: -50000px;
     left: -50000px; // z-index: 99; //overlays ink on top of everything
     svg {
+        position:absolute;
         width: 100000px;
         height: 100000px;
         .highlight {
diff --git a/src/client/views/InkingCanvas.tsx b/src/client/views/InkingCanvas.tsx
index 064d1cba2..84c47f616 100644
--- a/src/client/views/InkingCanvas.tsx
+++ b/src/client/views/InkingCanvas.tsx
@@ -1,4 +1,5 @@
 import { observer } from "mobx-react";
+import { observable } from "mobx";
 import { action, computed } from "mobx";
 import { InkingControl } from "./InkingControl";
 import React = require("react");
@@ -6,14 +7,10 @@ import { Transform } from "../util/Transform";
 import { Document } from "../../fields/Document";
 import { KeyStore } from "../../fields/KeyStore";
 import { InkField, InkTool, StrokeData, StrokeMap } from "../../fields/InkField";
-import { JsxArgs } from "./nodes/DocumentView";
 import { InkingStroke } from "./InkingStroke";
 import "./InkingCanvas.scss"
-import { CollectionDockingView } from "./collections/CollectionDockingView";
 import { Utils } from "../../Utils";
 import { FieldWaiting } from "../../fields/Field";
-import { getMapLikeKeys } from "mobx/lib/internal";
-
 
 interface InkCanvasProps {
     getScreenTransform: () => Transform;
@@ -22,7 +19,16 @@ interface InkCanvasProps {
 
 @observer
 export class InkingCanvas extends React.Component<InkCanvasProps> {
-
+    static InkOffset: number = 50000;
+    public static IntersectStrokeRect(stroke: StrokeData, selRect: { left: number, top: number, width: number, height: number }): boolean {
+        let inside = false;
+        stroke.pathData.map(val => {
+            if (selRect.left < val.x - InkingCanvas.InkOffset && selRect.left + selRect.width > val.x - InkingCanvas.InkOffset &&
+                selRect.top < val.y - InkingCanvas.InkOffset && selRect.top + selRect.height > val.y - InkingCanvas.InkOffset)
+                inside = true;
+        });
+        return inside
+    }
     private _isDrawing: boolean = false;
     private _idGenerator: string = "";
 
@@ -51,7 +57,6 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
         document.removeEventListener("mouseup", this.handleMouseUp);
     }
 
-
     @action
     handleMouseDown = (e: React.PointerEvent): void => {
         if (e.button != 0 ||
@@ -62,7 +67,6 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
         if (InkingControl.Instance.selectedTool === InkTool.Eraser) {
             return
         }
-        e.stopPropagation()
         const point = this.relativeCoordinatesForEvent(e);
 
         // start the new line, saves a uuid to represent the field of the stroke
@@ -110,8 +114,8 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
 
     relativeCoordinatesForEvent = (e: React.MouseEvent): { x: number, y: number } => {
         let [x, y] = this.props.getScreenTransform().transformPoint(e.clientX, e.clientY);
-        x += 50000
-        y += 50000
+        x += InkingCanvas.InkOffset;
+        y += InkingCanvas.InkOffset;
         return { x, y };
     }
 
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index d724421d3..87b5c43d8 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -21,8 +21,6 @@ export class InkingStroke extends React.Component<StrokeProps> {
     @observable private _strokeColor: string = this.props.color;
     @observable private _strokeWidth: string = this.props.width;
 
-    private _canvasColor: string = "#cdcdcd";
-
     deleteStroke = (e: React.MouseEvent): void => {
         if (InkingControl.Instance.selectedTool === InkTool.Eraser && e.buttons === 1) {
             this.props.deleteCallback(this.props.id);
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 8ee028076..d73e9b8fe 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -58,7 +58,7 @@ Documents.initProtos(mainDocId, (res?: Document) => {
     let videourl = "http://techslides.com/demos/sample-videos/small.mp4";
     let clearDatabase = action(() => Utils.Emit(Server.Socket, MessageStore.DeleteAll, {}))
     let addTextNode = action(() => Documents.TextDocument({ width: 200, height: 200, title: "a text note" }))
-    let addColNode = action(() => Documents.FreeformDocument([], { width: 200, height: 200, backgroundColor: "Transparent", title: "a freeform collection" }));
+    let addColNode = action(() => Documents.FreeformDocument([], { width: 200, height: 200, title: "a freeform collection" }));
     let addSchemaNode = action(() => Documents.SchemaDocument([Documents.TextDocument()], { width: 200, height: 200, title: "a schema collection" }));
     let addVideoNode = action(() => Documents.VideoDocument(videourl, { width: 200, title: "video node" }));
     let addPDFNode = action(() => Documents.PdfDocument(pdfurl, { width: 200, title: "a schema collection" }));
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index 98fb23fa4..c8b745254 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -338,7 +338,9 @@ export class CollectionFreeFormView extends CollectionViewBase {
                     <PreviewCursor container={this} addLiveTextDocument={this.addLiveTextBox} getTransform={this.getTransform} />
                     {this.views}
                 </div>
-                <MarqueeView container={this} activeDocuemnts={this.getActiveDocuments} selectDocuments={this.selectDocuments} addDocument={this.props.addDocument} removeDocument={this.props.removeDocument} getMarqueeTransform={this.getMarqueeTransform} getTransform={this.getTransform} />
+                <MarqueeView container={this} activeDocuments={this.getActiveDocuments} selectDocuments={this.selectDocuments}
+                    addDocument={this.props.addDocument} removeDocument={this.props.removeDocument}
+                    getMarqueeTransform={this.getMarqueeTransform} getTransform={this.getTransform} />
                 {this.overlayView}
             </div>
         );
diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index 0e2d250aa..b64ef3c07 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -24,14 +24,14 @@ export class CollectionVideoView extends React.Component<CollectionViewProps> {
     private get uIButtons() {
         let scaling = Math.min(1.8, this.props.ScreenToLocalTransform().transformDirection(1, 1)[0]);
         return ([
-            <div className="collectionVideoView-time" onPointerDown={this.onResetDown} style={{ transform: `scale(${scaling}, ${scaling})` }}>
+            <div className="collectionVideoView-time" key="time" onPointerDown={this.onResetDown} style={{ transform: `scale(${scaling}, ${scaling})` }}>
                 <span>{"" + Math.round(this.ctime)}</span>
                 <span style={{ fontSize: 8 }}>{" " + Math.round((this.ctime - Math.trunc(this.ctime)) * 100)}</span>
             </div>,
-            <div className="collectionVideoView-play" onPointerDown={this.onPlayDown} style={{ transform: `scale(${scaling}, ${scaling})` }}>
+            <div className="collectionVideoView-play" key="play" onPointerDown={this.onPlayDown} style={{ transform: `scale(${scaling}, ${scaling})` }}>
                 {this.playing ? "\"" : ">"}
             </div>,
-            <div className="collectionVideoView-full" onPointerDown={this.onFullDown} style={{ transform: `scale(${scaling}, ${scaling})` }}>
+            <div className="collectionVideoView-full" key="full" onPointerDown={this.onFullDown} style={{ transform: `scale(${scaling}, ${scaling})` }}>
                 F
                 </div>
         ]);
diff --git a/src/client/views/collections/MarqueeView.tsx b/src/client/views/collections/MarqueeView.tsx
index d9e4df1e9..67716f99a 100644
--- a/src/client/views/collections/MarqueeView.tsx
+++ b/src/client/views/collections/MarqueeView.tsx
@@ -3,21 +3,22 @@ import { observer } from "mobx-react";
 import { Document } from "../../../fields/Document";
 import { FieldWaiting, Opt } from "../../../fields/Field";
 import { KeyStore } from "../../../fields/KeyStore";
-import { ListField } from "../../../fields/ListField";
 import { Documents } from "../../documents/Documents";
 import { SelectionManager } from "../../util/SelectionManager";
 import { Transform } from "../../util/Transform";
 import { CollectionFreeFormView } from "./CollectionFreeFormView";
 import "./MarqueeView.scss";
 import React = require("react");
-
+import { InkField, StrokeData } from "../../../fields/InkField";
+import { Utils } from "../../../Utils";
+import { InkingCanvas } from "../InkingCanvas";
 
 interface MarqueeViewProps {
     getMarqueeTransform: () => Transform;
     getTransform: () => Transform;
     container: CollectionFreeFormView;
     addDocument: (doc: Document) => void;
-    activeDocuemnts: () => Document[];
+    activeDocuments: () => Document[];
     selectDocuments: (docs: Document[]) => void;
     removeDocument: (doc: Document) => boolean;
 }
@@ -94,29 +95,57 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
     marqueeCommand = (e: KeyboardEvent) => {
         if (e.key == "Backspace") {
             this.marqueeSelect().map(d => this.props.removeDocument(d));
+            this.props.container.props.Document.SetData(KeyStore.Ink, this.marqueeInkSelect(false), InkField);
             this.cleanupInteractions();
         }
         if (e.key == "c") {
             let bounds = this.Bounds;
-            let selected = this.marqueeSelect().map(m => m);
-            this.marqueeSelect().map(d => this.props.removeDocument(d));
-            //setTimeout(() => {
-            this.props.addDocument(Documents.FreeformDocument(selected.map(d => {
+            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, 0);
                 d.SetText(KeyStore.Title, "" + d.GetNumber(KeyStore.Width, 0) + " " + d.GetNumber(KeyStore.Height, 0));
                 return d;
-            }), { x: bounds.left, y: bounds.top, panx: 0, pany: 0, width: bounds.width, height: bounds.height, title: "a nested collection" }));
+            });
+            let liftedInk = this.marqueeInkSelect(true);
+            this.props.container.props.Document.SetData(KeyStore.Ink, this.marqueeInkSelect(false), InkField);
+            //setTimeout(() => {
+            this.props.addDocument(Documents.FreeformDocument(selected, { x: bounds.left, y: bounds.top, panx: 0, pany: 0, width: bounds.width, backgroundColor: "Transparent", height: bounds.height, ink: liftedInk, title: "a nested collection" }));
             // }, 100);
             this.cleanupInteractions();
         }
     }
+    marqueeInkSelect(select: boolean) {
+        let selRect = this.Bounds;
+        let centerShiftX = 0 - (selRect.left + selRect.width / 2); // moves each point by the offset that shifts the selection's center to the origin.
+        let centerShiftY = 0 - (selRect.top + selRect.height / 2);
+        let ink = this.props.container.props.Document.GetT(KeyStore.Ink, InkField);
+        if (ink && ink != FieldWaiting) {
+            let idata = new Map();
+            ink.Data.forEach((value: StrokeData, key: string, map: any) => {
+                let inside = InkingCanvas.IntersectStrokeRect(value, selRect);
+                if (inside && select) {
+                    idata.set(key,
+                        {
+                            pathData: value.pathData.map(val => { return { x: val.x + centerShiftX, y: val.y + centerShiftY } }),
+                            color: value.color,
+                            width: value.width,
+                            tool: value.tool,
+                            page: -1
+                        });
+                } else if (!inside && !select) {
+                    idata.set(key, value);
+                }
+            })
+            return idata;
+        }
+    }
 
     marqueeSelect() {
         let selRect = this.Bounds;
         let selection: Document[] = [];
-        this.props.activeDocuemnts().map(doc => {
+        this.props.activeDocuments().map(doc => {
             var x = doc.GetNumber(KeyStore.X, 0);
             var y = doc.GetNumber(KeyStore.Y, 0);
             var w = doc.GetNumber(KeyStore.Width, 0);
-- 
cgit v1.2.3-70-g09d2


From 487a74d28501cbdc86f0d02fef656754ed22ae19 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 15 Mar 2019 13:30:22 -0400
Subject: fixed various issues with schema/videos

---
 src/client/views/EditableView.tsx                  |  2 +-
 .../views/collections/CollectionFreeFormView.tsx   |  6 ++---
 .../views/collections/CollectionSchemaView.scss    |  2 +-
 .../views/collections/CollectionSchemaView.tsx     | 28 ++++++++++++----------
 src/client/views/collections/MarqueeView.tsx       |  2 +-
 src/client/views/nodes/VideoBox.tsx                | 16 ++++++-------
 src/fields/KeyStore.ts                             |  1 +
 7 files changed, 28 insertions(+), 29 deletions(-)

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

diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index 757bfeae6..3b54c0dbb 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -50,7 +50,7 @@ export class EditableView extends React.Component<EditableProps> {
                 style={{ display: "inline" }}></input>
         } else {
             return (
-                <div className="editableView-container-editing" style={{ display: "inline", height: "100%", maxHeight: `${this.props.height}` }}
+                <div className="editableView-container-editing" style={{ display: "inline", height: "auto", maxHeight: `${this.props.height}` }}
                     onClick={action(() => this.editing = true)}>
                     {this.props.contents}
                 </div>
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index c8b745254..a94539312 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -126,7 +126,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
     onPointerUp = (e: PointerEvent): void => {
         e.stopPropagation();
 
-        if (!this.MarqueeVisible && Math.abs(this.DownX - e.clientX) < 3 && Math.abs(this.DownY - e.clientY) < 3) {
+        if (Math.abs(this.DownX - e.clientX) < 4 && Math.abs(this.DownY - e.clientY) < 4) {
             //show preview text cursor on tap
             this.PreviewCursorVisible = true;
             //select is not already selected
@@ -140,9 +140,8 @@ export class CollectionFreeFormView extends CollectionViewBase {
     @action
     onPointerMove = (e: PointerEvent): void => {
         if (!e.cancelBubble && this.props.active()) {
-            if (e.buttons != 2 && !e.altKey && !e.metaKey && !this.MarqueeVisible) {
+            if (e.buttons == 1 && !e.altKey && !e.metaKey) {
                 this.MarqueeVisible = true;
-                this.PreviewCursorVisible = false;
             }
             if (this.MarqueeVisible) {
                 e.stopPropagation();
@@ -152,7 +151,6 @@ export class CollectionFreeFormView extends CollectionViewBase {
                 let x = this.props.Document.GetNumber(KeyStore.PanX, 0);
                 let y = this.props.Document.GetNumber(KeyStore.PanY, 0);
                 let [dx, dy] = this.getTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY);
-                this.PreviewCursorVisible = false;
                 this.SetPan(x - dx, y - dy);
                 this._lastX = e.pageX;
                 this._lastY = e.pageY;
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index fdcad1355..0d615dc01 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -84,7 +84,7 @@
       }
       .videobox-cont  {
         object-fit: contain;
-        max-width: 100%;
+        width:auto;
         height: 100%;
       }
     }
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 14e1df8ca..8c1aeef2c 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -1,5 +1,5 @@
 import React = require("react")
-import { action, observable } from "mobx";
+import { action, observable, computed } from "mobx";
 import { observer } from "mobx-react";
 import Measure from "react-measure";
 import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table";
@@ -31,7 +31,7 @@ export class CollectionSchemaView extends CollectionViewBase {
     @observable _panelWidth = 0;
     @observable _panelHeight = 0;
     @observable _selectedIndex = 0;
-    @observable _splitPercentage: number = 100;
+    @computed get splitPercentage() { return this.props.Document.GetNumber(KeyStore.SchemaSplitPercentage, 0); }
 
     renderCell = (rowProps: CellInfo) => {
         let props: FieldViewProps = {
@@ -89,7 +89,8 @@ export class CollectionSchemaView extends CollectionViewBase {
         return {
             onClick: action((e: React.MouseEvent, handleOriginal: Function) => {
                 that._selectedIndex = rowInfo.index;
-                this._splitPercentage += 0.05; // bcz - ugh - needed to force Measure to do its thing and call onResize
+                // bcz - ugh - needed to force Measure to do its thing and call onResize
+                this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, this.splitPercentage - 0.05)
 
                 if (handleOriginal) {
                     handleOriginal()
@@ -106,18 +107,18 @@ export class CollectionSchemaView extends CollectionViewBase {
     @action
     onDividerMove = (e: PointerEvent): void => {
         let nativeWidth = this._mainCont.current!.getBoundingClientRect();
-        this._splitPercentage = Math.round((e.clientX - nativeWidth.left) / nativeWidth.width * 100);
+        this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, 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);
-        if (this._startSplitPercent == this._splitPercentage) {
-            this._splitPercentage = this._splitPercentage == 1 ? 66 : 100;
+        if (this._startSplitPercent == this.splitPercentage) {
+            this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, this.splitPercentage == 0 ? 33 : 0);
         }
     }
     onDividerDown = (e: React.PointerEvent) => {
-        this._startSplitPercent = this._splitPercentage;
+        this._startSplitPercent = this.splitPercentage;
         e.stopPropagation();
         e.preventDefault();
         document.addEventListener("pointermove", this.onDividerMove);
@@ -134,12 +135,12 @@ export class CollectionSchemaView extends CollectionViewBase {
         e.preventDefault();
         document.removeEventListener("pointermove", this.onExpanderMove);
         document.removeEventListener('pointerup', this.onExpanderUp);
-        if (this._startSplitPercent == this._splitPercentage) {
-            this._splitPercentage = this._splitPercentage == 100 ? 66 : 100;
+        if (this._startSplitPercent == this.splitPercentage) {
+            this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, this.splitPercentage == 0 ? 33 : 0);
         }
     }
     onExpanderDown = (e: React.PointerEvent) => {
-        this._startSplitPercent = this._splitPercentage;
+        this._startSplitPercent = this.splitPercentage;
         e.stopPropagation();
         e.preventDefault();
         document.addEventListener("pointermove", this.onExpanderMove);
@@ -203,7 +204,7 @@ export class CollectionSchemaView extends CollectionViewBase {
         )
         let previewHandle = !this.props.active() ? (null) : (
             <div className="collectionSchemaView-previewHandle" onPointerDown={this.onExpanderDown} />);
-        let dividerDragger = this._splitPercentage == 100 ? (null) :
+        let dividerDragger = this.splitPercentage == 0 ? (null) :
             <div className="collectionSchemaView-dividerDragger" onPointerDown={this.onDividerDown} style={{ width: `${this.DIVIDER_WIDTH}px` }} />
         return (
             <div className="collectionSchemaView-container" onPointerDown={this.onPointerDown} ref={this._mainCont} style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }} >
@@ -213,7 +214,8 @@ export class CollectionSchemaView extends CollectionViewBase {
                         this._panelHeight = r.entry.height;
                     })}>
                         {({ measureRef }) =>
-                            <div ref={measureRef} className="collectionSchemaView-tableContainer" style={{ width: `${this._splitPercentage}%` }}>
+                            <div ref={measureRef} className="collectionSchemaView-tableContainer"
+                                style={{ width: `calc(100% - ${this.splitPercentage}%)` }}>
                                 <ReactTable
                                     data={children}
                                     pageSize={children.length}
@@ -235,7 +237,7 @@ export class CollectionSchemaView extends CollectionViewBase {
                         }
                     </Measure>
                     {dividerDragger}
-                    <div className="collectionSchemaView-previewRegion" style={{ width: `calc(${100 - this._splitPercentage}% - ${this.DIVIDER_WIDTH}px)` }}>
+                    <div className="collectionSchemaView-previewRegion" style={{ width: `calc(${this.props.Document.GetNumber(KeyStore.SchemaSplitPercentage, 0)}% - ${this.DIVIDER_WIDTH}px)` }}>
                         {content}
                     </div>
                     {previewHandle}
diff --git a/src/client/views/collections/MarqueeView.tsx b/src/client/views/collections/MarqueeView.tsx
index 67716f99a..65aaa837f 100644
--- a/src/client/views/collections/MarqueeView.tsx
+++ b/src/client/views/collections/MarqueeView.tsx
@@ -93,7 +93,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
 
     @action
     marqueeCommand = (e: KeyboardEvent) => {
-        if (e.key == "Backspace") {
+        if (e.key == "Backspace" || e.key == "Delete") {
             this.marqueeSelect().map(d => this.props.removeDocument(d));
             this.props.container.props.Document.SetData(KeyStore.Ink, this.marqueeInkSelect(false), InkField);
             this.cleanupInteractions();
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index fef278cec..8c1ee669f 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -48,16 +48,14 @@ export class VideoBox extends React.Component<FieldViewProps> {
 
         //setTimeout(action(() => this._loaded = true), 500);
         return (
-            <div style={{ width: "100%", height: "100%" }} >
-                <Measure onResize={this.setScaling}>
-                    {({ measureRef }) =>
-                        <video className="videobox-cont" ref={measureRef}>
-                            <source src={path} type="video/mp4" />
-                            Not supported.
+            <Measure onResize={this.setScaling}>
+                {({ measureRef }) =>
+                    <video className="videobox-cont" ref={measureRef}>
+                        <source src={path} type="video/mp4" />
+                        Not supported.
                         </video>
-                    }
-                </Measure>
-            </div>
+                }
+            </Measure>
         )
     }
 }
\ No newline at end of file
diff --git a/src/fields/KeyStore.ts b/src/fields/KeyStore.ts
index 0c8b7e260..06cdc8fc8 100644
--- a/src/fields/KeyStore.ts
+++ b/src/fields/KeyStore.ts
@@ -25,6 +25,7 @@ export namespace KeyStore {
     export const LayoutKeys = new Key("LayoutKeys");
     export const LayoutFields = new Key("LayoutFields");
     export const ColumnsKey = new Key("SchemaColumns");
+    export const SchemaSplitPercentage = new Key("SchemaSplitPercentage");
     export const Caption = new Key("Caption");
     export const ActiveFrame = new Key("ActiveFrame");
     export const DocumentText = new Key("DocumentText");
-- 
cgit v1.2.3-70-g09d2

