diff options
author | bob <bcz@cs.brown.edu> | 2019-02-22 15:25:00 -0500 |
---|---|---|
committer | bob <bcz@cs.brown.edu> | 2019-02-22 15:25:00 -0500 |
commit | 9a43ea5aefd7b1153f4d865aac0d6c541c989981 (patch) | |
tree | 3a2994e6c74657f168e9d9d8cf76ab98c45024c1 /src | |
parent | 85d7a3d9aee44f0b199dddace92f7a683bc33eb6 (diff) | |
parent | 1e83695f1380b7824d36bdc55305c44117f6da2c (diff) |
Merge branch 'collectionView'
Diffstat (limited to 'src')
-rw-r--r-- | src/client/Server.ts | 2 | ||||
-rw-r--r-- | src/client/documents/Documents.ts | 2 | ||||
-rw-r--r-- | src/client/util/DragManager.ts | 1 | ||||
-rw-r--r-- | src/client/views/DocumentDecorations.tsx | 2 | ||||
-rw-r--r-- | src/client/views/Main.tsx | 3 | ||||
-rw-r--r-- | src/client/views/collections/CollectionDockingView.tsx | 6 | ||||
-rw-r--r-- | src/client/views/collections/CollectionFreeFormView.tsx | 62 | ||||
-rw-r--r-- | src/client/views/collections/CollectionSchemaView.tsx | 16 | ||||
-rw-r--r-- | src/client/views/collections/CollectionView.tsx | 20 | ||||
-rw-r--r-- | src/client/views/collections/CollectionViewBase.tsx | 82 | ||||
-rw-r--r-- | src/client/views/nodes/CollectionFreeFormDocumentView.tsx | 24 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 3 |
12 files changed, 129 insertions, 94 deletions
diff --git a/src/client/Server.ts b/src/client/Server.ts index 06ac22c61..2d162b93a 100644 --- a/src/client/Server.ts +++ b/src/client/Server.ts @@ -34,7 +34,7 @@ export class Server { } })); } else if (cached != FieldWaiting) { - callback(cached); + setTimeout(() => callback(cached as Field), 0); } else { reaction(() => { return this.ClientFieldsCached.get(fieldid); diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index bfa6cb7a9..156a09316 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -13,7 +13,7 @@ import { CollectionFreeFormView } from "../views/collections/CollectionFreeFormV import { FieldId } from "../../fields/Field"; import { CollectionView, CollectionViewType } from "../views/collections/CollectionView"; -interface DocumentOptions { +export interface DocumentOptions { x?: number; y?: number; width?: number; diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 6d5fe12a7..eb4b3aeaa 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -44,6 +44,7 @@ export namespace DragManager { drop: (e: Event, de: DropEvent) => void; } + export function MakeDropTarget(element: HTMLElement, options: DropOptions): DragDropDisposer { if ("canDrop" in element.dataset) { throw new Error("Element is already droppable, can't make it droppable again"); diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 395a37ba5..7b64a4c2c 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -28,7 +28,7 @@ export class DocumentDecorations extends React.Component { } let transform = (element.props.ScreenToLocalTransform().scale(element.props.Scaling)).inverse(); var [sptX, sptY] = transform.transformPoint(0, 0); - let [bptX, bptY] = transform.transformPoint(element.props.PanelSize[0], element.props.PanelSize[1]); + let [bptX, bptY] = transform.transformPoint(element.props.PanelWidth, element.props.PanelHeight); return { x: Math.min(sptX, bounds.x), y: Math.min(sptY, bounds.y), r: Math.max(bptX, bounds.r), b: Math.max(bptY, bounds.b) diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index fe1a999ec..6f6a89839 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -107,7 +107,8 @@ Documents.initProtos(() => { <DocumentView Document={mainContainer} AddDocument={undefined} RemoveDocument={undefined} ScreenToLocalTransform={() => Transform.Identity} Scaling={1} - PanelSize={[0, 0]} + PanelWidth={0} + PanelHeight={0} isTopMost={true} ContainingCollectionView={undefined} /> <DocumentDecorations /> diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 752007439..7ac8ea5e4 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -14,8 +14,9 @@ import { DragManager } from "../../util/DragManager"; import { undoBatch } from "../../util/UndoManager"; import { DocumentView } from "../nodes/DocumentView"; import "./CollectionDockingView.scss"; -import { CollectionViewProps, COLLECTION_BORDER_WIDTH, SubCollectionViewProps } from "./CollectionView"; +import { COLLECTION_BORDER_WIDTH } from "./CollectionView"; import React = require("react"); +import { SubCollectionViewProps } from "./CollectionViewBase"; @observer export class CollectionDockingView extends React.Component<SubCollectionViewProps> { @@ -289,7 +290,8 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> { AddDocument={undefined} RemoveDocument={undefined} Scaling={this._parentScaling} - PanelSize={[this._nativeWidth, this._nativeHeight]} + PanelWidth={this._nativeWidth} + PanelHeight={this._nativeHeight} ScreenToLocalTransform={this.ScreenToLocalTransform} isTopMost={true} ContainingCollectionView={undefined} /> diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx index b78b1a3b6..e31fb25b9 100644 --- a/src/client/views/collections/CollectionFreeFormView.tsx +++ b/src/client/views/collections/CollectionFreeFormView.tsx @@ -4,20 +4,18 @@ import { action, computed, trace } from "mobx"; import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView"; import { DragManager } from "../../util/DragManager"; import "./CollectionFreeFormView.scss"; -import { COLLECTION_BORDER_WIDTH, CollectionViewProps, SubCollectionViewProps } from "./CollectionView"; +import { COLLECTION_BORDER_WIDTH } from "./CollectionView"; import { KeyStore } from "../../../fields/KeyStore"; import { Document } from "../../../fields/Document"; import { ListField } from "../../../fields/ListField"; -import { NumberField } from "../../../fields/NumberField"; -import { Documents } from "../../documents/Documents"; import { FieldWaiting } from "../../../fields/Field"; import { Transform } from "../../util/Transform"; import { DocumentView } from "../nodes/DocumentView"; import { undoBatch } from "../../util/UndoManager"; -import { jSXElement } from "babel-types"; +import { CollectionViewBase, SubCollectionViewProps } from "./CollectionViewBase"; @observer -export class CollectionFreeFormView extends React.Component<SubCollectionViewProps> { +export class CollectionFreeFormView extends CollectionViewBase { private _canvasRef = React.createRef<HTMLDivElement>(); private _lastX: number = 0; private _lastY: number = 0; @@ -45,13 +43,8 @@ export class CollectionFreeFormView extends React.Component<SubCollectionViewPro @undoBatch @action drop = (e: Event, de: DragManager.DropEvent) => { + super.drop(e, de); const doc: DocumentView = de.data["document"]; - if (doc.props.ContainingCollectionView && doc.props.ContainingCollectionView !== this.props.CollectionView) { - if (doc.props.RemoveDocument) { - doc.props.RemoveDocument(doc.props.Document); - } - this.props.addDocument(doc.props.Document); - } const xOffset = de.data["xOffset"] as number || 0; const yOffset = de.data["yOffset"] as number || 0; //this should be able to use translate and scale methods on an Identity transform, no? @@ -62,21 +55,6 @@ export class CollectionFreeFormView extends React.Component<SubCollectionViewPro doc.props.Document.SetNumber(KeyStore.X, x); doc.props.Document.SetNumber(KeyStore.Y, y); this.bringToFront(doc); - e.stopPropagation(); - } - - private dropDisposer?: DragManager.DragDropDisposer; - createDropTarget = (ele: HTMLDivElement) => { - if (this.dropDisposer) { - this.dropDisposer(); - } - if (ele) { - this.dropDisposer = DragManager.MakeDropTarget(ele, { - handlers: { - drop: this.drop - } - }); - } } @action @@ -148,36 +126,11 @@ export class CollectionFreeFormView extends React.Component<SubCollectionViewPro @action onDrop = (e: React.DragEvent): void => { - e.stopPropagation() - e.preventDefault() - let fReader = new FileReader() - let file = e.dataTransfer.items[0].getAsFile(); - let that = this; const panx: number = this.props.Document.GetNumber(KeyStore.PanX, 0); const pany: number = this.props.Document.GetNumber(KeyStore.PanY, 0); let x = e.pageX - panx let y = e.pageY - pany - - fReader.addEventListener("load", action("drop", () => { - if (fReader.result) { - let url = "" + fReader.result; - let doc = Documents.ImageDocument(url, { - x: x, y: y - }) - let docs = that.props.Document.GetT(KeyStore.Data, ListField); - if (docs != FieldWaiting) { - if (!docs) { - docs = new ListField<Document>(); - that.props.Document.Set(KeyStore.Data, docs) - } - docs.Data.push(doc); - } - } - }), false) - - if (file) { - fReader.readAsDataURL(file) - } + super.onDrop(e, { x: x, y: y }); } onDragOver = (): void => { @@ -234,7 +187,8 @@ export class CollectionFreeFormView extends React.Component<SubCollectionViewPro ScreenToLocalTransform={this.getTransform} isTopMost={false} Scaling={1} - PanelSize={[doc.GetNumber(KeyStore.Width, 0), doc.GetNumber(KeyStore.Height, 0)]} + PanelWidth={doc.GetNumber(KeyStore.Width, 0)} + PanelHeight={doc.GetNumber(KeyStore.Height, 0)} ContainingCollectionView={this.props.CollectionView} />); }) } @@ -249,7 +203,7 @@ export class CollectionFreeFormView extends React.Component<SubCollectionViewPro onPointerDown={this.onPointerDown} onWheel={this.onPointerWheel} onContextMenu={(e) => e.preventDefault()} - onDrop={this.onDrop} + onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px`, }} ref={this.createDropTarget}> diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index f25e721c0..7e7d23fe4 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -5,7 +5,7 @@ import Measure from "react-measure"; import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table"; import "react-table/react-table.css"; import { Document } from "../../../fields/Document"; -import { Field } from "../../../fields/Field"; +import { Field, FieldWaiting } from "../../../fields/Field"; import { KeyStore } from "../../../fields/KeyStore"; import { CompileScript, ToField } from "../../util/Scripting"; import { Transform } from "../../util/Transform"; @@ -13,10 +13,11 @@ import { EditableView } from "../EditableView"; import { DocumentView } from "../nodes/DocumentView"; import { FieldView, FieldViewProps } from "../nodes/FieldView"; import "./CollectionSchemaView.scss"; -import { COLLECTION_BORDER_WIDTH, CollectionViewProps, SubCollectionViewProps } from "./CollectionView"; +import { COLLECTION_BORDER_WIDTH } from "./CollectionView"; +import { CollectionViewBase } from "./CollectionViewBase"; @observer -export class CollectionSchemaView extends React.Component<SubCollectionViewProps> { +export class CollectionSchemaView extends CollectionViewBase { private _mainCont = React.createRef<HTMLDivElement>(); private DIVIDER_WIDTH = 5; @@ -117,6 +118,7 @@ export class CollectionSchemaView extends React.Component<SubCollectionViewProps } } + getTransform = (): Transform => { return this.props.ScreenToLocalTransform().translate(- COLLECTION_BORDER_WIDTH - this.DIVIDER_WIDTH - this._dividerX, - COLLECTION_BORDER_WIDTH).scale(1 / this._parentScaling); } @@ -147,7 +149,8 @@ export class CollectionSchemaView extends React.Component<SubCollectionViewProps ScreenToLocalTransform={this.getTransform} Scaling={this._parentScaling} isTopMost={false} - PanelSize={[this._panelWidth, this._panelHeight]} + PanelWidth={this._panelWidth} + PanelHeight={this._panelHeight} ContainingCollectionView={this.props.CollectionView} /> </div> } @@ -181,7 +184,10 @@ export class CollectionSchemaView extends React.Component<SubCollectionViewProps } </Measure> <div className="collectionSchemaView-dividerDragger" style={{ position: "relative", background: "black", float: "left", width: `${this.DIVIDER_WIDTH}px`, height: "100%" }} onPointerDown={this.onDividerDown} /> - <div className="collectionSchemaView-previewRegion" style={{ position: "relative", float: "left", width: `calc(${100 - this._splitPercentage}% - ${this.DIVIDER_WIDTH}px)`, height: "100%" }}> + <div className="collectionSchemaView-previewRegion" + onDrop={(e: React.DragEvent) => this.onDrop(e, {})} + ref={this.createDropTarget} + style={{ position: "relative", float: "left", width: `calc(${100 - this._splitPercentage}% - ${this.DIVIDER_WIDTH}px)`, height: "100%" }}> {content} </div> </div > diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 651d85879..ff1803ec3 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -1,36 +1,18 @@ import { action, computed } from "mobx"; import { observer } from "mobx-react"; import { Document } from "../../../fields/Document"; -import { Key } from "../../../fields/Key"; import { ListField } from "../../../fields/ListField"; import { SelectionManager } from "../../util/SelectionManager"; import { ContextMenu } from "../ContextMenu"; import React = require("react"); -import { Transform } from "../../util/Transform"; import { KeyStore } from "../../../fields/KeyStore"; import { NumberField } from "../../../fields/NumberField"; import { CollectionFreeFormView } from "./CollectionFreeFormView"; import { CollectionDockingView } from "./CollectionDockingView"; import { CollectionSchemaView } from "./CollectionSchemaView"; -import { Opt } from "../../../fields/Field"; +import { CollectionViewProps } from "./CollectionViewBase"; -export interface CollectionViewProps { - fieldKey: Key; - Document: Document; - ScreenToLocalTransform: () => Transform; - isSelected: () => boolean; - isTopMost: boolean; - select: (ctrlPressed: boolean) => void; - BackgroundView?: () => JSX.Element; -} - -export interface SubCollectionViewProps extends CollectionViewProps { - active: () => boolean; - addDocument: (doc: Document) => void; - removeDocument: (doc: Document) => boolean; - CollectionView: Opt<CollectionView>; -} export enum CollectionViewType { Invalid, diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx new file mode 100644 index 000000000..06de56383 --- /dev/null +++ b/src/client/views/collections/CollectionViewBase.tsx @@ -0,0 +1,82 @@ +import { action, computed } from "mobx"; +import { Document } from "../../../fields/Document"; +import { ListField } from "../../../fields/ListField"; +import React = require("react"); +import { KeyStore } from "../../../fields/KeyStore"; +import { Opt, FieldWaiting } from "../../../fields/Field"; +import { undoBatch } from "../../util/UndoManager"; +import { DragManager } from "../../util/DragManager"; +import { DocumentView } from "../nodes/DocumentView"; +import { Documents, DocumentOptions } from "../../documents/Documents"; +import { Key } from "../../../fields/Key"; +import { Transform } from "../../util/Transform"; + + +export interface CollectionViewProps { + fieldKey: Key; + Document: Document; + ScreenToLocalTransform: () => Transform; + isSelected: () => boolean; + isTopMost: boolean; + select: (ctrlPressed: boolean) => void; + BackgroundView?: () => JSX.Element; +} +export interface SubCollectionViewProps extends CollectionViewProps { + active: () => boolean; + addDocument: (doc: Document) => void; + removeDocument: (doc: Document) => boolean; + CollectionView: any; +} + +export class CollectionViewBase extends React.Component<SubCollectionViewProps> { + private dropDisposer?: DragManager.DragDropDisposer; + protected createDropTarget = (ele: HTMLDivElement) => { + if (this.dropDisposer) { + this.dropDisposer(); + } + if (ele) { + this.dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } }); + } + } + + @undoBatch + @action + protected drop(e: Event, de: DragManager.DropEvent) { + const doc: DocumentView = de.data["document"]; + if (doc.props.ContainingCollectionView && doc.props.ContainingCollectionView !== this.props.CollectionView) { + if (doc.props.RemoveDocument) { + doc.props.RemoveDocument(doc.props.Document); + } + this.props.addDocument(doc.props.Document); + } + e.stopPropagation(); + } + + @action + protected onDrop(e: React.DragEvent, options: DocumentOptions): void { + e.stopPropagation() + e.preventDefault() + let fReader = new FileReader() + let file = e.dataTransfer.items[0].getAsFile(); + let that = this; + + fReader.addEventListener("load", action("drop", () => { + if (fReader.result) { + let url = "" + fReader.result; + let doc = Documents.ImageDocument(url, options) + let docs = that.props.Document.GetT(KeyStore.Data, ListField); + if (docs != FieldWaiting) { + if (!docs) { + docs = new ListField<Document>(); + that.props.Document.Set(KeyStore.Data, docs) + } + docs.Data.push(doc); + } + } + }), false) + + if (file) { + fReader.readAsDataURL(file) + } + } +} diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 5568935fa..ad6756918 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -1,4 +1,4 @@ -import { computed } from "mobx"; +import { computed, trace } from "mobx"; import { observer } from "mobx-react"; import { KeyStore } from "../../../fields/KeyStore"; import { NumberField } from "../../../fields/NumberField"; @@ -69,15 +69,25 @@ export class CollectionFreeFormDocumentView extends React.Component<DocumentView this.props.Document.SetData(KeyStore.ZIndex, h, NumberField) } + @computed + get parentScaling() { + return this.nativeWidth > 0 ? this.width / this.nativeWidth : 1; + } getTransform = (): Transform => { - var parentScaling = this.nativeWidth > 0 ? this.width / this.nativeWidth : 1; return this.props.ScreenToLocalTransform(). - translate(-this.props.Document.GetNumber(KeyStore.X, 0), -this.props.Document.GetNumber(KeyStore.Y, 0)).scale(1 / parentScaling); + translate(-this.props.Document.GetNumber(KeyStore.X, 0), -this.props.Document.GetNumber(KeyStore.Y, 0)).scale(1 / this.parentScaling); + } + + @computed + get docView() { + return <DocumentView {...this.props} + Scaling={this.parentScaling} + ScreenToLocalTransform={this.getTransform} + /> } render() { - var parentScaling = this.nativeWidth > 0 ? this.width / this.nativeWidth : 1; return ( <div ref={this._mainCont} style={{ transformOrigin: "left top", @@ -88,11 +98,7 @@ export class CollectionFreeFormDocumentView extends React.Component<DocumentView zIndex: this.zIndex, backgroundColor: "transparent" }} > - - <DocumentView {...this.props} - Scaling={parentScaling} - ScreenToLocalTransform={this.getTransform} - /> + {this.docView} </div> ); } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 69e413c6f..c026e13cd 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -31,7 +31,8 @@ export interface DocumentViewProps { isTopMost: boolean; //tfs: This shouldn't be necessary I don't think Scaling: number; - PanelSize: number[]; + PanelWidth: number; + PanelHeight: number; } export interface JsxArgs extends DocumentViewProps { Keys: { [name: string]: Key } |