aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/CollectionFreeFormView.tsx
diff options
context:
space:
mode:
authorSam Wilkins <abdullah_ahmed@brown.edu>2019-03-17 13:27:33 -0400
committerSam Wilkins <abdullah_ahmed@brown.edu>2019-03-17 13:27:33 -0400
commitbc97c3d8b057ec73f6726c31cf8bbe37e679e0d0 (patch)
tree10031eb180ffde65538b617a7fec74b8be9d3bd1 /src/client/views/collections/CollectionFreeFormView.tsx
parent978c2139753e677020d6d3e149ebe51b6443b1dc (diff)
parent47da497aded0bafdc5c85c8a79a9a06d0d401e92 (diff)
merged with master, resolved conflicts and reformatted workspace menu
Diffstat (limited to 'src/client/views/collections/CollectionFreeFormView.tsx')
-rw-r--r--src/client/views/collections/CollectionFreeFormView.tsx228
1 files changed, 77 insertions, 151 deletions
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index 0c74d1852..bb28dd20a 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -5,46 +5,74 @@ import { FieldWaiting } from "../../../fields/Field";
import { KeyStore } from "../../../fields/KeyStore";
import { ListField } from "../../../fields/ListField";
import { TextField } from "../../../fields/TextField";
-import { Documents } from "../../documents/Documents";
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 { CollectionVideoView } from "../collections/CollectionVideoView";
import { CollectionView } from "../collections/CollectionView";
import { InkingCanvas } from "../InkingCanvas";
+import { AudioBox } from "../nodes/AudioBox";
import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView";
import { DocumentView } from "../nodes/DocumentView";
import { FormattedTextBox } from "../nodes/FormattedTextBox";
import { ImageBox } from "../nodes/ImageBox";
import { KeyValueBox } from "../nodes/KeyValueBox";
import { PDFBox } from "../nodes/PDFBox";
+import { VideoBox } from "../nodes/VideoBox";
import { WebBox } from "../nodes/WebBox";
import "./CollectionFreeFormView.scss";
import { COLLECTION_BORDER_WIDTH } from "./CollectionView";
import { CollectionViewBase } from "./CollectionViewBase";
+import { MarqueeView } from "./MarqueeView";
+import { PreviewCursor } from "./PreviewCursor";
import React = require("react");
-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;
+ public _canvasRef = React.createRef<HTMLDivElement>();
private _selectOnLoaded: string = ""; // id of document that should be selected once it's loaded (used for click-to-type)
- @observable
- private _downX: number = 0;
- @observable
- private _downY: number = 0;
+ public addLiveTextBox = (newBox: Document) => {
+ // mark this collection so that when the text box is created we can send it the SelectOnLoad prop to focus itself
+ this._selectOnLoaded = newBox.Id;
+ //set text to be the typed key and get focus on text box
+ this.props.addDocument(newBox);
+ //remove cursor from screen
+ this.PreviewCursorVisible = false;
+ }
+
+ public selectDocuments = (docs: Document[]) => {
+ this.props.CollectionView.SelectedDocs.length = 0;
+ docs.map(d => this.props.CollectionView.SelectedDocs.push(d.Id));
+ }
+
+ public getActiveDocuments = () => {
+ var curPage = this.props.Document.GetNumber(KeyStore.CurPage, -1);
+ const lvalue = this.props.Document.GetT<ListField<Document>>(this.props.fieldKey, ListField);
+ let active: Document[] = [];
+ if (lvalue && lvalue != FieldWaiting) {
+ lvalue.Data.map(doc => {
+ var page = doc.GetNumber(KeyStore.Page, -1);
+ if (page == curPage || page == -1) {
+ active.push(doc);
+ }
+ })
+ }
+
+ return active;
+ }
//determines whether the blinking cursor for indicating whether a text will be made on key down is visible
- @observable
- private _previewCursorVisible: boolean = false;
+ @observable public PreviewCursorVisible: boolean = false;
+ @observable public MarqueeVisible = false;
+ @observable public DownX: number = 0;
+ @observable public DownY: number = 0;
+ @observable private _lastX: number = 0;
+ @observable private _lastY: number = 0;
@computed get panX(): number { return this.props.Document.GetNumber(KeyStore.PanX, 0) }
@computed get panY(): number { return this.props.Document.GetNumber(KeyStore.PanY, 0) }
@@ -72,41 +100,34 @@ export class CollectionFreeFormView extends CollectionViewBase {
}
}
- @observable
- _marquee = false;
+
+ @action
+ cleanupInteractions = () => {
+ document.removeEventListener("pointermove", this.onPointerMove);
+ document.removeEventListener("pointerup", this.onPointerUp);
+ this.MarqueeVisible = false;
+ }
@action
onPointerDown = (e: React.PointerEvent): void => {
- if (((e.button === 2 && this.props.active()) || !e.defaultPrevented) &&
- (!this.isAnnotationOverlay || this.zoomScaling != 1 || e.button == 0)) {
+ this.PreviewCursorVisible = false;
+ if ((e.button === 2 && this.props.active() && (!this.isAnnotationOverlay || this.zoomScaling != 1)) || e.button == 0) {
document.removeEventListener("pointermove", this.onPointerMove);
document.addEventListener("pointermove", this.onPointerMove);
document.removeEventListener("pointerup", this.onPointerUp);
document.addEventListener("pointerup", this.onPointerUp);
- this._lastX = e.pageX;
- this._lastY = e.pageY;
- this._downX = e.pageX;
- this._downY = e.pageY;
+ this._lastX = this.DownX = e.pageX;
+ this._lastY = this.DownY = e.pageY;
}
}
@action
onPointerUp = (e: PointerEvent): void => {
- if (this._marquee) {
- document.removeEventListener("keydown", this.marqueeCommand);
- }
e.stopPropagation();
- if (this._marquee) {
- if (!e.shiftKey) {
- SelectionManager.DeselectAll();
- }
- var selectedDocs = this.marqueeSelect();
- selectedDocs.map(s => this.props.CollectionView.SelectedDocs.push(s.Id));
- }
- else if (!this._marquee && 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;
+ this.PreviewCursorVisible = true;
//select is not already selected
if (!this.props.isSelected()) {
this.props.select(false);
@@ -116,97 +137,31 @@ export class CollectionFreeFormView extends CollectionViewBase {
}
@action
- cleanupInteractions = () => {
- document.removeEventListener("pointermove", this.onPointerMove);
- document.removeEventListener("pointerup", this.onPointerUp);
- this._marquee = false;
- }
-
- 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);
- }
-
- marqueeSelect() {
- this.props.CollectionView.SelectedDocs.length = 0;
- var curPage = this.props.Document.GetNumber(KeyStore.CurPage, 1);
- let p = this.getTransform().transformPoint(this._downX < this._lastX ? this._downX : this._lastX, this._downY < this._lastY ? this._downY : this._lastY);
- 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] }
-
- var curPage = this.props.Document.GetNumber(KeyStore.CurPage, 1);
- const lvalue = this.props.Document.GetT<ListField<Document>>(this.props.fieldKey, ListField);
- let selection: Document[] = [];
- 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 (this.intersectRect({ left: x, top: y, right: x + w, bottom: y + h }, selRect))
- selection.push(doc)
- }
- })
- }
- return selection;
- }
-
- @action
onPointerMove = (e: PointerEvent): void => {
if (!e.cancelBubble && this.props.active()) {
- e.stopPropagation();
- e.preventDefault();
- let wasMarquee = this._marquee;
- this._marquee = e.buttons != 2 && !e.altKey && !e.metaKey;
- if (this._marquee && !wasMarquee) {
- this._previewCursorVisible = false;
- document.addEventListener("keydown", this.marqueeCommand);
+ if (e.buttons == 1 && !e.altKey && !e.metaKey) {
+ this.MarqueeVisible = true;
}
-
- if (!this._marquee) {
+ if (this.MarqueeVisible) {
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ else if ((!this.isAnnotationOverlay || this.zoomScaling != 1) && !e.shiftKey) {
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;
+ e.stopPropagation();
+ e.preventDefault();
}
}
- this._lastX = e.pageX;
- this._lastY = e.pageY;
- }
-
- @action
- marqueeCommand = (e: KeyboardEvent) => {
- if (e.key == "Backspace") {
- this.marqueeSelect().map(d => this.props.removeDocument(d));
- this.cleanupInteractions();
- }
- if (e.key == "c") {
- let p = this.getTransform().transformPoint(this._downX < this._lastX ? this._downX : this._lastX, this._downY < this._lastY ? this._downY : this._lastY);
- let v = this.getTransform().transformDirection(this._lastX - this._downX, this._lastY - this._downY);
-
- let selected = this.marqueeSelect().map(m => m);
- this.marqueeSelect().map(d => this.props.removeDocument(d));
- //setTimeout(() => {
- this.props.CollectionView.addDocument(Documents.FreeformDocument(selected.map(d => {
- d.SetNumber(KeyStore.X, d.GetNumber(KeyStore.X, 0) - p[0] - v[0] / 2);
- d.SetNumber(KeyStore.Y, d.GetNumber(KeyStore.Y, 0) - p[1] - v[1] / 2);
- d.SetNumber(KeyStore.Page, this.props.Document.GetNumber(KeyStore.Page, 0));
- d.SetText(KeyStore.Title, "" + d.GetNumber(KeyStore.Width, 0) + " " + d.GetNumber(KeyStore.Height, 0));
- return d;
- }), { x: p[0], y: p[1], panx: 0, pany: 0, width: v[0], height: v[1], title: "a nested collection" }));
- // }, 100);
- this.cleanupInteractions();
- }
}
@action
onPointerWheel = (e: React.WheelEvent): void => {
+ this.props.select(false);
e.stopPropagation();
e.preventDefault();
let coefficient = 1000;
@@ -242,7 +197,6 @@ export class CollectionFreeFormView extends CollectionViewBase {
@action
private SetPan(panX: number, panY: number) {
var x1 = this.getLocalTransform().inverse().Scale;
- var x2 = this.getTransform().inverse().Scale;
const newPanX = Math.min((1 - 1 / x1) * this.nativeWidth, Math.max(0, panX));
const newPanY = Math.min((1 - 1 / x1) * this.nativeHeight, Math.max(0, panY));
this.props.Document.SetNumber(KeyStore.PanX, this.isAnnotationOverlay ? newPanX : panX);
@@ -259,24 +213,6 @@ export class CollectionFreeFormView extends CollectionViewBase {
}
@action
- onKeyDown = (e: React.KeyboardEvent<Element>) => {
- //if not these keys, make a textbox if preview cursor is active!
- // if (!e.ctrlKey && !e.altKey) {
- // if (this._previewCursorVisible) {
- // //make textbox and add it to this collection
- // let [x, y] = this.getTransform().transformPoint(this._downX, this._downY); (this._downX, this._downY);
- // let newBox = Documents.TextDocument({ width: 200, height: 100, x: x, y: y, title: "new" });
- // // mark this collection so that when the text box is created we can send it the SelectOnLoad prop to focus itself
- // this._selectOnLoaded = newBox.Id;
- // //set text to be the typed key and get focus on text box
- // this.props.CollectionView.addDocument(newBox);
- // //remove cursor from screen
- // this._previewCursorVisible = false;
- // }
- // }
- }
-
- @action
bringToFront(doc: Document) {
const { fieldKey: fieldKey, Document: Document } = this.props;
@@ -317,7 +253,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
@computed
get views() {
- var curPage = this.props.Document.GetNumber(KeyStore.CurPage, 1);
+ 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) {
return lvalue.Data.map(doc => {
@@ -344,7 +280,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
get backgroundView() {
return !this.backgroundLayout ? (null) :
(<JsxParser
- components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, WebBox, KeyValueBox, PDFBox }}
+ components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, CollectionVideoView, WebBox, KeyValueBox, PDFBox, VideoBox, AudioBox }}
bindings={this.props.bindings}
jsx={this.backgroundLayout}
showWarnings={true}
@@ -355,7 +291,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
get overlayView() {
return !this.overlayLayout ? (null) :
(<JsxParser
- components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, WebBox, KeyValueBox, PDFBox }}
+ components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, CollectionVideoView, WebBox, KeyValueBox, PDFBox, VideoBox, AudioBox }}
bindings={this.props.bindings}
jsx={this.overlayLayout}
showWarnings={true}
@@ -364,28 +300,17 @@ export class CollectionFreeFormView extends CollectionViewBase {
}
getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH).translate(-this.centeringShiftX, -this.centeringShiftY).transform(this.getLocalTransform())
+ getMarqueeTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH)
getLocalTransform = (): Transform => Transform.Identity.scale(1 / this.scale).translate(this.panX, this.panY);
noScaling = () => 1;
//when focus is lost, this will remove the preview cursor
@action
- onBlur = (e: React.FocusEvent<HTMLDivElement>): void => {
- this._previewCursorVisible = false;
+ onBlur = (): void => {
+ this.PreviewCursorVisible = false;
}
render() {
- //determines whether preview text cursor should be visible (ie when user taps this collection it should)
- let cursor = null;
- if (this._previewCursorVisible) {
- //get local position and place cursor there!
- let [x, y] = this.getTransform().transformPoint(this._downX, this._downY);
- 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._lastX ? this._downX : this._lastX, this._downY < this._lastY ? this._downY : this._lastY);
- 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: `${Math.abs(v[0])}`, height: `${Math.abs(v[1])}` }}></div> : (null);
-
let [dx, dy] = [this.centeringShiftX, this.centeringShiftY];
const panx: number = -this.props.Document.GetNumber(KeyStore.PanX, 0);
@@ -397,7 +322,6 @@ export class CollectionFreeFormView extends CollectionViewBase {
return (
<div className={`collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`}
onPointerDown={this.onPointerDown}
- onKeyPress={this.onKeyDown}
onWheel={this.onPointerWheel}
onDrop={this.onDrop.bind(this)}
onDragOver={this.onDragOver}
@@ -410,12 +334,14 @@ export class CollectionFreeFormView extends CollectionViewBase {
ref={this._canvasRef}>
{this.backgroundView}
<InkingCanvas getScreenTransform={this.getTransform} Document={this.props.Document} />
- {cursor}
+ <PreviewCursor container={this} addLiveTextDocument={this.addLiveTextBox} getTransform={this.getTransform} />
{this.views}
- {marquee}
</div>
+ <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>
);
}
-}
+} \ No newline at end of file