aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections
diff options
context:
space:
mode:
authorTyler Schicke <tyler_schicke@brown.edu>2019-04-25 15:36:32 -0400
committerTyler Schicke <tyler_schicke@brown.edu>2019-04-25 15:36:32 -0400
commitc318c6cb44b26b780e94e0f0854e5ec4c14634a9 (patch)
tree5c6bcb413f771988bd89efe3551007bd6d0f160c /src/client/views/collections
parente1a65c5fa52dd094cc48c0c85b3c92ae8789666d (diff)
parent430dfa3afbfd38fe0db869b962da45903b888264 (diff)
Merge branch 'master' of github-tsch-brown:browngraphicslab/Dash-Web into newDocs
Diffstat (limited to 'src/client/views/collections')
-rw-r--r--src/client/views/collections/CollectionBaseView.tsx53
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx16
-rw-r--r--src/client/views/collections/CollectionSchemaView.tsx12
-rw-r--r--src/client/views/collections/CollectionSubView.tsx24
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx5
-rw-r--r--src/client/views/collections/CollectionVideoView.tsx10
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx2
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss1
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx78
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx123
10 files changed, 163 insertions, 161 deletions
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 058893198..4807dc40a 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -3,7 +3,7 @@ import { observer } from 'mobx-react';
import * as React from 'react';
import { ContextMenu } from '../ContextMenu';
import { FieldViewProps } from '../nodes/FieldView';
-import { Cast, FieldValue, PromiseValue } from '../../../new_fields/Types';
+import { Cast, FieldValue, PromiseValue, NumCast } from '../../../new_fields/Types';
import { Doc, FieldResult, Opt, Id } from '../../../new_fields/Doc';
import { listSpec } from '../../../new_fields/Schema';
import { List } from '../../../new_fields/List';
@@ -87,51 +87,24 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
let props = this.props;
var curPage = Cast(props.Document.curPage, "number", -1);
Doc.SetOnPrototype(doc, "page", curPage);
- if (true || this.isAnnotationOverlay) {
- doc.zoom = Cast(this.props.Document.scale, "number", 1);
- }
if (curPage >= 0) {
Doc.SetOnPrototype(doc, "annotationOn", props.Document);
}
- const data = props.Document[props.fieldKey];
- if (data !== undefined) {
+ if (!this.createsCycle(doc, props.Document)) {
//TODO This won't create the field if it doesn't already exist
- const value = Cast(data, listSpec(Doc));
- if (!this.createsCycle(doc, props.Document) && value !== undefined) {
+ const value = Cast(props.Document[props.fieldKey], listSpec(Doc));
+ if (value !== undefined) {
if (allowDuplicates || !value.some(v => v.Id === doc.Id)) {
value.push(doc);
}
+ } else {
+ this.props.Document[this.props.fieldKey] = new List([doc]);
}
- else {
- return false;
- }
- } else {
- let proto = FieldValue(props.Document.proto);
- if (!proto || !this.createsCycle(proto, doc)) {
- const field = new List([doc]);
- // const script = CompileScript(`
- // if(added) {
- // console.log("added " + field.Title + " " + doc.Title);
- // } else {
- // console.log("removed " + field.Title + " " + doc.Title);
- // }
- // `, {
- // addReturn: false,
- // params: {
- // field: Document.name,
- // added: "boolean"
- // },
- // capturedVariables: {
- // doc: this.props.Document
- // }
- // });
- // if (script.compiled) {
- // field.addScript(new ScriptField(script));
- // }
- Doc.SetOnPrototype(props.Document, props.fieldKey, field);
- }
- else {
- return false;
+ // set the ZoomBasis only if hasn't already been set -- bcz: maybe set/resetting the ZoomBasis should be a parameter to addDocument?
+ if (this.collectionViewType === CollectionViewType.Freeform || this.collectionViewType === CollectionViewType.Invalid) {
+ let zoom = NumCast(this.props.Document.scale, 1);
+ let screen = this.props.ScreenToLocalTransform().inverse().Scale / (this.props as any).ContentScaling() * zoom;
+ doc.zoomBasis = screen;
}
}
return true;
@@ -186,7 +159,9 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
};
const viewtype = this.collectionViewType;
return (
- <div className={this.props.className || "collectionView-cont"} onContextMenu={this.props.onContextMenu} ref={this.props.contentRef}>
+ <div className={this.props.className || "collectionView-cont"}
+ style={{ borderRadius: "inherit", pointerEvents: "all" }}
+ onContextMenu={this.props.onContextMenu} ref={this.props.contentRef}>
{viewtype !== undefined ? this.props.children(viewtype, props) : (null)}
</div>
);
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 86ee7cea9..ec5f823b0 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -5,7 +5,7 @@ import { action, observable, reaction, trace } from "mobx";
import { observer } from "mobx-react";
import * as ReactDOM from 'react-dom';
import Measure from "react-measure";
-import { Utils, returnTrue, emptyFunction, returnOne } from "../../../Utils";
+import { Utils, returnTrue, emptyFunction, returnOne, returnZero } from "../../../Utils";
import { Server } from "../../Server";
import { undoBatch } from "../../util/UndoManager";
import { DocumentView } from "../nodes/DocumentView";
@@ -16,9 +16,10 @@ import { ServerUtils } from "../../../server/ServerUtil";
import { DragManager, DragLinksAsDocuments } from "../../util/DragManager";
import { Transform } from '../../util/Transform';
import { Doc, Id, Opt, Field, FieldId } from "../../../new_fields/Doc";
-import { Cast } from "../../../new_fields/Types";
+import { Cast, NumCast } from "../../../new_fields/Types";
import { List } from "../../../new_fields/List";
import { DocServer } from "../../DocServer";
+import { listSpec } from "../../../new_fields/Schema";
@observer
export class CollectionDockingView extends React.Component<SubCollectionViewProps> {
@@ -256,8 +257,8 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
if (tfield !== undefined) {
tab.titleElement[0].textContent = f.Title;
}
- const lf = await Cast(f.linkedFromDocs, List);
- const lt = await Cast(f.linkedToDocs, List);
+ const lf = await Cast(f.linkedFromDocs, listSpec(Doc));
+ const lt = await Cast(f.linkedToDocs, listSpec(Doc));
let count = (lf ? lf.length : 0) + (lt ? lt.length : 0);
let counter: any = this.htmlToElement(`<div class="messageCounter">${count}</div>`);
tab.element.append(counter);
@@ -322,8 +323,8 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
DocServer.GetRefField(this.props.documentId).then(action((f: Opt<Field>) => this._document = f as Doc));
}
- nativeWidth = () => Cast(this._document!.nativeWidth, "number", this._panelWidth);
- nativeHeight = () => Cast(this._document!.nativeHeight, "number", this._panelHeight);
+ nativeWidth = () => NumCast(this._document!.nativeWidth, this._panelWidth);
+ nativeHeight = () => NumCast(this._document!.nativeHeight, this._panelHeight);
contentScaling = () => {
const nativeH = this.nativeHeight();
const nativeW = this.nativeWidth();
@@ -349,6 +350,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
<div className="collectionDockingView-content" ref={this._mainCont}
style={{ transform: `translate(${this.previewPanelCenteringOffset}px, 0px)` }}>
<DocumentView key={this._document![Id]} Document={this._document!}
+ toggleMinimized={emptyFunction}
addDocument={undefined}
removeDocument={undefined}
ContentScaling={this.contentScaling}
@@ -361,7 +363,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
whenActiveChanged={emptyFunction}
focus={emptyFunction}
ContainingCollectionView={undefined} />
- </div>);
+ </div >);
}
render() {
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index e556151f9..2e1175f28 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -7,10 +7,9 @@ import { observer } from "mobx-react";
import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table";
import { MAX_ROW_HEIGHT } from '../../views/globalCssVariables.scss'
import "react-table/react-table.css";
-import { emptyFunction, returnFalse } from "../../../Utils";
-import { Server } from "../../Server";
+import { emptyFunction, returnFalse, returnZero } from "../../../Utils";
import { SetupDrag } from "../../util/DragManager";
-import { CompileScript, ToField } from "../../util/Scripting";
+import { CompileScript } from "../../util/Scripting";
import { Transform } from "../../util/Transform";
import { COLLECTION_BORDER_WIDTH } from "../../views/globalCssVariables.scss";
import { anchorPoints, Flyout } from "../DocumentDecorations";
@@ -21,7 +20,7 @@ import { FieldView, FieldViewProps } from "../nodes/FieldView";
import "./CollectionSchemaView.scss";
import { CollectionSubView } from "./CollectionSubView";
import { Opt, Field, Doc, Id } from "../../../new_fields/Doc";
-import { Cast, FieldValue } from "../../../new_fields/Types";
+import { Cast, FieldValue, NumCast } from "../../../new_fields/Types";
import { listSpec } from "../../../new_fields/Schema";
import { List } from "../../../new_fields/List";
@@ -57,7 +56,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
@observable _keys: string[] = [];
@observable _newKeyName: string = "";
- @computed get splitPercentage() { return Cast(this.props.Document.schemaSplitPercentage, "number", 0); }
+ @computed get splitPercentage() { return NumCast(this.props.Document.schemaSplitPercentage); }
@computed get columns() { return Cast(this.props.Document.columns, listSpec("string"), []); }
@computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
@@ -74,6 +73,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
focus: emptyFunction,
active: returnFalse,
whenActiveChanged: emptyFunction,
+ PanelHeight: returnZero,
+ PanelWidth: returnZero,
};
let contents = (
<FieldView {...props} />
@@ -256,6 +257,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
<div className="collectionSchemaView-previewRegion" style={{ width: `${this.previewRegionWidth}px` }}>
<div className="collectionSchemaView-previewDoc" style={{ transform: `translate(${this.previewPanelCenteringOffset}px, 0px)` }}>
<DocumentView Document={this.previewDocument} isTopMost={false} selectOnLoad={false}
+ toggleMinimized={emptyFunction}
addDocument={this.props.addDocument} removeDocument={this.props.removeDocument}
ScreenToLocalTransform={this.getPreviewTransform}
ContentScaling={this.previewContentScaling}
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 642e5aed6..558a8728f 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -4,11 +4,7 @@ import { undoBatch, UndoManager } from "../../util/UndoManager";
import { DragManager } from "../../util/DragManager";
import { Docs, DocumentOptions } from "../../documents/Documents";
import { RouteStore } from "../../../server/RouteStore";
-import { TupleField } from "../../../fields/TupleField";
import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils";
-import { NumberField } from "../../../fields/NumberField";
-import { ServerUtils } from "../../../server/ServerUtil";
-import { Server } from "../../Server";
import { FieldViewProps } from "../nodes/FieldView";
import * as rp from 'request-promise';
import { CollectionView } from "./CollectionView";
@@ -85,7 +81,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
if (de.data instanceof DragManager.DocumentDragData) {
if (de.data.aliasOnDrop || de.data.copyOnDrop) {
["width", "height", "curPage"].map(key =>
- de.data.draggedDocuments.map((draggedDocument: Document, i: number) =>
+ de.data.draggedDocuments.map((draggedDocument: Doc, i: number) =>
PromiseValue(Cast(draggedDocument[key], "number")).then(f => f && (de.data.droppedDocuments[i][key] = f))));
}
let added = false;
@@ -148,7 +144,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
return undefined;
}
ctor = Docs.WebDocument;
- options = { height: options.width, ...options, title: path };
+ options = { height: options.width, ...options, title: path, nativeWidth: undefined };
}
return ctor ? ctor(path, options) : undefined;
}
@@ -166,9 +162,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
e.preventDefault();
if (html && html.indexOf("<img") !== 0 && !html.startsWith("<a")) {
- console.log("not good");
- let htmlDoc = Docs.HtmlDocument(html, { ...options, width: 300, height: 300 });
- htmlDoc.documentText = text;
+ let htmlDoc = Docs.HtmlDocument(html, { ...options, width: 300, height: 300, documentText: text });
this.props.addDocument(htmlDoc, false);
return;
}
@@ -182,7 +176,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
if (item.kind === "string" && item.type.indexOf("uri") !== -1) {
let str: string;
let prom = new Promise<string>(resolve => e.dataTransfer.items[i].getAsString(resolve))
- .then(action((s: string) => rp.head(ServerUtils.prepend(RouteStore.corsProxy + "/" + (str = s)))))
+ .then(action((s: string) => rp.head(DocServer.prepend(RouteStore.corsProxy + "/" + (str = s)))))
.then(result => {
let type = result.headers["content-type"];
if (type) {
@@ -210,15 +204,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
let path = window.location.origin + file;
let docPromise = this.getDocumentFromType(type, path, { ...options, nativeWidth: 600, width: 300, title: dropFileName });
- docPromise.then(async doc => {
- let docs = await Cast(this.props.Document[this.props.fieldKey], listSpec(Doc));
- if (!docs) {
- this.props.Document[this.props.fieldKey] = docs = new List();
- }
- if (doc) {
- docs.push(doc);
- }
- });
+ docPromise.then(doc => doc && this.props.addDocument(doc));
}));
});
promises.push(prom);
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index e0387f4b4..905b48db7 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -136,7 +136,10 @@ export class CollectionTreeView extends CollectionSubView {
);
return (
- <div id="body" className="collectionTreeView-dropTarget" onWheel={(e: React.WheelEvent) => e.stopPropagation()} onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createDropTarget}>
+ <div id="body" className="collectionTreeView-dropTarget"
+ style={{ borderRadius: "inherit" }}
+ onWheel={(e: React.WheelEvent) => e.stopPropagation()}
+ onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createDropTarget}>
<div className="coll-title">
<EditableView
contents={this.props.Document.Title}
diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index 29fb342c6..779dc8fc3 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -37,10 +37,13 @@ export class CollectionVideoView extends React.Component<FieldViewProps> {
]);
}
+ _ele: HTMLDivElement | null = null;
@action
mainCont = (ele: HTMLDivElement | null) => {
+ this._ele = ele;
if (ele) {
this._player = ele.getElementsByTagName("video")[0];
+ console.log(this._player);
if (this.props.Document.GetNumber(KeyStore.CurPage, -1) >= 0) {
this._currentTimecode = this.props.Document.GetNumber(KeyStore.CurPage, -1);
}
@@ -57,9 +60,12 @@ export class CollectionVideoView extends React.Component<FieldViewProps> {
@action
updateTimecode = () => {
+ this._player = this._player ? this._player : this._ele ? this._ele.getElementsByTagName("video")[0] : undefined;
if (this._player) {
- if ((this._player as any).AHackBecauseSomethingResetsTheVideoToZero !== -1) {
- this._player.currentTime = (this._player as any).AHackBecauseSomethingResetsTheVideoToZero;
+ let timecode = (this._player as any).hasOwnProperty("AHackBecauseSomethingResetsTheVideoToZero") ?
+ (this._player as any).AHackBecauseSomethingResetsTheVideoToZero : -1;
+ if (timecode !== -1 && Object) {
+ this._player.currentTime = timecode;
(this._player as any).AHackBecauseSomethingResetsTheVideoToZero = -1;
} else {
this._currentTimecode = this._player.currentTime;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
index cd74d3a84..ebdb0c75c 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
@@ -18,7 +18,7 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
componentDidMount() {
this._brushReactionDisposer = reaction(() => this.props.Document.GetList(this.props.fieldKey, [] as Document[]).map(doc => doc.GetNumber(KeyStore.X, 0)),
() => {
- let views = this.props.Document.GetList(this.props.fieldKey, [] as Document[]);
+ let views = this.props.Document.GetList(this.props.fieldKey, [] as Document[]).filter(doc => doc.GetText(KeyStore.BackgroundLayout, "").indexOf("istogram") !== -1);
for (let i = 0; i < views.length; i++) {
for (let j = 0; j < views.length; j++) {
let srcDoc = views[j];
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
index 57706b51e..67a0e532c 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
@@ -6,6 +6,7 @@
width: 100%;
height: 100%;
transform-origin: left top;
+ pointer-events: none;
}
.collectionfreeformview-container {
.collectionfreeformview > .jsx-parser {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 3a9c9780b..80900c450 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1,4 +1,4 @@
-import { action, computed, observable, trace } from "mobx";
+import { action, computed } from "mobx";
import { observer } from "mobx-react";
import { emptyFunction, returnFalse, returnOne } from "../../../../Utils";
import { DocumentManager } from "../../../util/DocumentManager";
@@ -8,7 +8,6 @@ import { Transform } from "../../../util/Transform";
import { undoBatch } from "../../../util/UndoManager";
import { COLLECTION_BORDER_WIDTH } from "../../../views/globalCssVariables.scss";
import { InkingCanvas } from "../../InkingCanvas";
-import { MainOverlayTextBox } from "../../MainOverlayTextBox";
import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDocumentView";
import { DocumentContentsView } from "../../nodes/DocumentContentsView";
import { DocumentViewProps, positionSchema } from "../../nodes/DocumentView";
@@ -21,7 +20,7 @@ import React = require("react");
import v5 = require("uuid/v5");
import { createSchema, makeInterface, listSpec } from "../../../../new_fields/Schema";
import { Doc, Id } from "../../../../new_fields/Doc";
-import { FieldValue, Cast } from "../../../../new_fields/Types";
+import { FieldValue, Cast, NumCast } from "../../../../new_fields/Types";
import { pageSchema } from "../../nodes/ImageBox";
import { List } from "../../../../new_fields/List";
@@ -36,6 +35,7 @@ const PanZoomDocument = makeInterface(panZoomSchema, positionSchema, pageSchema)
@observer
export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
+ public static RIGHT_BTN_DRAG = false;
private _selectOnLoaded: string = ""; // id of document that should be selected once it's loaded (used for click-to-type)
private _lastX: number = 0;
private _lastY: number = 0;
@@ -46,7 +46,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
@computed get nativeHeight() { return FieldValue(this.Document.nativeHeight, 0); }
private get borderWidth() { return this.isAnnotationOverlay ? 0 : COLLECTION_BORDER_WIDTH; }
private get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldKey === "annotations"; }
- private childViews = () => this.views;
private panX = () => FieldValue(this.Document.panX, 0);
private panY = () => FieldValue(this.Document.panY, 0);
private zoomScaling = () => FieldValue(this.Document.scale, 1);
@@ -60,10 +59,11 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
this.addDocument(newBox, false);
}
private addDocument = (newBox: Doc, allowDuplicates: boolean) => {
- newBox.zoom = FieldValue(this.Document.scale, 1);
- return this.props.addDocument(this.bringToFront(newBox), false);
+ this.props.addDocument(newBox, false);
+ this.bringToFront(newBox);
+ return true;
}
- private selectDocuments = (docs: Document[]) => {
+ private selectDocuments = (docs: Doc[]) => {
SelectionManager.DeselectAll;
docs.map(doc => DocumentManager.Instance.getDocumentView(doc)).filter(dv => dv).map(dv =>
SelectionManager.SelectDoc(dv!, true));
@@ -80,23 +80,24 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
@action
drop = (e: Event, de: DragManager.DropEvent) => {
if (super.drop(e, de) && de.data instanceof DragManager.DocumentDragData) {
- const [x, y] = this.getTransform().transformPoint(de.x - de.data.xOffset, de.y - de.data.yOffset);
if (de.data.droppedDocuments.length) {
let dragDoc = de.data.droppedDocuments[0];
- let dropX = Cast(dragDoc.x, "number", 0);
- let dropY = Cast(dragDoc.y, "number", 0);
+ let zoom = NumCast(dragDoc.zoomBasis, 1);
+ let [xp, yp] = this.getTransform().transformPoint(de.x, de.y);
+ let x = xp - de.data.xOffset / zoom;
+ let y = yp - de.data.yOffset / zoom;
+ let dropX = NumCast(de.data.droppedDocuments[0].x);
+ let dropY = NumCast(de.data.droppedDocuments[0].y);
de.data.droppedDocuments.map(d => {
- d.x = x + Cast(d.x, "number", 0) - dropX;
- d.y = y + Cast(d.y, "number", 0) - dropY;
- if (!Cast(d.isMinimized, "boolean", false)) {
- if (!Cast(d.width, "number", 0)) {
- d.width = 300;
- }
- if (!Cast(d.height, "number", 0)) {
- let nw = Cast(d.nativeWidth, "number", 0);
- let nh = Cast(d.nativeHeight, "number", 0);
- d.height = nw && nh ? nh / nw * Cast(d.width, "number", 0) : 300;
- }
+ d.x = x + NumCast(d.x) - dropX;
+ d.y = y + NumCast(d.y) - dropY;
+ if (!NumCast(d.width)) {
+ d.width = 300;
+ }
+ if (!NumCast(d.height)) {
+ let nw = NumCast(d.nativeWidth);
+ let nh = NumCast(d.nativeHeight);
+ d.height = nw && nh ? nh / nw * d.Width() : 300;
}
this.bringToFront(d);
});
@@ -119,20 +120,20 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
var dv = DocumentManager.Instance.getDocumentView(doc);
return childSelected || (dv && SelectionManager.IsSelected(dv) ? true : false);
}, false);
- if (((e.button === 2 && (!this.isAnnotationOverlay || this.zoomScaling() !== 1)) || (e.button === 0 && e.altKey)) && (childSelected || this.props.active())) {
- document.removeEventListener("pointermove", this.onPointerMove);
+ if ((CollectionFreeFormView.RIGHT_BTN_DRAG &&
+ (((e.button === 2 && (!this.isAnnotationOverlay || this.zoomScaling() !== 1)) ||
+ (e.button === 0 && e.altKey)) && (childSelected || this.props.active()))) ||
+ (!CollectionFreeFormView.RIGHT_BTN_DRAG &&
+ ((e.button === 0 && !e.altKey && (!this.isAnnotationOverlay || this.zoomScaling() !== 1)) && (childSelected || this.props.active())))) {
+ this.cleanupInteractions();
document.addEventListener("pointermove", this.onPointerMove);
- document.removeEventListener("pointerup", this.onPointerUp);
document.addEventListener("pointerup", this.onPointerUp);
this._lastX = e.pageX;
this._lastY = e.pageY;
}
}
- @action
onPointerUp = (e: PointerEvent): void => {
- e.stopPropagation();
-
this.cleanupInteractions();
}
@@ -166,7 +167,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
this.setPan(x - dx, y - dy);
this._lastX = e.pageX;
this._lastY = e.pageY;
- e.stopPropagation();
+ e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document' however it does mark the event as cancelBubble=true which we test for in the move event handlers
e.preventDefault();
}
}
@@ -196,10 +197,10 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
// if (modes[e.deltaMode] === 'pixels') coefficient = 50;
// else if (modes[e.deltaMode] === 'lines') coefficient = 1000; // This should correspond to line-height??
let deltaScale = (1 - (e.deltaY / coefficient));
- if (deltaScale < 0) deltaScale = -deltaScale;
if (deltaScale * this.zoomScaling() < 1 && this.isAnnotationOverlay) {
deltaScale = 1 / this.zoomScaling();
}
+ if (deltaScale < 0) deltaScale = -deltaScale;
let [x, y] = this.getTransform().transformPoint(e.clientX, e.clientY);
let localTransform = this.getLocalTransform().inverse().scaleAbout(deltaScale, x, y);
@@ -212,7 +213,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
@action
setPan(panX: number, panY: number) {
- MainOverlayTextBox.Instance.SetTextDoc();
var scale = this.getLocalTransform().inverse().Scale;
const newPanX = Math.min((1 - 1 / scale) * this.nativeWidth, Math.max(0, panX));
const newPanY = Math.min((1 - 1 / scale) * this.nativeHeight, Math.max(0, panY));
@@ -229,13 +229,14 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
onDragOver = (): void => {
}
- @action
bringToFront(doc: Doc) {
- (this.children || []).slice().sort((doc1, doc2) => {
+ const docs = (this.children || []);
+ docs.slice().sort((doc1, doc2) => {
if (doc1 === doc) return 1;
if (doc2 === doc) return -1;
- return Cast(doc1.zIndex, "number", 0) - Cast(doc2.zIndex, "number", 0);
+ return NumCast(doc1.zIndex) - NumCast(doc2.zIndex);
}).forEach((doc, index) => doc.zIndex = index + 1);
+ doc.zIndex = docs.length + 1;
return doc;
}
@@ -249,6 +250,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
getDocumentViewProps(document: Doc): DocumentViewProps {
return {
Document: document,
+ toggleMinimized: emptyFunction,
addDocument: this.props.addDocument,
removeDocument: this.props.removeDocument,
moveDocument: this.props.moveDocument,
@@ -289,17 +291,23 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY));
}
+ private childViews = () => [...this.views, <CollectionFreeFormBackgroundView key="backgroundView" {...this.getDocumentViewProps(this.props.Document)} />];
render() {
const containerName = `collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`;
return (
<div className={containerName} ref={this.createDropTarget} onWheel={this.onPointerWheel}
+ style={{ borderRadius: "inherit" }}
onPointerDown={this.onPointerDown} onPointerMove={this.onCursorMove} onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} >
+ {/* <svg viewBox="0 0 180 18" style={{ top: "50%", opacity: 0.05, position: "absolute" }}>
+ <text y="15" >
+ {this.props.Document.Title}
+ </text>
+ </svg> */}
<MarqueeView container={this} activeDocuments={this.getActiveDocuments} selectDocuments={this.selectDocuments}
addDocument={this.addDocument} removeDocument={this.props.removeDocument} addLiveTextDocument={this.addLiveTextBox}
getContainerTransform={this.getContainerTransform} getTransform={this.getTransform}>
<CollectionFreeFormViewPannableContents centeringShiftX={this.centeringShiftX} centeringShiftY={this.centeringShiftY}
zoomScaling={this.zoomScaling} panX={this.panX} panY={this.panY}>
- <CollectionFreeFormBackgroundView {...this.getDocumentViewProps(this.props.Document)} />
<CollectionFreeFormLinksView {...this.props} key="freeformLinks">
<InkingCanvas getScreenTransform={this.getTransform} Document={this.props.Document} >
{this.childViews}
@@ -356,7 +364,7 @@ class CollectionFreeFormViewPannableContents extends React.Component<CollectionF
const panx = -this.props.panX();
const pany = -this.props.panY();
const zoom = this.props.zoomScaling();// needs to be a variable outside of the <Measure> otherwise, reactions won't fire
- return <div className="collectionfreeformview" style={{ transform: `translate(${cenx}px, ${ceny}px) scale(${zoom}, ${zoom}) translate(${panx}px, ${pany}px)` }}>
+ return <div className="collectionfreeformview" style={{ borderRadius: "inherit", transform: `translate(${cenx}px, ${ceny}px) scale(${zoom}, ${zoom}) translate(${panx}px, ${pany}px)` }}>
{this.props.children}
</div>;
}
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index bf918beba..c6681e014 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -11,9 +11,9 @@ import { undoBatch } from "../../../util/UndoManager";
import { InkingCanvas } from "../../InkingCanvas";
import { PreviewCursor } from "../../PreviewCursor";
import { CollectionFreeFormView } from "./CollectionFreeFormView";
-import { MINIMIZED_ICON_SIZE } from '../../../views/globalCssVariables.scss'
import "./MarqueeView.scss";
import React = require("react");
+import { Utils } from "../../../../Utils";
interface MarqueeViewProps {
getContainerTransform: () => Transform;
@@ -33,18 +33,13 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
@observable _lastY: number = 0;
@observable _downX: number = 0;
@observable _downY: number = 0;
- @observable _used: boolean = false;
@observable _visible: boolean = false;
- _showOnUp: boolean = false;
- static DRAG_THRESHOLD = 4;
@action
cleanupInteractions = (all: boolean = false) => {
if (all) {
document.removeEventListener("pointermove", this.onPointerMove, true);
document.removeEventListener("pointerup", this.onPointerUp, true);
- } else {
- this._used = true;
}
document.removeEventListener("keydown", this.marqueeCommand, true);
this._visible = false;
@@ -52,34 +47,25 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
@action
onKeyPress = (e: KeyboardEvent) => {
- // Mixing events between React and Native is finicky. In FormattedTextBox, we set the
- // DASHFormattedTextBoxHandled flag when a text box consumes a key press so that we can ignore
- // the keyPress here.
- //if not these keys, make a textbox if preview cursor is active!
- if (!e.ctrlKey && !e.altKey && !e.defaultPrevented && !(e as any).DASHFormattedTextBoxHandled) {
- //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" });
- this.props.addLiveTextDocument(newBox);
- PreviewCursor.Visible = false;
- e.stopPropagation();
- }
- }
- hideCursor = () => {
- document.removeEventListener("keypress", this.onKeyPress, false);
+ //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-" });
+ this.props.addLiveTextDocument(newBox);
+ e.stopPropagation();
}
@action
onPointerDown = (e: React.PointerEvent): void => {
- if (e.buttons === 1 && !e.altKey && !e.metaKey && this.props.container.props.active()) {
- this._downX = this._lastX = e.pageX;
- this._downY = this._lastY = e.pageY;
- this._used = false;
- this._showOnUp = true;
- document.removeEventListener("keypress", this.onKeyPress, false);
+ this._downX = this._lastX = e.pageX;
+ this._downY = this._lastY = e.pageY;
+ PreviewCursor.Visible = false;
+ if ((CollectionFreeFormView.RIGHT_BTN_DRAG && e.button === 0 && !e.altKey && !e.metaKey && this.props.container.props.active()) ||
+ (!CollectionFreeFormView.RIGHT_BTN_DRAG && (e.button === 2 || (e.button === 0 && e.altKey)) && this.props.container.props.active())) {
document.addEventListener("pointermove", this.onPointerMove, true);
document.addEventListener("pointerup", this.onPointerUp, true);
document.addEventListener("keydown", this.marqueeCommand, true);
}
+ if (e.altKey)
+ e.preventDefault();
}
@action
@@ -87,33 +73,41 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
this._lastX = e.pageX;
this._lastY = e.pageY;
if (!e.cancelBubble) {
- if (Math.abs(this._downX - e.clientX) > 4 || Math.abs(this._downY - e.clientY) > 4) {
- this._showOnUp = false;
- PreviewCursor.Visible = false;
- }
- if (!this._used && e.buttons === 1 && !e.altKey && !e.metaKey &&
- (Math.abs(this._lastX - this._downX) > MarqueeView.DRAG_THRESHOLD || Math.abs(this._lastY - this._downY) > MarqueeView.DRAG_THRESHOLD)) {
+ if (Math.abs(this._lastX - this._downX) > Utils.DRAG_THRESHOLD ||
+ Math.abs(this._lastY - this._downY) > Utils.DRAG_THRESHOLD) {
this._visible = true;
+ e.stopPropagation();
+ e.preventDefault();
}
- e.stopPropagation();
- e.preventDefault();
}
+ if (e.altKey)
+ e.preventDefault();
}
@action
onPointerUp = (e: PointerEvent): void => {
- this.cleanupInteractions(true);
- this._visible = false;
- if (this._showOnUp) {
- PreviewCursor.Show(this.hideCursor, this._downX, this._downY);
- document.addEventListener("keypress", this.onKeyPress, false);
- } else {
+ if (this._visible) {
let mselect = this.marqueeSelect();
if (!e.shiftKey) {
SelectionManager.DeselectAll(mselect.length ? undefined : this.props.container.props.Document);
}
this.props.selectDocuments(mselect.length ? mselect : [this.props.container.props.Document]);
}
+ this.cleanupInteractions(true);
+ if (e.altKey)
+ e.preventDefault();
+ }
+
+ @action
+ onClick = (e: React.MouseEvent): void => {
+ if (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD &&
+ Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD) {
+ PreviewCursor.Show(e.clientX, e.clientY, this.onKeyPress);
+ // let the DocumentView stopPropagation of this event when it selects this document
+ } else { // why do we get a click event when the cursor have moved a big distance?
+ // let's cut it off here so no one else has to deal with it.
+ e.stopPropagation();
+ }
}
intersectRect(r1: { left: number, top: number, width: number, height: number },
@@ -133,15 +127,17 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
@undoBatch
@action
marqueeCommand = (e: KeyboardEvent) => {
- if (e.key === "Backspace" || e.key === "Delete") {
+ 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);
}
- this.cleanupInteractions();
+ this.cleanupInteractions(true);
+ e.stopPropagation();
}
- if (e.key === "c") {
+ if (e.key === "c" || e.key === "r" || e.key === "e") {
+ e.stopPropagation();
let bounds = this.Bounds;
let selected = this.marqueeSelect().map(d => {
this.props.removeDocument(d);
@@ -152,22 +148,45 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
});
let ink = this.props.container.props.Document.GetT(KeyStore.Ink, InkField);
let inkData = ink && ink !== FieldWaiting ? ink.Data : undefined;
- //setTimeout(() => {
+ let zoomBasis = this.props.container.props.Document.GetNumber(KeyStore.Scale, 1);
let newCollection = Documents.FreeformDocument(selected, {
x: bounds.left,
y: bounds.top,
panx: 0,
pany: 0,
- width: bounds.width,
- height: bounds.height,
+ 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,
title: "a nested collection"
});
- this.props.addDocument(newCollection, false);
+
this.marqueeInkDelete(inkData);
- // }, 100);
- this.cleanupInteractions();
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()!);
+ this.props.addLiveTextDocument(summary);
+ e.preventDefault();
+ }
+ else {
+ this.props.addDocument(newCollection, false);
+ }
+ this.cleanupInteractions(true);
+ }
+ if (e.key === "s") {
+ e.stopPropagation();
+ e.preventDefault();
+ 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-" });
+ this.props.addLiveTextDocument(summary);
+ selected.map(select => summary.GetPrototype()!.CreateLink(select.GetPrototype()!));
+
+ this.cleanupInteractions(true);
}
}
@action
@@ -208,7 +227,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
let selRect = this.Bounds;
let selection: Document[] = [];
this.props.activeDocuments().map(doc => {
- var z = doc.GetNumber(KeyStore.Zoom, 1);
+ var 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;
@@ -230,7 +249,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
}
render() {
- return <div className="marqueeView" onPointerDown={this.onPointerDown}>
+ return <div className="marqueeView" style={{ borderRadius: "inherit" }} onClick={this.onClick} onPointerDown={this.onPointerDown}>
{this.props.children}
{!this._visible ? (null) : this.marqueeDiv}
</div>;