From d9b2e678dafbcd4c2717ff484da48607e78d37fa Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Mon, 11 Mar 2019 11:51:07 -0400
Subject: selection marquee without selection

---
 .../views/collections/CollectionFreeFormView.tsx   | 68 ++++++++++++++++++----
 1 file changed, 58 insertions(+), 10 deletions(-)

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

diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index 16002ad9f..bc6d02757 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -25,13 +25,16 @@ import "./CollectionFreeFormView.scss";
 import { COLLECTION_BORDER_WIDTH } from "./CollectionView";
 import { CollectionViewBase } from "./CollectionViewBase";
 import React = require("react");
-import { render } from "pug";
+import { Utils } from "../../../Utils";
+import { SelectionManager } from "../../util/SelectionManager";
 const JsxParser = require('react-jsx-parser').default;//TODO Why does this need to be imported like this?
 
 @observer
 export class CollectionFreeFormView extends CollectionViewBase {
     private _canvasRef = React.createRef<HTMLDivElement>();
+    @observable
     private _lastX: number = 0;
+    @observable
     private _lastY: number = 0;
     private _selectOnLoaded: string = ""; // id of document that should be selected once it's loaded (used for click-to-type)
 
@@ -68,10 +71,13 @@ export class CollectionFreeFormView extends CollectionViewBase {
         this.bringToFront(doc);
     }
 
+    @observable
+    _marquee = false;
+
     @action
     onPointerDown = (e: React.PointerEvent): void => {
-        if (((e.button === 2 && this.props.active()) ||
-            !e.defaultPrevented) && (!this.isAnnotationOverlay || this.zoomScaling != 1 || e.button == 0)) {
+        if (((e.button === 2 && this.props.active()) || !e.defaultPrevented) &&
+            (!this.isAnnotationOverlay || this.zoomScaling != 1 || e.button == 0)) {
             document.removeEventListener("pointermove", this.onPointerMove);
             document.addEventListener("pointermove", this.onPointerMove);
             document.removeEventListener("pointerup", this.onPointerUp);
@@ -80,6 +86,11 @@ export class CollectionFreeFormView extends CollectionViewBase {
             this._lastY = e.pageY;
             this._downX = e.pageX;
             this._downY = e.pageY;
+            this._marquee = e.shiftKey;
+            if (this._marquee) {
+                e.stopPropagation();
+                e.preventDefault();
+            }
         }
     }
 
@@ -88,7 +99,12 @@ export class CollectionFreeFormView extends CollectionViewBase {
         document.removeEventListener("pointermove", this.onPointerMove);
         document.removeEventListener("pointerup", this.onPointerUp);
         e.stopPropagation();
-        if (Math.abs(this._downX - e.clientX) < 3 && Math.abs(this._downY - e.clientY) < 3) {
+
+        if (this._marquee) {
+            this.marqueeSelect();
+            this._marquee = false;
+        }
+        else if (!this._marquee && Math.abs(this._downX - e.clientX) < 3 && Math.abs(this._downY - e.clientY) < 3) {
             //show preview text cursor on tap
             this._previewCursorVisible = true;
             //select is not already selected
@@ -99,16 +115,43 @@ export class CollectionFreeFormView extends CollectionViewBase {
 
     }
 
+    @action
+    marqueeSelect() {
+        var curPage = this.props.Document.GetNumber(KeyStore.CurPage, 1);
+        let p = this.getTransform().transformPoint(this._downX, this._downY);
+        let v = this.getTransform().transformDirection(this._lastX - this._downX, this._lastY - this._downY);
+
+        var curPage = this.props.Document.GetNumber(KeyStore.CurPage, 1);
+        const lvalue = this.props.Document.GetT<ListField<Document>>(this.props.fieldKey, ListField);
+        if (lvalue && lvalue != FieldWaiting) {
+            lvalue.Data.map(doc => {
+                var page = doc.GetNumber(KeyStore.Page, 0);
+                if (page == curPage || page == 0) {
+                    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 (x > p[0] && x < p[0] + v[0] && y > p[1] && y < p[1] + v[1]) {
+                        // SelectionManager.SelectDoc(doc as any as DocumentView, true);
+                    }
+                }
+            })
+        }
+    }
+
     @action
     onPointerMove = (e: PointerEvent): void => {
         if (!e.cancelBubble && this.props.active()) {
             e.stopPropagation();
             e.preventDefault();
-            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);
+
+            if (!this._marquee) {
+                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;
@@ -291,6 +334,10 @@ export class CollectionFreeFormView extends CollectionViewBase {
             cursor = <div id="prevCursor" onKeyPress={this.onKeyDown} style={{ color: "black", position: "absolute", transformOrigin: "left top", transform: `translate(${x}px, ${y}px)` }}>I</div>
         }
 
+        let p = this.getTransform().transformPoint(this._downX, this._downY);
+        let v = this.getTransform().transformDirection(this._lastX - this._downX, this._lastY - this._downY);
+        var marquee = this._marquee ? <div className="collectionfreeformview-marquee" style={{ transform: `translate(${p[0]}px, ${p[1]}px)`, width: `${v[0]}`, height: `${v[1]}` }}></div> : (null);
+
         let [dx, dy] = [this.centeringShiftX, this.centeringShiftY];
 
         const panx: number = -this.props.Document.GetNumber(KeyStore.PanX, 0);
@@ -313,7 +360,8 @@ export class CollectionFreeFormView extends CollectionViewBase {
                     {this.backgroundView}
                     <InkingCanvas getScreenTransform={this.getTransform} Document={this.props.Document} />
                     {cursor}
-                    {this.views}
+                    {React.Children.map(this.views, (child) => child)}
+                    {marquee}
                 </div>
                 {this.overlayView}
             </div>
-- 
cgit v1.2.3-70-g09d2


From 933cfacdeed99da38070790c5ec17cbdeb755267 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Mon, 11 Mar 2019 12:54:32 -0400
Subject: added marquee selection.

---
 .../views/collections/CollectionFreeFormView.tsx   | 16 +++++++++++---
 src/client/views/collections/CollectionPDFView.tsx |  2 ++
 src/client/views/collections/CollectionView.tsx    |  7 ++++--
 src/client/views/nodes/DocumentView.tsx            | 25 +++++++++++++++++++---
 4 files changed, 42 insertions(+), 8 deletions(-)

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

diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index bc6d02757..37b3d6adb 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -27,6 +27,7 @@ import { CollectionViewBase } from "./CollectionViewBase";
 import React = require("react");
 import { Utils } from "../../../Utils";
 import { SelectionManager } from "../../util/SelectionManager";
+import anymatch = require("anymatch");
 const JsxParser = require('react-jsx-parser').default;//TODO Why does this need to be imported like this?
 
 @observer
@@ -115,12 +116,22 @@ export class CollectionFreeFormView extends CollectionViewBase {
 
     }
 
+    intersectRect(r1: { left: number, right: number, top: number, bottom: number },
+        r2: { left: number, right: number, top: number, bottom: number }) {
+        return !(r2.left > r1.right ||
+            r2.right < r1.left ||
+            r2.top > r1.bottom ||
+            r2.bottom < r1.top);
+    }
+
     @action
     marqueeSelect() {
         var curPage = this.props.Document.GetNumber(KeyStore.CurPage, 1);
         let p = this.getTransform().transformPoint(this._downX, this._downY);
         let v = this.getTransform().transformDirection(this._lastX - this._downX, this._lastY - this._downY);
+        let selRect = { left: p[0], top: p[1], right: p[0] + v[0], bottom: p[1] + v[1] }
 
+        this.props.CollectionView.SelectedDocs.length = 0;
         var curPage = this.props.Document.GetNumber(KeyStore.CurPage, 1);
         const lvalue = this.props.Document.GetT<ListField<Document>>(this.props.fieldKey, ListField);
         if (lvalue && lvalue != FieldWaiting) {
@@ -131,9 +142,8 @@ export class CollectionFreeFormView extends CollectionViewBase {
                     var y = doc.GetNumber(KeyStore.Y, 0);
                     var w = doc.GetNumber(KeyStore.Width, 0);
                     var h = doc.GetNumber(KeyStore.Height, 0);
-                    if (x > p[0] && x < p[0] + v[0] && y > p[1] && y < p[1] + v[1]) {
-                        // SelectionManager.SelectDoc(doc as any as DocumentView, true);
-                    }
+                    if (this.intersectRect({ left: x, top: y, right: x + w, bottom: y + h }, selRect))
+                        this.props.CollectionView.SelectedDocs.push(doc.Id)
                 }
             })
         }
diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx
index 7fd9f0f11..f22c07060 100644
--- a/src/client/views/collections/CollectionPDFView.tsx
+++ b/src/client/views/collections/CollectionPDFView.tsx
@@ -6,6 +6,7 @@ import { ContextMenu } from "../ContextMenu";
 import { CollectionView, CollectionViewType } from "./CollectionView";
 import { CollectionViewProps } from "./CollectionViewBase";
 import React = require("react");
+import { FieldId } from "../../../fields/Field";
 
 
 @observer
@@ -17,6 +18,7 @@ export class CollectionPDFView extends React.Component<CollectionViewProps> {
                     isTopMost={isTopMost} SelectOnLoad={selectOnLoad} BackgroundView={BackgroundView} focus={focus}/>`;
     }
 
+    public SelectedDocs: FieldId[] = []
     @action onPageBack = () => this.curPage > 1 ? this.props.Document.SetNumber(KeyStore.CurPage, this.curPage - 1) : 0;
     @action onPageForward = () => this.curPage < this.numPages ? this.props.Document.SetNumber(KeyStore.CurPage, this.curPage + 1) : 0;
 
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index f154909bb..548a51bf1 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -1,4 +1,4 @@
-import { action, computed } from "mobx";
+import { action, computed, observable } from "mobx";
 import { observer } from "mobx-react";
 import { Document } from "../../../fields/Document";
 import { ListField } from "../../../fields/ListField";
@@ -12,7 +12,7 @@ import { CollectionDockingView } from "./CollectionDockingView";
 import { CollectionSchemaView } from "./CollectionSchemaView";
 import { CollectionViewProps } from "./CollectionViewBase";
 import { CollectionTreeView } from "./CollectionTreeView";
-import { Field } from "../../../fields/Field";
+import { Field, FieldId } from "../../../fields/Field";
 
 export enum CollectionViewType {
     Invalid,
@@ -27,6 +27,9 @@ export const COLLECTION_BORDER_WIDTH = 2;
 @observer
 export class CollectionView extends React.Component<CollectionViewProps> {
 
+    @observable
+    public SelectedDocs: FieldId[] = [];
+
     public static LayoutString(fieldKey: string = "DataKey") {
         return `<${CollectionView.name} Document={Document}
                     ScreenToLocalTransform={ScreenToLocalTransform} fieldKey={${fieldKey}} panelWidth={PanelWidth} panelHeight={PanelHeight} isSelected={isSelected} select={select} bindings={bindings}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 263bb31d7..7627fbf6c 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1,4 +1,4 @@
-import { action, computed } from "mobx";
+import { action, computed, IReactionDisposer, reaction } from "mobx";
 import { observer } from "mobx-react";
 import { Document } from "../../../fields/Document";
 import { Field, FieldWaiting, Opt } from "../../../fields/Field";
@@ -16,8 +16,8 @@ import { CollectionPDFView } from "../collections/CollectionPDFView";
 import { ContextMenu } from "../ContextMenu";
 import { FormattedTextBox } from "../nodes/FormattedTextBox";
 import { ImageBox } from "../nodes/ImageBox";
-import { VideoBox } from "../nodes/VideoBox"; 
-import { AudioBox } from "../nodes/AudioBox"; 
+import { VideoBox } from "../nodes/VideoBox";
+import { AudioBox } from "../nodes/AudioBox";
 import { Documents } from "../../documents/Documents"
 import { KeyValueBox } from "./KeyValueBox"
 import { WebBox } from "../nodes/WebBox";
@@ -88,6 +88,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     private _documentBindings: any = null;
     private _downX: number = 0;
     private _downY: number = 0;
+    private _reactionDisposer: Opt<IReactionDisposer>;
     @computed get active(): boolean { return SelectionManager.IsSelected(this) || !this.props.ContainingCollectionView || this.props.ContainingCollectionView.active(); }
     @computed get topMost(): boolean { return !this.props.ContainingCollectionView || this.props.ContainingCollectionView.collectionViewType == CollectionViewType.Docking; }
     @computed get layout(): string { return this.props.Document.GetText(KeyStore.Layout, "<p>Error loading layout data</p>"); }
@@ -113,6 +114,24 @@ export class DocumentView extends React.Component<DocumentViewProps> {
             }
         }
     }
+
+
+    componentDidMount() {
+        this._reactionDisposer = reaction(
+            () => this.props.ContainingCollectionView && this.props.ContainingCollectionView.SelectedDocs.slice(),
+            () => {
+                if (this.props.ContainingCollectionView && this.props.ContainingCollectionView.SelectedDocs.indexOf(this.props.Document.Id) != -1)
+                    SelectionManager.SelectDoc(this, true);
+            });
+    }
+
+    componentWillUnmount() {
+        if (this._reactionDisposer) {
+            this._reactionDisposer();
+        }
+    }
+
+
     onPointerMove = (e: PointerEvent): void => {
         if (e.cancelBubble) {
             return;
-- 
cgit v1.2.3-70-g09d2


From 501a74c77bda9256f449c7009194a6964819841a Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Mon, 11 Mar 2019 13:38:34 -0400
Subject: cleanup

---
 src/client/views/collections/CollectionFreeFormView.tsx | 9 +++------
 src/client/views/collections/CollectionViewBase.tsx     | 1 -
 2 files changed, 3 insertions(+), 7 deletions(-)

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

diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index 37b3d6adb..07f022382 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -1,4 +1,4 @@
-import { action, computed, observable, reaction, trace } from "mobx";
+import { action, computed, observable } from "mobx";
 import { observer } from "mobx-react";
 import { Document } from "../../../fields/Document";
 import { FieldWaiting } from "../../../fields/Field";
@@ -10,9 +10,9 @@ import { DragManager } from "../../util/DragManager";
 import { Transform } from "../../util/Transform";
 import { undoBatch } from "../../util/UndoManager";
 import { CollectionDockingView } from "../collections/CollectionDockingView";
+import { CollectionPDFView } from "../collections/CollectionPDFView";
 import { CollectionSchemaView } from "../collections/CollectionSchemaView";
 import { CollectionView } from "../collections/CollectionView";
-import { CollectionPDFView } from "../collections/CollectionPDFView";
 import { InkingCanvas } from "../InkingCanvas";
 import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView";
 import { DocumentView } from "../nodes/DocumentView";
@@ -25,9 +25,6 @@ import "./CollectionFreeFormView.scss";
 import { COLLECTION_BORDER_WIDTH } from "./CollectionView";
 import { CollectionViewBase } from "./CollectionViewBase";
 import React = require("react");
-import { Utils } from "../../../Utils";
-import { SelectionManager } from "../../util/SelectionManager";
-import anymatch = require("anymatch");
 const JsxParser = require('react-jsx-parser').default;//TODO Why does this need to be imported like this?
 
 @observer
@@ -370,7 +367,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
                     {this.backgroundView}
                     <InkingCanvas getScreenTransform={this.getTransform} Document={this.props.Document} />
                     {cursor}
-                    {React.Children.map(this.views, (child) => child)}
+                    {this.views}
                     {marquee}
                 </div>
                 {this.overlayView}
diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx
index 38271e7bf..59fa61800 100644
--- a/src/client/views/collections/CollectionViewBase.tsx
+++ b/src/client/views/collections/CollectionViewBase.tsx
@@ -11,7 +11,6 @@ import { Documents, DocumentOptions } from "../../documents/Documents";
 import { Key } from "../../../fields/Key";
 import { Transform } from "../../util/Transform";
 import { CollectionView } from "./CollectionView";
-import * as request from "request";
 
 export interface CollectionViewProps {
     fieldKey: Key;
-- 
cgit v1.2.3-70-g09d2

