diff options
author | Tyler Schicke <tyler_schicke@brown.edu> | 2019-04-03 20:12:06 -0400 |
---|---|---|
committer | Tyler Schicke <tyler_schicke@brown.edu> | 2019-04-03 20:12:06 -0400 |
commit | c10b9ca57e13c8de8b35f01e6c6ce82706319e4d (patch) | |
tree | 8309da408515969da55846b38a60aad724a30728 /src | |
parent | 5889bf159ee0a0f6567683b2bb8c2475feccf9ec (diff) | |
parent | c406c8d123ce0aa9d63fb8a4dd90adfe83d2889d (diff) |
Merge and it compiles
Diffstat (limited to 'src')
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} /> |