diff options
author | bob <bcz@cs.brown.edu> | 2019-02-05 11:22:10 -0500 |
---|---|---|
committer | bob <bcz@cs.brown.edu> | 2019-02-05 11:22:10 -0500 |
commit | 58c7742c18f82fe854784b083dfa723a8f256b72 (patch) | |
tree | 7f5df647e16b225c81db90a18e67bdca5be067b1 | |
parent | 00a4534c535281aaecf4b47da64f1a0770e3bf68 (diff) |
lots of reorganization
-rw-r--r-- | src/Main.tsx | 14 | ||||
-rw-r--r-- | src/util/DragManager.ts | 2 | ||||
-rw-r--r-- | src/util/SelectionManager.ts | 12 | ||||
-rw-r--r-- | src/views/collections/CollectionDockingView.tsx | 12 | ||||
-rw-r--r-- | src/views/collections/CollectionFreeFormView.tsx | 37 | ||||
-rw-r--r-- | src/views/collections/CollectionSchemaView.tsx | 12 | ||||
-rw-r--r-- | src/views/nodes/CollectionFreeFormDocumentView.tsx | 222 | ||||
-rw-r--r-- | src/views/nodes/DocumentView.tsx | 257 | ||||
-rw-r--r-- | src/views/nodes/FieldTextBox.tsx | 6 | ||||
-rw-r--r-- | src/views/nodes/FieldView.tsx | 4 | ||||
-rw-r--r-- | src/views/nodes/ImageBox.tsx | 8 |
11 files changed, 306 insertions, 280 deletions
diff --git a/src/Main.tsx b/src/Main.tsx index cbdf0ae98..7618630f8 100644 --- a/src/Main.tsx +++ b/src/Main.tsx @@ -11,7 +11,7 @@ import { NumberField } from './fields/NumberField'; import { TextField } from './fields/TextField'; import "./Main.scss"; import { ContextMenu } from './views/ContextMenu'; -import { DocumentView, DocumentContentsView } from './views/nodes/DocumentView'; +import { DocumentView } from './views/nodes/DocumentView'; configure({ enforceActions: "observed" @@ -51,14 +51,14 @@ document.addEventListener("pointerdown", action(function (e: PointerEvent) { schemaDocs[4].SetFieldValue(KS.Author, "Bob", TextField); schemaDocs.push(doc2); const doc7 = Documents.SchemaDocument(schemaDocs) - const docset = [doc3];//[doc1, doc2, doc3, doc7]; + const docset = [doc1, doc2, doc3, doc7]; let doc4 = Documents.CollectionDocument(docset, { x: 0, y: 400, title: "mini collection" }); let doc5 = Documents.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { x: 650, y: 500, width: 600, height: 600, title: "cat 2" }); - let docset2 = new Array<Document>(doc4, doc1, doc3); + let docset2 = new Array<Document>(doc4);//, doc1, doc3); let doc6 = Documents.CollectionDocument(docset2, { x: 350, y: 100, width: 600, height: 600, title: "docking collection" }); @@ -66,21 +66,21 @@ document.addEventListener("pointerdown", action(function (e: PointerEvent) { if (!mainNodes) { mainNodes = new ListField<Document>(); } - // mainNodes.Data.push(doc1); + mainNodes.Data.push(doc1); // mainNodes.Data.push(doc2); mainNodes.Data.push(doc4); // mainNodes.Data.push(doc3); - //mainNodes.Data.push(doc5); + // mainNodes.Data.push(doc5); // mainNodes.Data.push(doc1); //mainNodes.Data.push(doc2); - //mainNodes.Data.push(doc6); + mainNodes.Data.push(doc7); mainContainer.SetField(KeyStore.Data, mainNodes); } //); ReactDOM.render(( <div style={{ position: "absolute", width: "100%", height: "100%" }}> - <DocumentContentsView Document={mainContainer} ContainingCollectionView={undefined} ContainingDocumentContentsView={undefined} /> + <DocumentView Document={mainContainer} ContainingCollectionView={undefined} DocumentContentsView={undefined} /> <DocumentDecorations /> <ContextMenu /> </div>), diff --git a/src/util/DragManager.ts b/src/util/DragManager.ts index b4132a222..63d6a88f8 100644 --- a/src/util/DragManager.ts +++ b/src/util/DragManager.ts @@ -1,5 +1,5 @@ import { Opt } from "../fields/Field"; -import { DocumentView } from "../views/nodes/DocumentView"; +import { CollectionFreeFormDocumentView } from "../views/nodes/CollectionFreeFormDocumentView"; import { DocumentDecorations } from "../DocumentDecorations"; import { SelectionManager } from "./SelectionManager"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; diff --git a/src/util/SelectionManager.ts b/src/util/SelectionManager.ts index 2a63248c4..0759ae110 100644 --- a/src/util/SelectionManager.ts +++ b/src/util/SelectionManager.ts @@ -1,13 +1,13 @@ -import { DocumentView } from "../views/nodes/DocumentView"; +import { CollectionFreeFormDocumentView } from "../views/nodes/CollectionFreeFormDocumentView"; import { observable, action } from "mobx"; export namespace SelectionManager { class Manager { @observable - SelectedDocuments: Array<DocumentView> = []; + SelectedDocuments: Array<CollectionFreeFormDocumentView> = []; @action - SelectDoc(doc: DocumentView, ctrlPressed: boolean): void { + SelectDoc(doc: CollectionFreeFormDocumentView, ctrlPressed: boolean): void { // if doc is not in SelectedDocuments, add it if (!ctrlPressed) { manager.SelectedDocuments = []; @@ -21,11 +21,11 @@ export namespace SelectionManager { const manager = new Manager; - export function SelectDoc(doc: DocumentView, ctrlPressed: boolean): void { + export function SelectDoc(doc: CollectionFreeFormDocumentView, ctrlPressed: boolean): void { manager.SelectDoc(doc, ctrlPressed) } - export function IsSelected(doc: DocumentView): boolean { + export function IsSelected(doc: CollectionFreeFormDocumentView): boolean { return manager.SelectedDocuments.indexOf(doc) !== -1; } @@ -33,7 +33,7 @@ export namespace SelectionManager { manager.SelectedDocuments = [] } - export function SelectedDocuments(): Array<DocumentView> { + export function SelectedDocuments(): Array<CollectionFreeFormDocumentView> { return manager.SelectedDocuments; } }
\ No newline at end of file diff --git a/src/views/collections/CollectionDockingView.tsx b/src/views/collections/CollectionDockingView.tsx index 197b7df46..1a523e1bf 100644 --- a/src/views/collections/CollectionDockingView.tsx +++ b/src/views/collections/CollectionDockingView.tsx @@ -4,7 +4,7 @@ import React = require("react"); import FlexLayout from "flexlayout-react"; import { action, observable, computed } from "mobx"; import { Document } from "../../fields/Document"; -import { DocumentView, DocumentContentsView } from "../nodes/DocumentView"; +import { DocumentView } from "../nodes/DocumentView"; import { ListField } from "../../fields/ListField"; import { NumberField } from "../../fields/NumberField"; import { SSL_OP_SINGLE_DH_USE } from "constants"; @@ -20,7 +20,7 @@ import { CollectionViewBase, CollectionViewProps, COLLECTION_BORDER_WIDTH } from export class CollectionDockingView extends CollectionViewBase { private static UseGoldenLayout = true; - public static LayoutString() { return '<CollectionDockingView DocumentForCollection={Document} CollectionFieldKey={DataKey} DocumentContentsContainingCollection={ContainingDocumentContentsView}/>'; } + public static LayoutString() { return CollectionViewBase.LayoutString("CollectionDockingView"); } private _containerRef = React.createRef<HTMLDivElement>(); @computed private get modelForFlexLayout() { @@ -69,7 +69,7 @@ export class CollectionDockingView extends CollectionViewBase { @action onResize = (event: any) => { - var cur = this.props.DocumentContentsContainingCollection!.MainContent.current; + var cur = this.props.DocumentContentsOfCollection!.MainContent.current; // bcz: since GoldenLayout isn't a React component itself, we need to notify it to resize when its document container's size has changed CollectionDockingView.myLayout.updateSize(cur!.getBoundingClientRect().width, cur!.getBoundingClientRect().height); @@ -96,7 +96,7 @@ export class CollectionDockingView extends CollectionViewBase { const value: Document[] = Document.GetFieldValue(fieldKey, ListField, []); for (var i: number = 0; i < value.length; i++) { if (value[i].Id === component) { - return (<DocumentView key={value[i].Id} ContainingCollectionView={this} Document={value[i]} ContainingDocumentContentsView={this.props.DocumentContentsContainingCollection} />); + return (<DocumentView key={value[i].Id} ContainingCollectionView={this} Document={value[i]} DocumentContentsView={undefined} />); } } if (component === "text") { @@ -237,7 +237,7 @@ export class CollectionDockingView extends CollectionViewBase { container.getElement().html("<div id='" + containingDiv + "'></div>"); setTimeout(function () { ReactDOM.render(( - <DocumentContentsView key={state.doc.Id} Document={state.doc} ContainingCollectionView={me} ContainingDocumentContentsView={me.props.DocumentContentsContainingCollection} /> // bcz: need to fill in containingdoccontnents with value of DocumentContents when created... + <DocumentView key={state.doc.Id} Document={state.doc} ContainingCollectionView={me} DocumentContentsView={undefined} /> // bcz: need to fill in DocumentContentsView with value of DocumentContents when created... ), document.getElementById(containingDiv) ); @@ -255,7 +255,7 @@ export class CollectionDockingView extends CollectionViewBase { const { CollectionFieldKey: fieldKey, DocumentForCollection: Document } = this.props; const value: Document[] = Document.GetFieldValue(fieldKey, ListField, []); // bcz: not sure why, but I need these to force the flexlayout to update when the collection size changes. - var s = this.props.DocumentContentsContainingCollection != undefined ? this.props.DocumentContentsContainingCollection!.ScalingToScreenSpace : 1; + var s = this.props.DocumentContentsOfCollection != undefined ? this.props.DocumentContentsOfCollection!.ScalingToScreenSpace : 1; var w = Document.GetFieldValue(KeyStore.Width, NumberField, Number(0)) / s; var h = Document.GetFieldValue(KeyStore.Height, NumberField, Number(0)) / s; diff --git a/src/views/collections/CollectionFreeFormView.tsx b/src/views/collections/CollectionFreeFormView.tsx index d0dea7a79..c91946475 100644 --- a/src/views/collections/CollectionFreeFormView.tsx +++ b/src/views/collections/CollectionFreeFormView.tsx @@ -3,7 +3,7 @@ import { Key, KeyStore } from "../../fields/Key"; import React = require("react"); import { action, observable, computed } from "mobx"; import { Document } from "../../fields/Document"; -import { DocumentView } from "../nodes/DocumentView"; +import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView"; import { ListField } from "../../fields/ListField"; import { NumberField } from "../../fields/NumberField"; import { SSL_OP_SINGLE_DH_USE } from "constants"; @@ -12,10 +12,11 @@ import { DragManager } from "../../util/DragManager"; import "./CollectionFreeFormView.scss"; import { Utils } from "../../Utils"; import { CollectionViewBase, CollectionViewProps, COLLECTION_BORDER_WIDTH } from "./CollectionViewBase"; +import { SelectionManager } from "../../util/SelectionManager"; @observer export class CollectionFreeFormView extends CollectionViewBase { - public static LayoutString() { return '<CollectionFreeFormView DocumentForCollection={Document} CollectionFieldKey={DataKey} DocumentContentsContainingCollection={ContainingDocumentContentsView}/>'; } + public static LayoutString() { return CollectionViewBase.LayoutString("CollectionFreeFormView"); } private _containerRef = React.createRef<HTMLDivElement>(); private _canvasRef = React.createRef<HTMLDivElement>(); private _nodeContainerRef = React.createRef<HTMLDivElement>(); @@ -29,7 +30,8 @@ export class CollectionFreeFormView extends CollectionViewBase { @action drop = (e: Event, de: DragManager.DropEvent) => { const doc = de.data["document"]; - if (doc instanceof DocumentView) { + var me = this; + if (doc instanceof CollectionFreeFormDocumentView) { if (doc.props.ContainingCollectionView && doc.props.ContainingCollectionView !== this) { doc.props.ContainingCollectionView.removeDocument(doc.props.Document); this.addDocument(doc.props.Document); @@ -37,14 +39,14 @@ export class CollectionFreeFormView extends CollectionViewBase { const xOffset = de.data["xOffset"] as number || 0; const yOffset = de.data["yOffset"] as number || 0; const { scale, translateX, translateY } = Utils.GetScreenTransform(this._canvasRef.current!); - let sscale = this.props.DocumentContentsContainingCollection!.props.Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1)) + let sscale = this.props.DocumentContentsOfCollection!.props.Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1)) const screenX = de.x - xOffset; const screenY = de.y - yOffset; const docX = (screenX - translateX) / sscale / scale; const docY = (screenY - translateY) / sscale / scale; doc.x = docX; doc.y = docY; - //this.bringToFront(doc); + this.bringToFront(doc); } e.stopPropagation(); } @@ -59,9 +61,14 @@ export class CollectionFreeFormView extends CollectionViewBase { } } + downactive: boolean = false; @action onPointerDown = (e: React.PointerEvent): void => { - if (e.button === 2 && this.active) { + var me = this; + me.downactive = this.active; + var title = this.props.DocumentForCollection.Title; + if ((e.button === 2 && this.active) || + !e.defaultPrevented) { document.removeEventListener("pointermove", this.onPointerMove); document.addEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); @@ -76,28 +83,32 @@ export class CollectionFreeFormView extends CollectionViewBase { document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); e.stopPropagation(); + SelectionManager.DeselectAll(); } @action onPointerMove = (e: PointerEvent): void => { - if (!e.cancelBubble) { + var me = this; + var act = me.active; + var title = me.props.DocumentForCollection.Title; + if (!e.cancelBubble && this.active) { e.preventDefault(); e.stopPropagation(); - let currScale: number = this.props.DocumentContentsContainingCollection!.ScalingToScreenSpace; + let currScale: number = this.props.DocumentContentsOfCollection!.ScalingToScreenSpace; let x = this.props.DocumentForCollection.GetFieldValue(KeyStore.PanX, NumberField, Number(0)); let y = this.props.DocumentForCollection.GetFieldValue(KeyStore.PanY, NumberField, Number(0)); this.props.DocumentForCollection.SetFieldValue(KeyStore.PanX, x + (e.pageX - this._lastX) / currScale, NumberField); this.props.DocumentForCollection.SetFieldValue(KeyStore.PanY, y + (e.pageY - this._lastY) / currScale, NumberField); - this._lastX = e.pageX; - this._lastY = e.pageY; } + this._lastX = e.pageX; + this._lastY = e.pageY; } @action onPointerWheel = (e: React.WheelEvent): void => { e.stopPropagation(); - let { LocalX, Ss, Panxx, Xx, LocalY, Panyy, Yy, ContainerX, ContainerY } = this.props.DocumentContentsContainingCollection!.TransformToLocalPoint(e.pageX, e.pageY); + let { LocalX, Ss, Panxx, Xx, LocalY, Panyy, Yy, ContainerX, ContainerY } = this.props.DocumentContentsOfCollection!.TransformToLocalPoint(e.pageX, e.pageY); var deltaScale = (1 - (e.deltaY / 1000)) * Ss; @@ -148,7 +159,7 @@ export class CollectionFreeFormView extends CollectionViewBase { } @action - bringToFront(doc: DocumentView) { + bringToFront(doc: CollectionFreeFormDocumentView) { const { CollectionFieldKey: fieldKey, DocumentForCollection: Document } = this.props; const value: Document[] = Document.GetListField<Document>(fieldKey, []); @@ -187,7 +198,7 @@ export class CollectionFreeFormView extends CollectionViewBase { <div className="node-container" ref={this._nodeContainerRef}> {value.map(doc => { - return (<DocumentView key={doc.Id} ContainingCollectionView={this} Document={doc} ContainingDocumentContentsView={this.props.DocumentContentsContainingCollection} />); + return (<CollectionFreeFormDocumentView key={doc.Id} ContainingCollectionView={this} Document={doc} DocumentContentsView={this.props.DocumentContentsOfCollection} />); })} </div> </div> diff --git a/src/views/collections/CollectionSchemaView.tsx b/src/views/collections/CollectionSchemaView.tsx index f625b39c5..8c79c9189 100644 --- a/src/views/collections/CollectionSchemaView.tsx +++ b/src/views/collections/CollectionSchemaView.tsx @@ -1,4 +1,3 @@ -import { DocumentContentsView } from "../nodes/DocumentView"; import React = require("react") import ReactTable, { ReactTableDefaults, CellInfo, ComponentPropsGetterRC, ComponentPropsGetterR } from "react-table"; import { observer } from "mobx-react"; @@ -11,22 +10,23 @@ import SplitPane from "react-split-pane" import "./CollectionSchemaView.scss" import { ScrollBox } from "../../util/ScrollBox"; import { CollectionViewBase } from "./CollectionViewBase"; +import { DocumentView } from "../nodes/DocumentView"; @observer export class CollectionSchemaView extends CollectionViewBase { - public static LayoutString() { return '<CollectionSchemaView DocumentForCollection={Document} CollectionFieldKey={DataKey} ContainingDocumentView={ContainingDocumentContentsView}/>'; } + public static LayoutString() { return CollectionViewBase.LayoutString("CollectionSchemaView"); } @observable selectedIndex = 0; renderCell = (rowProps: CellInfo) => { - if (!this.props.DocumentContentsContainingCollection) { + if (!this.props.DocumentContentsOfCollection) { return <div></div> } let props: FieldViewProps = { doc: rowProps.value[0], fieldKey: rowProps.value[1], - documentViewContainer: this.props.DocumentContentsContainingCollection + documentViewContainer: this.props.DocumentContentsOfCollection } return ( <FieldView {...props} /> @@ -77,8 +77,8 @@ export class CollectionSchemaView extends CollectionViewBase { [KS.Title, KS.Data, KS.Author]) let content; if (this.selectedIndex != -1) { - content = (<DocumentContentsView Document={children[this.selectedIndex]} - ContainingDocumentContentsView={this.props.DocumentContentsContainingCollection} + content = (<DocumentView Document={children[this.selectedIndex]} + DocumentContentsView={this.props.DocumentContentsOfCollection} ContainingCollectionView={this} />) } else { content = <div /> diff --git a/src/views/nodes/CollectionFreeFormDocumentView.tsx b/src/views/nodes/CollectionFreeFormDocumentView.tsx new file mode 100644 index 000000000..78e3325ab --- /dev/null +++ b/src/views/nodes/CollectionFreeFormDocumentView.tsx @@ -0,0 +1,222 @@ +import { action, computed } from "mobx"; +import { observer } from "mobx-react"; +import { Key, KeyStore } from "../../fields/Key"; +import { NumberField } from "../../fields/NumberField"; +import { DragManager } from "../../util/DragManager"; +import { SelectionManager } from "../../util/SelectionManager"; +import { CollectionDockingView } from "../collections/CollectionDockingView"; +import { CollectionFreeFormView } from "../collections/CollectionFreeFormView"; +import { ContextMenu } from "../ContextMenu"; +import "./NodeView.scss"; +import React = require("react"); +import { DocumentView, DocumentViewProps } from "./DocumentView"; + + +@observer +export class CollectionFreeFormDocumentView extends DocumentView { + private _contextMenuCanOpen = false; + private _downX: number = 0; + private _downY: number = 0; + + constructor(props: DocumentViewProps) { + super(props); + } + get screenRect(): ClientRect | DOMRect { + if (this._mainCont.current) { + return this._mainCont.current.getBoundingClientRect(); + } + return new DOMRect(); + } + + @computed + get x(): number { + return this.props.Document.GetFieldValue(KeyStore.X, NumberField, Number(0)); + } + + @computed + get y(): number { + return this.props.Document.GetFieldValue(KeyStore.Y, NumberField, Number(0)); + } + + set x(x: number) { + this.props.Document.SetFieldValue(KeyStore.X, x, NumberField) + } + + set y(y: number) { + this.props.Document.SetFieldValue(KeyStore.Y, y, NumberField) + } + + @computed + get transform(): string { + return `translate(${this.x}px, ${this.y}px)`; + } + + @computed + get width(): number { + return this.props.Document.GetFieldValue(KeyStore.Width, NumberField, Number(0)); + } + + set width(w: number) { + this.props.Document.SetFieldValue(KeyStore.Width, w, NumberField) + } + + @computed + get height(): number { + return this.props.Document.GetFieldValue(KeyStore.Height, NumberField, Number(0)); + } + + set height(h: number) { + this.props.Document.SetFieldValue(KeyStore.Height, h, NumberField) + } + + @computed + get zIndex(): number { + return this.props.Document.GetFieldValue(KeyStore.ZIndex, NumberField, Number(0)); + } + + set zIndex(h: number) { + this.props.Document.SetFieldValue(KeyStore.ZIndex, h, NumberField) + } + + @action + dragComplete = (e: DragManager.DragCompleteEvent) => { + } + + @computed + get active(): boolean { + return SelectionManager.IsSelected(this) || this.props.ContainingCollectionView === undefined || this.props.ContainingCollectionView!.active; + } + + @computed + get topMost(): boolean { + return this.props.ContainingCollectionView == undefined || this.props.ContainingCollectionView instanceof CollectionDockingView; + } + + onPointerDown = (e: React.PointerEvent): void => { + this._downX = e.clientX; + this._downY = e.clientY; + var me = this; + if (e.shiftKey && e.buttons === 1) { + CollectionDockingView.StartOtherDrag(this._mainCont.current!, this.props.Document); + e.stopPropagation(); + return; + } + this._contextMenuCanOpen = e.button == 2; + if (this.active && !e.isDefaultPrevented()) { + e.stopPropagation(); + if (e.buttons === 2) { + e.preventDefault(); + } + document.removeEventListener("pointermove", this.onPointerMove) + document.addEventListener("pointermove", this.onPointerMove); + document.removeEventListener("pointerup", this.onPointerUp) + document.addEventListener("pointerup", this.onPointerUp); + } + } + + onPointerMove = (e: PointerEvent): void => { + if (e.cancelBubble) { + this._contextMenuCanOpen = false; + return; + } + if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) { + this._contextMenuCanOpen = false; + if (this._mainCont.current != null && !this.topMost) { + this._contextMenuCanOpen = false; + const rect = this.screenRect; + let dragData: { [id: string]: any } = {}; + dragData["document"] = this; + dragData["xOffset"] = e.x - rect.left; + dragData["yOffset"] = e.y - rect.top; + DragManager.StartDrag(this._mainCont.current, dragData, { + handlers: { + dragComplete: this.dragComplete, + }, + hideSource: true + }) + } + } + e.stopPropagation(); + e.preventDefault(); + } + + onPointerUp = (e: PointerEvent): void => { + document.removeEventListener("pointermove", this.onPointerMove) + document.removeEventListener("pointerup", this.onPointerUp) + e.stopPropagation(); + if (Math.abs(e.clientX - this._downX) < 4 && Math.abs(e.clientY - this._downY) < 4) { + SelectionManager.SelectDoc(this, e.ctrlKey); + } + } + + openRight = (e: React.MouseEvent): void => { + CollectionDockingView.AddRightSplit(this.props.Document); + } + + deleteClicked = (e: React.MouseEvent): void => { + if (this.props.ContainingCollectionView instanceof CollectionFreeFormView) { + this.props.ContainingCollectionView.removeDocument(this.props.Document) + } + } + @action + fullScreenClicked = (e: React.MouseEvent): void => { + CollectionDockingView.OpenFullScreen(this.props.Document); + ContextMenu.Instance.clearItems(); + ContextMenu.Instance.addItem({ description: "Close Full Screen", event: this.closeFullScreenClicked }); + ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) + } + @action + closeFullScreenClicked = (e: React.MouseEvent): void => { + CollectionDockingView.CloseFullScreen(); + ContextMenu.Instance.clearItems(); + ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked }) + ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) + } + + @action + onContextMenu = (e: React.MouseEvent): void => { + if (!SelectionManager.IsSelected(this)) { + return; + } + e.preventDefault() + + if (!this._contextMenuCanOpen) { + return; + } + + if (this.topMost) { + ContextMenu.Instance.clearItems() + ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked }) + ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) + } + else { + // DocumentViews should stop propogation of this event + e.stopPropagation(); + + ContextMenu.Instance.clearItems(); + ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked }) + ContextMenu.Instance.addItem({ description: "Open Right", event: this.openRight }) + ContextMenu.Instance.addItem({ description: "Delete", event: this.deleteClicked }) + ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) + SelectionManager.SelectDoc(this, e.ctrlKey); + } + } + + render() { + var freestyling = this.props.ContainingCollectionView instanceof CollectionFreeFormView; + return ( + <div className="node" ref={this._mainCont} style={{ + transform: freestyling ? this.transform : "", + width: freestyling ? this.width : "100%", + height: freestyling ? this.height : "100%", + position: freestyling ? "absolute" : "relative", + zIndex: freestyling ? this.zIndex : 0, + }} + onContextMenu={this.onContextMenu} + onPointerDown={this.onPointerDown}> + + <DocumentView {...this.props} DocumentContentsView={this} /> + </div> + ); + } +}
\ No newline at end of file diff --git a/src/views/nodes/DocumentView.tsx b/src/views/nodes/DocumentView.tsx index 3cc0f3bf6..fd5ffeb61 100644 --- a/src/views/nodes/DocumentView.tsx +++ b/src/views/nodes/DocumentView.tsx @@ -6,28 +6,24 @@ import { Key, KeyStore } from "../../fields/Key"; import { ListField } from "../../fields/ListField"; import { NumberField } from "../../fields/NumberField"; import { TextField } from "../../fields/TextField"; -import { DragManager } from "../../util/DragManager"; -import { SelectionManager } from "../../util/SelectionManager"; import { Utils } from "../../Utils"; import { CollectionDockingView } from "../collections/CollectionDockingView"; import { CollectionFreeFormView } from "../collections/CollectionFreeFormView"; import { CollectionSchemaView } from "../collections/CollectionSchemaView"; import { CollectionViewBase, COLLECTION_BORDER_WIDTH } from "../collections/CollectionViewBase"; -import { ContextMenu } from "../ContextMenu"; import { FieldTextBox } from "../nodes/FieldTextBox"; import { ImageBox } from "../nodes/ImageBox"; import "./NodeView.scss"; import React = require("react"); -import { baseKeymap } from "prosemirror-commands"; const JsxParser = require('react-jsx-parser').default;//TODO Why does this need to be imported like this? -interface DocumentViewProps { +export interface DocumentViewProps { Document: Document; ContainingCollectionView: Opt<CollectionViewBase>; - ContainingDocumentContentsView: Opt<DocumentContentsView>; + DocumentContentsView: Opt<DocumentView> } @observer -export class DocumentContentsView extends React.Component<DocumentViewProps> { +export class DocumentView extends React.Component<DocumentViewProps> { protected _mainCont = React.createRef<any>(); get MainContent() { @@ -53,9 +49,9 @@ export class DocumentContentsView extends React.Component<DocumentViewProps> { // @computed public get ScalingToScreenSpace(): number { - if (this.props.ContainingDocumentContentsView != undefined) { - let ss = this.props.ContainingDocumentContentsView.props.Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1)); - return this.props.ContainingDocumentContentsView.ScalingToScreenSpace * ss; + if (this.props.ContainingCollectionView != undefined && this.props.ContainingCollectionView.props.DocumentContentsOfCollection != undefined) { + let ss = this.props.ContainingCollectionView.props.DocumentForCollection.GetFieldValue(KeyStore.Scale, NumberField, Number(1)); + return this.props.ContainingCollectionView.props.DocumentContentsOfCollection.ScalingToScreenSpace * ss; } return 1; } @@ -66,8 +62,8 @@ export class DocumentContentsView extends React.Component<DocumentViewProps> { public TransformToLocalPoint(screenX: number, screenY: number) { // if this collection view is nested within another collection view, then // first transform the screen point into the parent collection's coordinate space. - let { LocalX: parentX, LocalY: parentY } = this.props.ContainingDocumentContentsView != undefined ? - this.props.ContainingDocumentContentsView!.TransformToLocalPoint(screenX, screenY) : + let { LocalX: parentX, LocalY: parentY } = this.props.ContainingCollectionView != undefined && this.props.ContainingCollectionView.props.DocumentContentsOfCollection != undefined ? + this.props.ContainingCollectionView.props.DocumentContentsOfCollection.TransformToLocalPoint(screenX, screenY) : { LocalX: screenX, LocalY: screenY }; let ContainerX: number = parentX - COLLECTION_BORDER_WIDTH; let ContainerY: number = parentY - COLLECTION_BORDER_WIDTH; @@ -115,7 +111,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps> { // if this collection view is nested within another collection view, then // first transform the local point into the parent collection's coordinate space. - let containingDocView = this.props.ContainingDocumentContentsView; + let containingDocView = this.props.ContainingCollectionView != undefined ? this.props.ContainingCollectionView.props.DocumentContentsOfCollection : undefined;//.ContainingDocumentContentsView; if (containingDocView != undefined) { let ss = containingDocView.props.Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1)); let panxx = containingDocView.props.Document.GetFieldValue(KeyStore.PanX, NumberField, Number(0)) + COLLECTION_BORDER_WIDTH * ss; @@ -126,13 +122,16 @@ export class DocumentContentsView extends React.Component<DocumentViewProps> { } return { ScreenX: parentX, ScreenY: parentY }; } + + render() { let doc = this.props.Document; let bindings = { ...this.props } as any; for (const key of this.layoutKeys) { bindings[key.Name + "Key"] = key; } - bindings.ContainingDocumentContentsView = this; + if (this.props.DocumentContentsView == undefined) + bindings.DocumentContentsView = this; for (const key of this.layoutFields) { let field = doc.GetField(key); if (field) { @@ -140,224 +139,18 @@ export class DocumentContentsView extends React.Component<DocumentViewProps> { } } return ( - //<div ref={this._mainCont}> - <JsxParser ref={this._mainCont} - components={{ FieldTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView }} - bindings={bindings} - jsx={this.layout} - showWarnings={true} - onError={(test: any) => { console.log(test) }} - /> - //</div> - ) - } -} - -@observer -export class DocumentView extends DocumentContentsView { - private _contextMenuCanOpen = false; - private _downX: number = 0; - private _downY: number = 0; - - constructor(props: DocumentViewProps) { - super(props); - } - get screenRect(): ClientRect | DOMRect { - if (this._mainCont.current) { - return this._mainCont.current.getBoundingClientRect(); - } - return new DOMRect(); - } - - @computed - get x(): number { - return this.props.Document.GetFieldValue(KeyStore.X, NumberField, Number(0)); - } - - @computed - get y(): number { - return this.props.Document.GetFieldValue(KeyStore.Y, NumberField, Number(0)); - } - - set x(x: number) { - this.props.Document.SetFieldValue(KeyStore.X, x, NumberField) - } - - set y(y: number) { - this.props.Document.SetFieldValue(KeyStore.Y, y, NumberField) - } - - @computed - get transform(): string { - return `translate(${this.x}px, ${this.y}px)`; - } - - @computed - get width(): number { - return this.props.Document.GetFieldValue(KeyStore.Width, NumberField, Number(0)); - } - - set width(w: number) { - this.props.Document.SetFieldValue(KeyStore.Width, w, NumberField) - } - - @computed - get height(): number { - return this.props.Document.GetFieldValue(KeyStore.Height, NumberField, Number(0)); - } - - set height(h: number) { - this.props.Document.SetFieldValue(KeyStore.Height, h, NumberField) - } - - @computed - get zIndex(): number { - return this.props.Document.GetFieldValue(KeyStore.ZIndex, NumberField, Number(0)); - } - - set zIndex(h: number) { - this.props.Document.SetFieldValue(KeyStore.ZIndex, h, NumberField) - } - - @action - dragComplete = (e: DragManager.DragCompleteEvent) => { - } - - @computed - get active(): boolean { - return SelectionManager.IsSelected(this) || this.props.ContainingCollectionView === undefined || this.props.ContainingCollectionView!.active; - } - - @computed - get topMost(): boolean { - return this.props.ContainingCollectionView == undefined || this.props.ContainingCollectionView instanceof CollectionDockingView; - } - - onPointerDown = (e: React.PointerEvent): void => { - this._downX = e.clientX; - this._downY = e.clientY; - var me = this; - if (e.shiftKey && e.buttons === 1) { - CollectionDockingView.StartOtherDrag(this._mainCont.current!, this.props.Document); - e.stopPropagation(); - return; - } - this._contextMenuCanOpen = e.button == 2; - if (this.active && !e.isDefaultPrevented()) { - e.stopPropagation(); - if (e.buttons === 2) { - e.preventDefault(); - } - document.removeEventListener("pointermove", this.onPointerMove) - document.addEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp) - document.addEventListener("pointerup", this.onPointerUp); - } - } - - onPointerMove = (e: PointerEvent): void => { - if (e.cancelBubble) { - this._contextMenuCanOpen = false; - return; - } - if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) { - this._contextMenuCanOpen = false; - if (this._mainCont.current != null && !this.topMost) { - this._contextMenuCanOpen = false; - const rect = this.screenRect; - let dragData: { [id: string]: any } = {}; - dragData["document"] = this; - dragData["xOffset"] = e.x - rect.left; - dragData["yOffset"] = e.y - rect.top; - DragManager.StartDrag(this._mainCont.current, dragData, { - handlers: { - dragComplete: this.dragComplete, - }, - hideSource: true - }) - } - } - e.stopPropagation(); - e.preventDefault(); - } - - onPointerUp = (e: PointerEvent): void => { - document.removeEventListener("pointermove", this.onPointerMove) - document.removeEventListener("pointerup", this.onPointerUp) - e.stopPropagation(); - if (Math.abs(e.clientX - this._downX) < 4 && Math.abs(e.clientY - this._downY) < 4) { - SelectionManager.SelectDoc(this, e.ctrlKey); - } - } - - openRight = (e: React.MouseEvent): void => { - CollectionDockingView.AddRightSplit(this.props.Document); - } - - deleteClicked = (e: React.MouseEvent): void => { - if (this.props.ContainingCollectionView instanceof CollectionFreeFormView) { - this.props.ContainingCollectionView.removeDocument(this.props.Document) - } - } - @action - fullScreenClicked = (e: React.MouseEvent): void => { - CollectionDockingView.OpenFullScreen(this.props.Document); - ContextMenu.Instance.clearItems(); - ContextMenu.Instance.addItem({ description: "Close Full Screen", event: this.closeFullScreenClicked }); - ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) - } - @action - closeFullScreenClicked = (e: React.MouseEvent): void => { - CollectionDockingView.CloseFullScreen(); - ContextMenu.Instance.clearItems(); - ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked }) - ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) - } - - @action - onContextMenu = (e: React.MouseEvent): void => { - if (!SelectionManager.IsSelected(this)) { - return; - } - e.preventDefault() - - if (!this._contextMenuCanOpen) { - return; - } - - if (this.topMost) { - ContextMenu.Instance.clearItems() - ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked }) - ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) - } - else { - // DocumentViews should stop propogation of this event - e.stopPropagation(); - - ContextMenu.Instance.clearItems(); - ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked }) - ContextMenu.Instance.addItem({ description: "Open Right", event: this.openRight }) - ContextMenu.Instance.addItem({ description: "Delete", event: this.deleteClicked }) - ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) - SelectionManager.SelectDoc(this, e.ctrlKey); - } - } - - render() { - var freestyling = this.props.ContainingCollectionView instanceof CollectionFreeFormView; - return ( <div className="node" ref={this._mainCont} style={{ - transform: freestyling ? this.transform : "", - width: freestyling ? this.width : "100%", - height: freestyling ? this.height : "100%", - position: freestyling ? "absolute" : "relative", - zIndex: freestyling ? this.zIndex : 0, - }} - onContextMenu={this.onContextMenu} - onPointerDown={this.onPointerDown}> - - <DocumentContentsView {...this.props} /> + width: "100%", + height: "100%", + }}> + <JsxParser + components={{ FieldTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView }} + bindings={bindings} + jsx={this.layout} + showWarnings={true} + onError={(test: any) => { console.log(test) }} + /> </div> - ); + ) } -}
\ No newline at end of file +} diff --git a/src/views/nodes/FieldTextBox.tsx b/src/views/nodes/FieldTextBox.tsx index 0a8706517..0e884a031 100644 --- a/src/views/nodes/FieldTextBox.tsx +++ b/src/views/nodes/FieldTextBox.tsx @@ -13,7 +13,7 @@ import "./FieldTextBox.scss"; import React = require("react") import { RichTextField } from "../../fields/RichTextField"; import { FieldViewProps } from "./FieldView"; -import { DocumentView } from "./DocumentView"; +import { CollectionFreeFormDocumentView } from "./CollectionFreeFormDocumentView"; // FieldTextBox: Displays an editable plain text node that maps to a specified Key of a Document @@ -34,7 +34,7 @@ import { DocumentView } from "./DocumentView"; // export class FieldTextBox extends React.Component<FieldViewProps> { - public static LayoutString() { return "<FieldTextBox doc={Document} documentViewContainer={ContainingDocumentView} fieldKey={DataKey} />"; } + public static LayoutString() { return "<FieldTextBox doc={Document} documentViewContainer={DocumentContentsView} fieldKey={DataKey} />"; } private _ref: React.RefObject<HTMLDivElement>; private _editorView: Opt<EditorView>; private _reactionDisposer: Opt<IReactionDisposer>; @@ -111,7 +111,7 @@ export class FieldTextBox extends React.Component<FieldViewProps> { } onPointerDown = (e: React.PointerEvent): void => { let me = this; - if (e.buttons === 1 && me.props.documentViewContainer instanceof DocumentView && SelectionManager.IsSelected(me.props.documentViewContainer)) { + if (e.buttons === 1 && me.props.documentViewContainer instanceof CollectionFreeFormDocumentView && SelectionManager.IsSelected(me.props.documentViewContainer)) { e.stopPropagation(); } } diff --git a/src/views/nodes/FieldView.tsx b/src/views/nodes/FieldView.tsx index b7a1d0526..9f0404dbf 100644 --- a/src/views/nodes/FieldView.tsx +++ b/src/views/nodes/FieldView.tsx @@ -1,5 +1,4 @@ import React = require("react") -import { DocumentView, DocumentContentsView } from "./DocumentView"; import { Document } from "../../fields/Document"; import { observer } from "mobx-react"; import { computed } from "mobx"; @@ -11,6 +10,7 @@ import { FieldTextBox } from "./FieldTextBox"; import { ImageField } from "../../fields/ImageField"; import { ImageBox } from "./ImageBox"; import { Key } from "../../fields/Key"; +import { DocumentView } from "./DocumentView"; // // these properties get assigned through the render() method of the DocumentView when it creates this node. @@ -20,7 +20,7 @@ import { Key } from "../../fields/Key"; export interface FieldViewProps { fieldKey: Key; doc: Document; - documentViewContainer: DocumentContentsView + documentViewContainer: DocumentView } @observer diff --git a/src/views/nodes/ImageBox.tsx b/src/views/nodes/ImageBox.tsx index d2f567423..a4254ce39 100644 --- a/src/views/nodes/ImageBox.tsx +++ b/src/views/nodes/ImageBox.tsx @@ -6,7 +6,7 @@ import "./ImageBox.scss"; import React = require("react") import { ImageField } from '../../fields/ImageField'; import { FieldViewProps } from './FieldView'; -import { DocumentView } from './DocumentView'; +import { CollectionFreeFormDocumentView } from './CollectionFreeFormDocumentView'; interface ImageBoxState { photoIndex: number, @@ -15,7 +15,7 @@ interface ImageBoxState { export class ImageBox extends React.Component<FieldViewProps, ImageBoxState> { - public static LayoutString() { return "<ImageBox doc={Document} documentViewContainer={ContainingDocumentView} fieldKey={DataKey} />"; } + public static LayoutString() { return "<ImageBox doc={Document} documentViewContainer={DocumentContentsView} fieldKey={DataKey} />"; } private _ref: React.RefObject<HTMLDivElement>; private _downX: number = 0; private _downY: number = 0; @@ -39,7 +39,7 @@ export class ImageBox extends React.Component<FieldViewProps, ImageBoxState> { onPointerDown = (e: React.PointerEvent): void => { if (Date.now() - this._lastTap < 300) { - if (e.buttons === 1 && this.props.documentViewContainer instanceof DocumentView && SelectionManager.IsSelected(this.props.documentViewContainer)) { + if (e.buttons === 1 && this.props.documentViewContainer instanceof CollectionFreeFormDocumentView && SelectionManager.IsSelected(this.props.documentViewContainer)) { e.stopPropagation(); this._downX = e.clientX; this._downY = e.clientY; @@ -67,7 +67,7 @@ export class ImageBox extends React.Component<FieldViewProps, ImageBoxState> { const images = [path,]; var lightbox = () => { const { photoIndex } = this.state; - if (this.state.isOpen && this.props.documentViewContainer instanceof DocumentView && SelectionManager.IsSelected(this.props.documentViewContainer)) { + if (this.state.isOpen && this.props.documentViewContainer instanceof CollectionFreeFormDocumentView && SelectionManager.IsSelected(this.props.documentViewContainer)) { return (<Lightbox mainSrc={images[photoIndex]} nextSrc={photoIndex + 1 < images.length ? images[(photoIndex + 1) % images.length] : undefined} |