aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTyler Schicke <tyler_schicke@brown.edu>2019-04-03 20:12:06 -0400
committerTyler Schicke <tyler_schicke@brown.edu>2019-04-03 20:12:06 -0400
commitc10b9ca57e13c8de8b35f01e6c6ce82706319e4d (patch)
tree8309da408515969da55846b38a60aad724a30728
parent5889bf159ee0a0f6567683b2bb8c2475feccf9ec (diff)
parentc406c8d123ce0aa9d63fb8a4dd90adfe83d2889d (diff)
Merge and it compiles
-rw-r--r--src/client/northstar/dash-nodes/HistogramBox.tsx4
-rw-r--r--src/client/util/DragManager.ts170
-rw-r--r--src/client/util/SelectionManager.ts14
-rw-r--r--src/client/views/DocumentDecorations.scss6
-rw-r--r--src/client/views/DocumentDecorations.tsx105
-rw-r--r--src/client/views/InkingCanvas.scss17
-rw-r--r--src/client/views/InkingCanvas.tsx54
-rw-r--r--src/client/views/InkingStroke.tsx9
-rw-r--r--src/client/views/Main.tsx10
-rw-r--r--src/client/views/collections/CollectionBaseView.tsx23
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx12
-rw-r--r--src/client/views/collections/CollectionSchemaView.tsx28
-rw-r--r--src/client/views/collections/CollectionViewBase.tsx13
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx22
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx45
-rw-r--r--src/client/views/nodes/DocumentContentsView.tsx4
-rw-r--r--src/client/views/nodes/DocumentView.tsx22
-rw-r--r--src/client/views/nodes/FieldView.tsx36
-rw-r--r--src/client/views/nodes/KeyValuePair.tsx10
19 files changed, 365 insertions, 239 deletions
diff --git a/src/client/northstar/dash-nodes/HistogramBox.tsx b/src/client/northstar/dash-nodes/HistogramBox.tsx
index 4457c9502..5938bf9b1 100644
--- a/src/client/northstar/dash-nodes/HistogramBox.tsx
+++ b/src/client/northstar/dash-nodes/HistogramBox.tsx
@@ -54,7 +54,7 @@ export class HistogramBox extends React.Component<FieldViewProps> {
@action
dropX = (e: Event, de: DragManager.DropEvent) => {
if (de.data instanceof DragManager.DocumentDragData) {
- let h = de.data.draggedDocument.GetT(KeyStore.Data, HistogramField);
+ let h = de.data.draggedDocuments[0].GetT(KeyStore.Data, HistogramField);
if (h && h != FieldWaiting) {
this.HistoOp.X = h.Data.X;
}
@@ -65,7 +65,7 @@ export class HistogramBox extends React.Component<FieldViewProps> {
@action
dropY = (e: Event, de: DragManager.DropEvent) => {
if (de.data instanceof DragManager.DocumentDragData) {
- let h = de.data.draggedDocument.GetT(KeyStore.Data, HistogramField);
+ let h = de.data.draggedDocuments[0].GetT(KeyStore.Data, HistogramField);
if (h && h != FieldWaiting) {
this.HistoOp.Y = h.Data.X;
}
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 53bbae18d..96c965c23 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -14,9 +14,9 @@ export function setupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc:
document.removeEventListener("pointermove", onRowMove);
document.removeEventListener('pointerup', onRowUp);
- var dragData = new DragManager.DocumentDragData(docFunc());
+ var dragData = new DragManager.DocumentDragData([docFunc()]);
dragData.removeDocument = removeFunc;
- DragManager.StartDocumentDrag(_reference.current!, dragData);
+ DragManager.StartDocumentDrag([_reference.current!], dragData);
});
let onRowUp = action((e: PointerEvent): void => {
document.removeEventListener("pointermove", onRowMove);
@@ -27,7 +27,7 @@ export function setupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc:
if (e.button == 0) {
e.stopPropagation();
if (e.shiftKey) {
- CollectionDockingView.Instance.StartOtherDrag(docFunc(), e);
+ CollectionDockingView.Instance.StartOtherDrag([docFunc()], e);
} else {
document.addEventListener("pointermove", onRowMove);
document.addEventListener('pointerup', onRowUp);
@@ -101,20 +101,21 @@ export namespace DragManager {
}
export class DocumentDragData {
- constructor(dragDoc: Document) {
- this.draggedDocument = dragDoc;
- this.droppedDocument = dragDoc;
+ constructor(dragDoc: Document[]) {
+ this.draggedDocuments = dragDoc;
+ this.droppedDocuments = dragDoc;
}
- draggedDocument: Document;
- droppedDocument: Document;
+ draggedDocuments: Document[];
+ droppedDocuments: Document[];
xOffset?: number;
yOffset?: number;
aliasOnDrop?: boolean;
- moveDocument?: (targetCollection: Document, addDocument: (document: Document) => void) => void;
+ moveDocument?: (document: Document, targetCollection: Document, addDocument: (document: Document) => boolean) => boolean;
[id: string]: any;
}
- export function StartDocumentDrag(ele: HTMLElement, dragData: DocumentDragData, options?: DragOptions) {
- StartDrag(ele, dragData, options, (dropData: { [id: string]: any }) => dropData.droppedDocument = dragData.aliasOnDrop ? dragData.draggedDocument.CreateAlias() : dragData.draggedDocument);
+
+ export function StartDocumentDrag(eles: HTMLElement[], dragData: DocumentDragData, options?: DragOptions) {
+ StartDrag(eles, dragData, options, (dropData: { [id: string]: any }) => dropData.droppedDocuments = dragData.aliasOnDrop ? dragData.draggedDocuments.map(d => d.CreateAlias()) : dragData.draggedDocuments);
}
export class LinkDragData {
@@ -125,49 +126,58 @@ export namespace DragManager {
[id: string]: any;
}
export function StartLinkDrag(ele: HTMLElement, dragData: LinkDragData, options?: DragOptions) {
- StartDrag(ele, dragData, options);
+ StartDrag([ele], dragData, options);
}
- function StartDrag(ele: HTMLElement, dragData: { [id: string]: any }, options?: DragOptions, finishDrag?: (dropData: { [id: string]: any }) => void) {
+ function StartDrag(eles: HTMLElement[], dragData: { [id: string]: any }, options?: DragOptions, finishDrag?: (dropData: { [id: string]: any }) => void) {
if (!dragDiv) {
dragDiv = document.createElement("div");
dragDiv.className = "dragManager-dragDiv"
DragManager.Root().appendChild(dragDiv);
}
- const w = ele.offsetWidth, h = ele.offsetHeight;
- const rect = ele.getBoundingClientRect();
- const scaleX = rect.width / w, scaleY = rect.height / h;
- let x = rect.left, y = rect.top;
- // const offsetX = e.x - rect.left, offsetY = e.y - rect.top;
-
- let dragElement = ele.cloneNode(true) as HTMLElement;
- dragElement.style.opacity = "0.7";
- dragElement.style.position = "absolute";
- dragElement.style.bottom = "";
- dragElement.style.left = "";
- dragElement.style.transformOrigin = "0 0";
- dragElement.style.zIndex = "1000";
- dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`;
- dragElement.style.width = `${rect.width / scaleX}px`;
- dragElement.style.height = `${rect.height / scaleY}px`;
-
- // bcz: PDFs don't show up if you clone them because they contain a canvas.
- // however, PDF's have a thumbnail field that contains an image of their canvas.
- // So we replace the pdf's canvas with the image thumbnail
- const doc: Document = dragData["draggedDocument"];
- if (doc) {
- var pdfBox = dragElement.getElementsByClassName("pdfBox-cont")[0] as HTMLElement;
- let thumbnail = doc.GetT(KeyStore.Thumbnail, ImageField);
- if (pdfBox && pdfBox.childElementCount && thumbnail) {
- let img = new Image();
- img!.src = thumbnail.toString();
- img!.style.position = "absolute";
- img!.style.width = `${rect.width / scaleX}px`;
- img!.style.height = `${rect.height / scaleY}px`;
- pdfBox.replaceChild(img!, pdfBox.children[0])
+
+ let scaleXs: number[] = [];
+ let scaleYs: number[] = [];
+ let xs: number[] = [];
+ let ys: number[] = [];
+
+ const docs: Document[] = dragData instanceof DocumentDragData ? dragData.draggedDocuments : [];
+ let dragElements = eles.map(ele => {
+ const w = ele.offsetWidth, h = ele.offsetHeight;
+ const rect = ele.getBoundingClientRect();
+ const scaleX = rect.width / w, scaleY = rect.height / h;
+ let x = rect.left, y = rect.top;
+ xs.push(x); ys.push(y);
+ scaleXs.push(scaleX); scaleYs.push(scaleY);
+ let dragElement = ele.cloneNode(true) as HTMLElement;
+ dragElement.style.opacity = "0.7";
+ dragElement.style.position = "absolute";
+ dragElement.style.bottom = "";
+ dragElement.style.left = "";
+ dragElement.style.transformOrigin = "0 0";
+ dragElement.style.zIndex = "1000";
+ dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`;
+ dragElement.style.width = `${rect.width / scaleX}px`;
+ dragElement.style.height = `${rect.height / scaleY}px`;
+
+ // bcz: PDFs don't show up if you clone them because they contain a canvas.
+ // however, PDF's have a thumbnail field that contains an image of their canvas.
+ // So we replace the pdf's canvas with the image thumbnail
+ if (docs.length) {
+ var pdfBox = dragElement.getElementsByClassName("pdfBox-cont")[0] as HTMLElement;
+ let thumbnail = docs[0].GetT(KeyStore.Thumbnail, ImageField);
+ if (pdfBox && pdfBox.childElementCount && thumbnail) {
+ let img = new Image();
+ img!.src = thumbnail.toString();
+ img!.style.position = "absolute";
+ img!.style.width = `${rect.width / scaleX}px`;
+ img!.style.height = `${rect.height / scaleY}px`;
+ pdfBox.replaceChild(img!, pdfBox.children[0])
+ }
}
- }
- dragDiv.appendChild(dragElement);
+ dragDiv.appendChild(dragElement);
+ return dragElement;
+ });
let hideSource = false;
if (options) {
@@ -177,62 +187,64 @@ export namespace DragManager {
hideSource = options.hideSource();
}
}
- const wasHidden = ele.hidden;
- if (hideSource) {
- ele.hidden = true;
- }
+ eles.map(ele => ele.hidden = hideSource);
+
const moveHandler = (e: PointerEvent) => {
e.stopPropagation();
e.preventDefault();
- x += e.movementX;
- y += e.movementY;
if (dragData instanceof DocumentDragData)
dragData.aliasOnDrop = e.ctrlKey || e.altKey;
if (e.shiftKey) {
abortDrag();
- CollectionDockingView.Instance.StartOtherDrag(doc, { pageX: e.pageX, pageY: e.pageY, preventDefault: () => { }, button: 0 });
+ CollectionDockingView.Instance.StartOtherDrag(docs, { pageX: e.pageX, pageY: e.pageY, preventDefault: () => { }, button: 0 });
}
- dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`;
+ dragElements.map((dragElement, i) => dragElement.style.transform = `translate(${xs[i] += e.movementX}px, ${ys[i] += e.movementY}px) scale(${scaleXs[i]}, ${scaleYs[i]})`);
};
const abortDrag = () => {
document.removeEventListener("pointermove", moveHandler, true);
document.removeEventListener("pointerup", upHandler);
- dragDiv.removeChild(dragElement);
- ele.hidden = false;
+ dragElements.map(dragElement => dragDiv.removeChild(dragElement));
+ eles.map(ele => ele.hidden = false);
}
const upHandler = (e: PointerEvent) => {
abortDrag();
- FinishDrag(ele, e, dragData, options, finishDrag);
+ FinishDrag(eles, e, dragData, options, finishDrag);
};
document.addEventListener("pointermove", moveHandler, true);
document.addEventListener("pointerup", upHandler);
}
- function FinishDrag(dragEle: HTMLElement, e: PointerEvent, dragData: { [index: string]: any }, options?: DragOptions, finishDrag?: (dragData: { [index: string]: any }) => void) {
- let parent = dragEle.parentElement;
- if (parent)
- parent.removeChild(dragEle);
+ function FinishDrag(dragEles: HTMLElement[], e: PointerEvent, dragData: { [index: string]: any }, options?: DragOptions, finishDrag?: (dragData: { [index: string]: any }) => void) {
+ let removed = dragEles.map(dragEle => {
+ let parent = dragEle.parentElement;
+ if (parent)
+ parent.removeChild(dragEle);
+ return [dragEle, parent];
+ });
const target = document.elementFromPoint(e.x, e.y);
- if (parent)
- parent.appendChild(dragEle);
- if (!target) {
- return;
- }
- if (finishDrag)
- finishDrag(dragData);
-
- target.dispatchEvent(new CustomEvent<DropEvent>("dashOnDrop", {
- bubbles: true,
- detail: {
- x: e.x,
- y: e.y,
- data: dragData
+ removed.map(r => {
+ let dragEle: HTMLElement = r[0]!;
+ let parent: HTMLElement | null = r[1];
+ if (parent)
+ parent.appendChild(dragEle);
+ });
+ if (target) {
+ if (finishDrag)
+ finishDrag(dragData);
+
+ target.dispatchEvent(new CustomEvent<DropEvent>("dashOnDrop", {
+ bubbles: true,
+ detail: {
+ x: e.x,
+ y: e.y,
+ data: dragData
+ }
+ }));
+
+ if (options) {
+ options.handlers.dragComplete({});
}
- }));
-
- if (options) {
- options.handlers.dragComplete({});
}
DocumentDecorations.Instance.Hidden = false;
}
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 6d6ae26fc..05810b61c 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -11,13 +11,20 @@ export namespace SelectionManager {
SelectDoc(doc: DocumentView, ctrlPressed: boolean): void {
// if doc is not in SelectedDocuments, add it
if (!ctrlPressed) {
- manager.SelectedDocuments = [];
+ this.DeselectAll();
}
if (manager.SelectedDocuments.indexOf(doc) === -1) {
manager.SelectedDocuments.push(doc)
+ doc.props.onActiveChanged(true);
}
}
+
+ @action
+ DeselectAll(): void {
+ manager.SelectedDocuments.map(dv => dv.props.onActiveChanged(false))
+ manager.SelectedDocuments = [];
+ }
}
const manager = new Manager;
@@ -39,7 +46,10 @@ export namespace SelectionManager {
found = view;
}
}
- manager.SelectedDocuments.length = 0;
+
+ manager.DeselectAll()
+ if (found)
+ manager.SelectDoc(found, false);
}
export function SelectedDocuments(): Array<DocumentView> {
diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss
index 11595aa01..7a43f3087 100644
--- a/src/client/views/DocumentDecorations.scss
+++ b/src/client/views/DocumentDecorations.scss
@@ -32,6 +32,12 @@
}
}
+.documentDecorations-background {
+ background:lightblue;
+ position: absolute;
+ opacity: 0.1;
+}
+
// position: absolute;
// display: grid;
// z-index: 1000;
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 47098c3b5..d0699e1ab 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -1,14 +1,14 @@
-import { observable, computed, action } from "mobx";
-import React = require("react");
-import { SelectionManager } from "../util/SelectionManager";
+import { action, computed, observable, trace } from "mobx";
import { observer } from "mobx-react";
-import './DocumentDecorations.scss'
-import { KeyStore } from '../../fields/KeyStore'
+import { KeyStore } from '../../fields/KeyStore';
+import { ListField } from "../../fields/ListField";
import { NumberField } from "../../fields/NumberField";
-import { props } from "bluebird";
import { DragManager } from "../util/DragManager";
+import { SelectionManager } from "../util/SelectionManager";
+import { CollectionView } from "./collections/CollectionView";
+import './DocumentDecorations.scss';
import { LinkMenu } from "./nodes/LinkMenu";
-import { ListField } from "../../fields/ListField";
+import React = require("react");
const higflyout = require("@hig/flyout");
export const { anchorPoints } = higflyout;
export const Flyout = higflyout.default;
@@ -22,6 +22,7 @@ export class DocumentDecorations extends React.Component {
private _resizeBorderWidth = 16;
private _linkButton = React.createRef<HTMLDivElement>();
@observable private _hidden = false;
+ @observable private _dragging = false;
constructor(props: Readonly<{}>) {
super(props)
@@ -50,6 +51,46 @@ export class DocumentDecorations extends React.Component {
public get Hidden() { return this._hidden; }
public set Hidden(value: boolean) { this._hidden = value; }
+ _lastDrag: number[] = [0, 0];
+ onBackgroundDown = (e: React.PointerEvent): void => {
+ document.removeEventListener("pointermove", this.onBackgroundMove);
+ document.addEventListener("pointermove", this.onBackgroundMove);
+ document.removeEventListener("pointerup", this.onBackgroundUp);
+ document.addEventListener("pointerup", this.onBackgroundUp);
+ this._lastDrag = [e.clientX, e.clientY]
+ e.stopPropagation();
+ e.preventDefault();
+ }
+
+ @action
+ onBackgroundMove = (e: PointerEvent): void => {
+ let dragDocView = SelectionManager.SelectedDocuments()[0];
+ const [left, top] = dragDocView.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
+ let dragData = new DragManager.DocumentDragData(SelectionManager.SelectedDocuments().map(dv => dv.props.Document));
+ dragData.aliasOnDrop = false;
+ dragData.xOffset = e.x - left;
+ dragData.yOffset = e.y - top;
+ let move = SelectionManager.SelectedDocuments()[0].props.moveDocument;
+ dragData.moveDocument = move;
+ this._dragging = true;
+ document.removeEventListener("pointermove", this.onBackgroundMove);
+ document.removeEventListener("pointerup", this.onBackgroundUp);
+ DragManager.StartDocumentDrag(SelectionManager.SelectedDocuments().map(docView => (docView as any)._mainCont!.current!), dragData, {
+ handlers: {
+ dragComplete: action(() => this._dragging = false),
+ },
+ hideSource: true
+ })
+ e.stopPropagation();
+ }
+
+ onBackgroundUp = (e: PointerEvent): void => {
+ document.removeEventListener("pointermove", this.onBackgroundMove);
+ document.removeEventListener("pointerup", this.onBackgroundUp);
+ e.stopPropagation();
+ e.preventDefault();
+ }
+
onPointerDown = (e: React.PointerEvent): void => {
e.stopPropagation();
if (e.button === 0) {
@@ -191,7 +232,6 @@ export class DocumentDecorations extends React.Component {
// buttonOnPointerUp = (e: React.PointerEvent): void => {
// e.stopPropagation();
// }
-
render() {
var bounds = this.Bounds;
if (this.Hidden) {
@@ -218,25 +258,36 @@ export class DocumentDecorations extends React.Component {
</Flyout>);
}
return (
- <div id="documentDecorations-container" style={{
- width: (bounds.r - bounds.x + this._resizeBorderWidth) + "px",
- height: (bounds.b - bounds.y + this._resizeBorderWidth + 30) + "px",
- left: bounds.x - this._resizeBorderWidth / 2,
- top: bounds.y - this._resizeBorderWidth / 2,
- }}>
- <div id="documentDecorations-topLeftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
- <div id="documentDecorations-topResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
- <div id="documentDecorations-topRightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
- <div id="documentDecorations-leftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
- <div id="documentDecorations-centerCont"></div>
- <div id="documentDecorations-rightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
- <div id="documentDecorations-bottomLeftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
- <div id="documentDecorations-bottomResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
- <div id="documentDecorations-bottomRightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
-
- <div title="View Links" className="linkFlyout" ref={this._linkButton}>{linkButton}</div>
-
- </div >
+ <div className="documentDecorations">
+ <div className="documentDecorations-background" style={{
+ width: (bounds.r - bounds.x + this._resizeBorderWidth) + "px",
+ height: (bounds.b - bounds.y + this._resizeBorderWidth) + "px",
+ left: bounds.x - this._resizeBorderWidth / 2,
+ top: bounds.y - this._resizeBorderWidth / 2,
+ pointerEvents: this._dragging ? "none" : "all",
+ zIndex: SelectionManager.SelectedDocuments().length > 1 ? 1000 : 0,
+ }} onPointerDown={this.onBackgroundDown} onContextMenu={(e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation() }} >
+ </div>
+ <div id="documentDecorations-container" style={{
+ width: (bounds.r - bounds.x + this._resizeBorderWidth) + "px",
+ height: (bounds.b - bounds.y + this._resizeBorderWidth + 30) + "px",
+ left: bounds.x - this._resizeBorderWidth / 2,
+ top: bounds.y - this._resizeBorderWidth / 2,
+ }}>
+ <div id="documentDecorations-topLeftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
+ <div id="documentDecorations-topResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
+ <div id="documentDecorations-topRightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
+ <div id="documentDecorations-leftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
+ <div id="documentDecorations-centerCont"></div>
+ <div id="documentDecorations-rightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
+ <div id="documentDecorations-bottomLeftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
+ <div id="documentDecorations-bottomResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
+ <div id="documentDecorations-bottomRightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
+
+ <div title="View Links" className="linkFlyout" ref={this._linkButton}>{linkButton}</div>
+
+ </div >
+ </div>
)
}
} \ No newline at end of file
diff --git a/src/client/views/InkingCanvas.scss b/src/client/views/InkingCanvas.scss
index 214c70280..35c8ee942 100644
--- a/src/client/views/InkingCanvas.scss
+++ b/src/client/views/InkingCanvas.scss
@@ -2,18 +2,19 @@
.inkingCanvas-paths-ink, .inkingCanvas-paths-markers, .inkingCanvas-noSelect, .inkingCanvas-canSelect {
position: absolute;
- top: -50000px;
- left: -50000px;
- width: 100000px;
- height: 100000px;
- .inkingCanvas-children {
- transform: translate(50000px, 50000px);
- pointer-events: none;
- }
+ width: 8192px;
+ height: 8192px;
cursor:"crosshair";
pointer-events: auto;
}
+.inkingCanvas-canSelect,
+.inkingCanvas-noSelect {
+ top:-50000px;
+ left:-50000px;
+ width: 100000px;
+ height: 100000px;
+}
.inkingCanvas-noSelect {
pointer-events: none;
cursor: "arrow";
diff --git a/src/client/views/InkingCanvas.tsx b/src/client/views/InkingCanvas.tsx
index 123ff679b..cad4b74b1 100644
--- a/src/client/views/InkingCanvas.tsx
+++ b/src/client/views/InkingCanvas.tsx
@@ -1,4 +1,4 @@
-import { action, computed, trace } from "mobx";
+import { action, computed, trace, observable, runInAction } from "mobx";
import { observer } from "mobx-react";
import { Document } from "../../fields/Document";
import { FieldWaiting } from "../../fields/Field";
@@ -14,26 +14,40 @@ import React = require("react");
interface InkCanvasProps {
getScreenTransform: () => Transform;
Document: Document;
+ children: () => JSX.Element[];
}
@observer
export class InkingCanvas extends React.Component<InkCanvasProps> {
- static InkOffset: number = 50000;
+ maxCanvasDim = 8192 / 2; // 1/2 of the maximum canvas dimension for Chrome
+ @observable inkMidX: number = 0;
+ @observable inkMidY: number = 0;
private _currentStrokeId: string = "";
public static IntersectStrokeRect(stroke: StrokeData, selRect: { left: number, top: number, width: number, height: number }): boolean {
- return stroke.pathData.reduce((inside, val) => inside ||
- (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)
+ return stroke.pathData.reduce((inside: boolean, val) => inside ||
+ (selRect.left < val.x && selRect.left + selRect.width > val.x &&
+ selRect.top < val.y && selRect.top + selRect.height > val.y)
, false);
}
+ componentDidMount() {
+ this.props.Document.GetTAsync(KeyStore.Ink, InkField, ink => runInAction(() => {
+ if (ink) {
+ let bounds = Array.from(ink.Data).reduce(([mix, max, miy, may], [id, strokeData]) =>
+ strokeData.pathData.reduce(([mix, max, miy, may], p) =>
+ [Math.min(mix, p.x), Math.max(max, p.x), Math.min(miy, p.y), Math.max(may, p.y)],
+ [mix, max, miy, may]),
+ [Number.MAX_VALUE, Number.MIN_VALUE, Number.MAX_VALUE, Number.MIN_VALUE]);
+ this.inkMidX = (bounds[0] + bounds[1]) / 2;
+ this.inkMidY = (bounds[2] + bounds[3]) / 2;
+ }
+ }));
+ }
+
@computed
get inkData(): StrokeMap {
let map = this.props.Document.GetT(KeyStore.Ink, InkField);
- if (!map || map === FieldWaiting) {
- return new Map;
- }
- return new Map(map.Data);
+ return !map || map === FieldWaiting ? new Map : new Map(map.Data);
}
set inkData(value: StrokeMap) {
@@ -63,9 +77,15 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
}
}
+ @action
onPointerUp = (e: PointerEvent): void => {
document.removeEventListener("pointermove", this.onPointerMove, true);
document.removeEventListener("pointerup", this.onPointerUp, true);
+ let coord = this.relativeCoordinatesForEvent(e.clientX, e.clientY);
+ if (Math.abs(coord.x - this.inkMidX) > 500 || Math.abs(coord.y - this.inkMidY) > 500) {
+ this.inkMidX = coord.x;
+ this.inkMidY = coord.y;
+ }
e.stopPropagation();
e.preventDefault();
}
@@ -87,8 +107,6 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
relativeCoordinatesForEvent = (ex: number, ey: number): { x: number, y: number } => {
let [x, y] = this.props.getScreenTransform().transformPoint(ex, ey);
- x += InkingCanvas.InkOffset;
- y += InkingCanvas.InkOffset;
return { x, y };
}
@@ -101,30 +119,32 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
@computed
get drawnPaths() {
- // parse data from server
let curPage = this.props.Document.GetNumber(KeyStore.CurPage, -1)
let paths = Array.from(this.inkData).reduce((paths, [id, strokeData]) => {
if (strokeData.page == -1 || strokeData.page == curPage)
paths.push(<InkingStroke key={id} id={id} line={strokeData.pathData}
+ offsetX={this.maxCanvasDim - this.inkMidX}
+ offsetY={this.maxCanvasDim - this.inkMidY}
color={strokeData.color} width={strokeData.width}
tool={strokeData.tool} deleteCallback={this.removeLine} />)
return paths;
}, [] as JSX.Element[]);
- return [<svg className={`inkingCanvas-paths-markers`} key="Markers" >
+ return [<svg className={`inkingCanvas-paths-markers`} key="Markers"
+ style={{ left: `${this.inkMidX - this.maxCanvasDim}px`, top: `${this.inkMidY - this.maxCanvasDim}px` }} >
{paths.filter(path => path.props.tool == InkTool.Highlighter)}
</svg>,
- <svg className={`inkingCanvas-paths-ink`} key="Pens" >
+ <svg className={`inkingCanvas-paths-ink`} key="Pens"
+ style={{ left: `-${this.inkMidX - this.maxCanvasDim}px`, top: `-${this.inkMidY - this.maxCanvasDim}px` }}>
{paths.filter(path => path.props.tool != InkTool.Highlighter)}
</svg>];
}
render() {
let svgCanvasStyle = InkingControl.Instance.selectedTool != InkTool.None ? "canSelect" : "noSelect";
-
return (
<div className="inkingCanvas" >
- <svg className={`inkingCanvas-${svgCanvasStyle}`} onPointerDown={this.onPointerDown} />
- {(this.props.children as any)() /* bcz: is there a better way to know that children is a function? */}
+ <div className={`inkingCanvas-${svgCanvasStyle}`} onPointerDown={this.onPointerDown} />
+ {this.props.children()}
{this.drawnPaths}
</div >
)
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 52111c711..615f8af7e 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -6,6 +6,8 @@ import React = require("react");
interface StrokeProps {
+ offsetX: number;
+ offsetY: number;
id: string;
line: Array<{ x: number, y: number }>;
color: string;
@@ -28,7 +30,7 @@ export class InkingStroke extends React.Component<StrokeProps> {
}
parseData = (line: Array<{ x: number, y: number }>): string => {
- return !line.length ? "" : "M " + line.map(p => p.x + " " + p.y).join(" L ");
+ return !line.length ? "" : "M " + line.map(p => (p.x + this.props.offsetX) + " " + (p.y + this.props.offsetY)).join(" L ");
}
createStyle() {
@@ -43,14 +45,13 @@ export class InkingStroke extends React.Component<StrokeProps> {
}
}
-
render() {
let pathStyle = this.createStyle();
let pathData = this.parseData(this.props.line);
+ let pointerEvents: any = InkingControl.Instance.selectedTool == InkTool.Eraser ? "all" : "none";
return (
- <path className={(this._strokeTool === InkTool.Highlighter) ? "highlight" : ""}
- d={pathData} style={{ ...pathStyle, pointerEvents: "all" }} strokeLinejoin="round" strokeLinecap="round"
+ <path d={pathData} style={{ ...pathStyle, pointerEvents: pointerEvents }} strokeLinejoin="round" strokeLinecap="round"
onPointerOver={this.deleteStroke} onPointerDown={this.deleteStroke} />
)
}
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index bcbe6b987..8f67c006d 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -6,7 +6,7 @@ import { Document } from '../../fields/Document';
import { KeyStore } from '../../fields/KeyStore';
import "./Main.scss";
import { MessageStore } from '../../server/Message';
-import { Utils, returnTrue } from '../../Utils';
+import { Utils, returnTrue, emptyFunction } from '../../Utils';
import * as request from 'request'
import * as rp from 'request-promise'
import { Documents } from '../documents/Documents';
@@ -217,7 +217,8 @@ export class Main extends React.Component {
focusDocument = (doc: Document) => { }
noScaling = () => 1;
- get content() {
+ @computed
+ get mainContent() {
return !this.mainContainer ? (null) :
<DocumentView Document={this.mainContainer}
addDocument={undefined}
@@ -230,6 +231,7 @@ export class Main extends React.Component {
selectOnLoad={false}
focus={this.focusDocument}
parentActive={returnTrue}
+ onActiveChanged={emptyFunction}
ContainingCollectionView={undefined} />
}
@@ -311,17 +313,17 @@ export class Main extends React.Component {
}
return (
<div id="main-div">
+ <DocumentDecorations />
<Measure onResize={(r: any) => runInAction(() => {
this.pwidth = r.entry.width;
this.pheight = r.entry.height;
})}>
{({ measureRef }) =>
<div ref={measureRef} id="mainContent-div">
- {this.content}
+ {this.mainContent}
</div>
}
</Measure>
- <DocumentDecorations />
<ContextMenu />
{this.nodesMenu}
{this.miscButtons}
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index c9f640c4a..301467d99 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -21,8 +21,9 @@ export enum CollectionViewType {
export interface CollectionRenderProps {
addDocument: (document: Document, allowDuplicates?: boolean) => boolean;
removeDocument: (document: Document) => boolean;
- moveDocument: (document: Document, targetCollection: Document, addDocument: (document: Document) => void) => boolean;
+ moveDocument: (document: Document, targetCollection: Document, addDocument: (document: Document) => boolean) => boolean;
active: () => boolean;
+ onActiveChanged: (isActive: boolean) => void;
}
export interface CollectionViewProps extends FieldViewProps {
@@ -49,9 +50,15 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
active = (): boolean => {
var isSelected = this.props.isSelected();
- var childSelected = SelectionManager.SelectedDocuments().some(view => view.props.ContainingCollectionView == this);
var topMost = this.props.isTopMost;
- return isSelected || childSelected || topMost;
+ return isSelected || this._isChildActive || topMost;
+ }
+
+ //TODO should this be observable?
+ private _isChildActive = false;
+ onActiveChanged = (isActive: boolean) => {
+ this._isChildActive = isActive;
+ this.props.onActiveChanged(isActive);
}
createsCycle(documentToAdd: Document, containerDocument: Document): boolean {
@@ -121,7 +128,7 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
if (index !== -1) {
value.splice(index, 1)
- SelectionManager.DeselectAll()
+ // SelectionManager.DeselectAll()
ContextMenu.Instance.clearItems()
return true;
}
@@ -129,13 +136,12 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
}
@action.bound
- moveDocument(doc: Document, targetCollection: Document, addDocument: (doc: Document) => void): boolean {
+ moveDocument(doc: Document, targetCollection: Document, addDocument: (doc: Document) => boolean): boolean {
if (this.props.Document === targetCollection) {
return false;
}
if (this.removeDocument(doc)) {
- addDocument(doc);
- return true;
+ return addDocument(doc);
}
return false;
}
@@ -145,7 +151,8 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
addDocument: this.addDocument,
removeDocument: this.removeDocument,
moveDocument: this.moveDocument,
- active: this.active
+ active: this.active,
+ onActiveChanged: this.onActiveChanged,
}
return (
<div className={this.props.className || "collectionView-cont"} onContextMenu={this.props.onContextMenu} ref={this.props.contentRef}>
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index bb34340fb..1b0ad0bee 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -8,7 +8,7 @@ import { Document } from "../../../fields/Document";
import { KeyStore } from "../../../fields/KeyStore";
import Measure from "react-measure";
import { FieldId, Opt, Field } from "../../../fields/Field";
-import { Utils, returnTrue } from "../../../Utils";
+import { Utils, returnTrue, emptyFunction } from "../../../Utils";
import { Server } from "../../Server";
import { undoBatch } from "../../util/UndoManager";
import { DocumentView } from "../nodes/DocumentView";
@@ -47,9 +47,10 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
(window as any).React = React;
(window as any).ReactDOM = ReactDOM;
}
- public StartOtherDrag(dragDoc: Document, e: any) {
- this.AddRightSplit(dragDoc, true).contentItems[0].tab._dragListener.
- onMouseDown({ pageX: e.pageX, pageY: e.pageY, preventDefault: () => { }, button: 0 })
+ public StartOtherDrag(dragDocs: Document[], e: any) {
+ dragDocs.map(dragDoc =>
+ this.AddRightSplit(dragDoc, true).contentItems[0].tab._dragListener.
+ onMouseDown({ pageX: e.pageX, pageY: e.pageY, preventDefault: () => { }, button: 0 }));
}
@action
@@ -199,7 +200,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
let tab = (e.target as any).parentElement as HTMLElement;
Server.GetField(docid, action((f: Opt<Field>) => {
if (f instanceof Document)
- DragManager.StartDocumentDrag(tab, new DragManager.DocumentDragData(f as Document),
+ DragManager.StartDocumentDrag([tab], new DragManager.DocumentDragData([f as Document]),
{
handlers: {
dragComplete: action(() => { }),
@@ -319,6 +320,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
isTopMost={true}
selectOnLoad={false}
parentActive={returnTrue}
+ onActiveChanged={emptyFunction}
focus={(doc: Document) => { }}
ContainingCollectionView={undefined} />
</div>
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 0eacd38b0..78a813a99 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -83,7 +83,8 @@ export class CollectionSchemaView extends CollectionViewBase {
selectOnLoad: false,
ScreenToLocalTransform: Transform.Identity,
focus: emptyFunction,
- active: returnFalse
+ active: returnFalse,
+ onActiveChanged: emptyFunction,
}
let contents = (
<FieldView {...props} />
@@ -299,18 +300,19 @@ export class CollectionSchemaView extends CollectionViewBase {
<Measure onResize={this.setScaling}>
{({ measureRef }) =>
<div className="collectionSchemaView-content" ref={measureRef}>
- {doc instanceof Document ? <DocumentView Document={doc}
- addDocument={this.props.addDocument} removeDocument={this.props.removeDocument}
- isTopMost={false}
- selectOnLoad={false}
- ScreenToLocalTransform={this.getPreviewTransform}
- ContentScaling={this.getContentScaling}
- PanelWidth={this.getPanelWidth}
- PanelHeight={this.getPanelHeight}
- ContainingCollectionView={undefined}
- focus={this.focusDocument}
- parentActive={this.props.active}
- /> : null}
+ {doc instanceof Document ?
+ <DocumentView Document={doc}
+ addDocument={this.props.addDocument} removeDocument={this.props.removeDocument}
+ isTopMost={false}
+ selectOnLoad={false}
+ ScreenToLocalTransform={this.getPreviewTransform}
+ ContentScaling={this.getContentScaling}
+ PanelWidth={this.getPanelWidth}
+ PanelHeight={this.getPanelHeight}
+ ContainingCollectionView={undefined}
+ focus={this.focusDocument}
+ parentActive={this.props.active}
+ onActiveChanged={this.props.onActiveChanged} /> : null}
<input value={this.previewScript} onChange={this.onPreviewScriptChange}
style={{ position: 'absolute', bottom: '0px' }} />
</div>
diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx
index 4a0b2312e..71a639137 100644
--- a/src/client/views/collections/CollectionViewBase.tsx
+++ b/src/client/views/collections/CollectionViewBase.tsx
@@ -22,7 +22,7 @@ import { FieldViewProps } from "../nodes/FieldView";
export interface CollectionViewProps extends FieldViewProps {
addDocument: (document: Document, allowDuplicates?: boolean) => boolean;
removeDocument: (document: Document) => boolean;
- moveDocument: (document: Document, targetCollection: Document, addDocument: (document: Document) => void) => boolean;
+ moveDocument: (document: Document, targetCollection: Document, addDocument: (document: Document) => boolean) => boolean;
}
export interface SubCollectionViewProps extends CollectionViewProps {
@@ -72,11 +72,14 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
if (de.data instanceof DragManager.DocumentDragData) {
if (de.data.aliasOnDrop) {
[KeyStore.Width, KeyStore.Height, KeyStore.CurPage].map(key =>
- de.data.draggedDocument.GetTAsync(key, NumberField, (f: Opt<NumberField>) => f ? de.data.droppedDocument.SetNumber(key, f.Data) : null));
+ de.data.draggedDocuments.GetTAsync(key, NumberField, (f: Opt<NumberField>) => f ? de.data.droppedDocument.SetNumber(key, f.Data) : null));
}
- let added = this.props.addDocument(de.data.droppedDocument, false);
- if (added && de.data.moveDocument && !de.data.aliasOnDrop) {
- de.data.moveDocument(this.props.Document, this.props.addDocument);
+ let added = false;
+ if (de.data.aliasOnDrop) {
+ added = de.data.droppedDocuments.reduce((added, d) => added || this.props.addDocument(d), false);
+ } else if (de.data.moveDocument) {
+ const move = de.data.moveDocument;
+ added = de.data.droppedDocuments.reduce((added, d) => added || move(d, this.props.Document, this.props.addDocument), false)
}
e.stopPropagation();
return added;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 144d121db..b04438ede 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -86,13 +86,20 @@ export class CollectionFreeFormView extends CollectionViewBase {
let screenX = de.x - (de.data.xOffset as number || 0);
let screenY = de.y - (de.data.yOffset as number || 0);
const [x, y] = this.getTransform().transformPoint(screenX, screenY);
- de.data.droppedDocument.SetNumber(KeyStore.X, x);
- de.data.droppedDocument.SetNumber(KeyStore.Y, y);
- if (!de.data.droppedDocument.GetNumber(KeyStore.Width, 0)) {
- de.data.droppedDocument.SetNumber(KeyStore.Width, 300);
- de.data.droppedDocument.SetNumber(KeyStore.Height, 300);
- }
- this.bringToFront(de.data.droppedDocument);
+ let dragDoc = de.data.draggedDocuments[0];
+ let dragX = dragDoc.GetNumber(KeyStore.X, 0);
+ let dragY = dragDoc.GetNumber(KeyStore.Y, 0);
+ de.data.draggedDocuments.map(d => {
+ let docX = d.GetNumber(KeyStore.X, 0);
+ let docY = d.GetNumber(KeyStore.Y, 0);
+ d.SetNumber(KeyStore.X, x + (docX - dragX));
+ d.SetNumber(KeyStore.Y, y + (docY - dragY));
+ if (!d.GetNumber(KeyStore.Width, 0)) {
+ d.SetNumber(KeyStore.Width, 300);
+ d.SetNumber(KeyStore.Height, 300);
+ }
+ this.bringToFront(d);
+ })
}
return true;
}
@@ -247,6 +254,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
ContainingCollectionView: undefined,
focus: this.focusDocument,
parentActive: this.props.active,
+ onActiveChanged: this.props.active,
}
}
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 20132a4b1..e2239c8be 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -102,7 +102,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
if (e.key == "Backspace" || e.key == "Delete") {
this.marqueeSelect().map(d => this.props.removeDocument(d));
let ink = this.props.container.props.Document.GetT(KeyStore.Ink, InkField);
- if (ink && ink != FieldWaiting && ink.Data) {
+ if (ink && ink != FieldWaiting) {
this.marqueeInkDelete(ink.Data);
}
this.cleanupInteractions();
@@ -118,22 +118,21 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
return d;
});
let ink = this.props.container.props.Document.GetT(KeyStore.Ink, InkField);
- if (ink && ink != FieldWaiting && ink.Data) {
- //setTimeout(() => {
- let newCollection = Documents.FreeformDocument(selected, {
- x: bounds.left,
- y: bounds.top,
- panx: 0,
- pany: 0,
- width: bounds.width,
- height: bounds.height,
- backgroundColor: "Transparent",
- ink: this.marqueeInkSelect(ink.Data),
- title: "a nested collection"
- });
- this.props.addDocument(newCollection, false);
- this.marqueeInkDelete(ink.Data);
- }
+ let inkData = ink && ink != FieldWaiting ? ink.Data : undefined;
+ //setTimeout(() => {
+ let newCollection = Documents.FreeformDocument(selected, {
+ x: bounds.left,
+ y: bounds.top,
+ panx: 0,
+ pany: 0,
+ width: bounds.width,
+ height: bounds.height,
+ backgroundColor: "Transparent",
+ ink: inkData ? this.marqueeInkSelect(inkData) : undefined,
+ title: "a nested collection"
+ });
+ this.props.addDocument(newCollection, false);
+ this.marqueeInkDelete(inkData);
// }, 100);
this.cleanupInteractions();
}
@@ -159,15 +158,17 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
}
@action
- marqueeInkDelete(ink: Map<any, any>, ) {
+ marqueeInkDelete(ink?: Map<any, any>) {
// bcz: this appears to work but when you restart all the deleted strokes come back -- InkField isn't observing its changes so they aren't written to the DB.
// ink.forEach((value: StrokeData, key: string, map: any) =>
// InkingCanvas.IntersectStrokeRect(value, this.Bounds) && ink.delete(key));
- let idata = new Map();
- ink.forEach((value: StrokeData, key: string, map: any) =>
- !InkingCanvas.IntersectStrokeRect(value, this.Bounds) && idata.set(key, value));
- this.props.container.props.Document.SetDataOnPrototype(KeyStore.Ink, idata, InkField);
+ if (ink) {
+ let idata = new Map();
+ ink.forEach((value: StrokeData, key: string, map: any) =>
+ !InkingCanvas.IntersectStrokeRect(value, this.Bounds) && idata.set(key, value));
+ this.props.container.props.Document.SetDataOnPrototype(KeyStore.Ink, idata, InkField);
+ }
}
marqueeSelect() {
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 2574b374a..1c9155dce 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -54,7 +54,8 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
ScreenToLocalTransform,
addDocument,
removeDocument,
- parentActive: active
+ onActiveChanged,
+ parentActive: active,
} = this.props;
let bindings: JsxBindings = {
props: {
@@ -65,6 +66,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
selectOnLoad,
ScreenToLocalTransform,
active,
+ onActiveChanged,
addDocument,
removeDocument,
focus,
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 545344024..6c05f6924 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -36,6 +36,7 @@ export interface DocumentViewProps {
focus: (doc: Document) => void;
selectOnLoad: boolean;
parentActive: () => boolean;
+ onActiveChanged: (isActive: boolean) => void;
}
export interface JsxArgs extends DocumentViewProps {
Keys: { [name: string]: Key }
@@ -99,7 +100,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
if (this.props.isTopMost) {
this.startDragging(e.pageX, e.pageY, e.altKey || e.ctrlKey);
}
- else CollectionDockingView.Instance.StartOtherDrag(this.props.Document, e);
+ else CollectionDockingView.Instance.StartOtherDrag([this.props.Document], e);
e.stopPropagation();
} else {
if (this.active && !e.isDefaultPrevented()) {
@@ -118,9 +119,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
if (this._mainCont.current) {
this.dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, { handlers: { drop: this.drop.bind(this) } });
}
- runInAction(() => {
- DocumentManager.Instance.DocumentViews.push(this);
- })
+ runInAction(() => DocumentManager.Instance.DocumentViews.push(this))
}
componentDidUpdate() {
@@ -136,25 +135,18 @@ export class DocumentView extends React.Component<DocumentViewProps> {
if (this.dropDisposer) {
this.dropDisposer();
}
- runInAction(() => {
- DocumentManager.Instance.DocumentViews.splice(DocumentManager.Instance.DocumentViews.indexOf(this), 1);
-
- })
+ runInAction(() => DocumentManager.Instance.DocumentViews.splice(DocumentManager.Instance.DocumentViews.indexOf(this), 1))
}
startDragging(x: number, y: number, dropAliasOfDraggedDoc: boolean) {
if (this._mainCont.current) {
const [left, top] = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
- let dragData = new DragManager.DocumentDragData(this.props.Document);
+ let dragData = new DragManager.DocumentDragData([this.props.Document]);
dragData.aliasOnDrop = dropAliasOfDraggedDoc;
dragData.xOffset = x - left;
dragData.yOffset = y - top;
- dragData.moveDocument = (targetCollection: Document, addDocument: (document: Document) => void) => {
- if (this.props.moveDocument) {
- this.props.moveDocument(this.props.Document, targetCollection, addDocument)
- }
- }
- DragManager.StartDocumentDrag(this._mainCont.current, dragData, {
+ dragData.moveDocument = this.props.moveDocument;
+ DragManager.StartDocumentDrag([this._mainCont.current], dragData, {
handlers: {
dragComplete: action(() => { }),
},
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 57af55f9f..4c6062a2f 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -36,9 +36,10 @@ export interface FieldViewProps {
selectOnLoad: boolean;
addDocument?: (document: Document, allowDuplicates?: boolean) => boolean;
removeDocument?: (document: Document) => boolean;
- moveDocument?: (document: Document, targetCollection: Document, addDocument: (document: Document) => void) => boolean;
+ moveDocument?: (document: Document, targetCollection: Document, addDocument: (document: Document) => boolean) => boolean;
ScreenToLocalTransform: () => Transform;
active: () => boolean;
+ onActiveChanged: (isActive: boolean) => void;
focus: (doc: Document) => void;
}
@@ -74,21 +75,24 @@ export class FieldView extends React.Component<FieldViewProps> {
return <AudioBox {...this.props} />
}
else if (field instanceof Document) {
- return (<DocumentContentsView Document={field}
- addDocument={undefined}
- removeDocument={undefined}
- ScreenToLocalTransform={Transform.Identity}
- ContentScaling={() => 1}
- PanelWidth={() => 100}
- PanelHeight={() => 100}
- isTopMost={true} //TODO Why is this top most?
- selectOnLoad={false}
- focus={() => { }}
- isSelected={() => false}
- select={() => false}
- layoutKey={KeyStore.Layout}
- ContainingCollectionView={undefined}
- parentActive={this.props.active} />)
+ return (
+ <DocumentContentsView Document={field}
+ addDocument={undefined}
+ removeDocument={undefined}
+ ScreenToLocalTransform={Transform.Identity}
+ ContentScaling={() => 1}
+ PanelWidth={() => 100}
+ PanelHeight={() => 100}
+ isTopMost={true} //TODO Why is this top most?
+ selectOnLoad={false}
+ focus={() => { }}
+ isSelected={() => false}
+ select={() => false}
+ layoutKey={KeyStore.Layout}
+ ContainingCollectionView={undefined}
+ parentActive={this.props.active}
+ onActiveChanged={this.props.onActiveChanged} />
+ )
}
else if (field instanceof ListField) {
return (<div>
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index e178cbc8d..a676844dc 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -12,6 +12,7 @@ import { Server } from "../../Server"
import { EditableView } from "../EditableView";
import { CompileScript, ToField } from "../../util/Scripting";
import { Transform } from '../../util/Transform';
+import { returnFalse, emptyFunction } from '../../../Utils';
// Represents one row in a key value plane
@@ -46,13 +47,14 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
let props: FieldViewProps = {
Document: this.props.doc,
fieldKey: this.key,
- isSelected: () => false,
- select: () => { },
+ isSelected: returnFalse,
+ select: emptyFunction,
isTopMost: false,
selectOnLoad: false,
- active: () => false,
+ active: returnFalse,
+ onActiveChanged: emptyFunction,
ScreenToLocalTransform: Transform.Identity,
- focus: () => { },
+ focus: emptyFunction,
}
let contents = (
<FieldView {...props} />