diff options
Diffstat (limited to 'src/client/views/nodes/DocumentView.tsx')
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 258 |
1 files changed, 74 insertions, 184 deletions
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 4d7a85316..b99e449be 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1,30 +1,32 @@ -import { action, computed, IReactionDisposer, reaction, runInAction, trace } from "mobx"; +import { action, computed, runInAction } from "mobx"; import { observer } from "mobx-react"; +import { BooleanField } from "../../../fields/BooleanField"; import { Document } from "../../../fields/Document"; import { Field, FieldWaiting, Opt } from "../../../fields/Field"; import { Key } from "../../../fields/Key"; import { KeyStore } from "../../../fields/KeyStore"; import { ListField } from "../../../fields/ListField"; -import { BooleanField } from "../../../fields/BooleanField"; import { TextField } from "../../../fields/TextField"; import { ServerUtils } from "../../../server/ServerUtil"; -import { Utils, emptyFunction } from "../../../Utils"; +import { emptyFunction, Utils } from "../../../Utils"; import { Documents } from "../../documents/Documents"; import { DocumentManager } from "../../util/DocumentManager"; import { DragManager } from "../../util/DragManager"; import { SelectionManager } from "../../util/SelectionManager"; import { Transform } from "../../util/Transform"; +import { undoBatch, UndoManager } from "../../util/UndoManager"; import { CollectionDockingView } from "../collections/CollectionDockingView"; +import { CollectionPDFView } from "../collections/CollectionPDFView"; +import { CollectionVideoView } from "../collections/CollectionVideoView"; import { CollectionView } from "../collections/CollectionView"; import { ContextMenu } from "../ContextMenu"; import { DocumentContentsView } from "./DocumentContentsView"; import "./DocumentView.scss"; import React = require("react"); -import { undoBatch, UndoManager } from "../../util/UndoManager"; export interface DocumentViewProps { - ContainingCollectionView: Opt<CollectionView>; + ContainingCollectionView: Opt<CollectionView | CollectionPDFView | CollectionVideoView>; Document: Document; addDocument?: (doc: Document, allowDuplicates?: boolean) => boolean; removeDocument?: (doc: Document) => boolean; @@ -63,14 +65,12 @@ export function FakeJsxArgs(keys: string[], fields: string[] = []): JsxArgs { let Keys: { [name: string]: any } = {}; let Fields: { [name: string]: any } = {}; for (const key of keys) { - let fn = emptyFunction; - Object.defineProperty(fn, "name", { value: key + "Key" }); - Keys[key] = fn; + Object.defineProperty(emptyFunction, "name", { value: key + "Key" }); + Keys[key] = emptyFunction; } for (const field of fields) { - let fn = emptyFunction; - Object.defineProperty(fn, "name", { value: field }); - Fields[field] = fn; + Object.defineProperty(emptyFunction, "name", { value: field }); + Fields[field] = emptyFunction; } let args: JsxArgs = { Document: function Document() { }, @@ -83,21 +83,24 @@ export function FakeJsxArgs(keys: string[], fields: string[] = []): JsxArgs { @observer export class DocumentView extends React.Component<DocumentViewProps> { - private _mainCont = React.createRef<HTMLDivElement>(); - public get ContentRef() { - return this._mainCont; - } private _downX: number = 0; private _downY: number = 0; + private _mainCont = React.createRef<HTMLDivElement>(); + private _dropDisposer?: DragManager.DragDropDisposer; + + public get ContentDiv() { return this._mainCont.current; } @computed get active(): boolean { return SelectionManager.IsSelected(this) || this.props.parentActive(); } @computed get topMost(): boolean { return this.props.isTopMost; } @computed get layout(): string { return this.props.Document.GetText(KeyStore.Layout, "<p>Error loading layout data</p>"); } @computed get layoutKeys(): Key[] { return this.props.Document.GetData(KeyStore.LayoutKeys, ListField, new Array<Key>()); } @computed get layoutFields(): Key[] { return this.props.Document.GetData(KeyStore.LayoutFields, ListField, new Array<Key>()); } - screenRect = (): ClientRect | DOMRect => this._mainCont.current ? this._mainCont.current.getBoundingClientRect() : new DOMRect(); + onPointerDown = (e: React.PointerEvent): void => { this._downX = e.clientX; this._downY = e.clientY; + if (e.button === 2 && !this.isSelected()) { + return; + } if (e.shiftKey && e.buttons === 2) { if (this.props.isTopMost) { this.startDragging(e.pageX, e.pageY, e.altKey || e.ctrlKey); @@ -116,11 +119,9 @@ export class DocumentView extends React.Component<DocumentViewProps> { } } - private dropDisposer?: DragManager.DragDropDisposer; - componentDidMount() { if (this._mainCont.current) { - this.dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, { + this._dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, { handlers: { drop: this.drop.bind(this) } }); } @@ -128,29 +129,26 @@ export class DocumentView extends React.Component<DocumentViewProps> { } componentDidUpdate() { - if (this.dropDisposer) { - this.dropDisposer(); + if (this._dropDisposer) { + this._dropDisposer(); } if (this._mainCont.current) { - this.dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, { + this._dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, { handlers: { drop: this.drop.bind(this) } }); } } componentWillUnmount() { - if (this.dropDisposer) { - this.dropDisposer(); + if (this._dropDisposer) { + this._dropDisposer(); } 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); + const [left, top] = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0); let dragData = new DragManager.DocumentDragData([this.props.Document]); dragData.aliasOnDrop = dropAliasOfDraggedDoc; dragData.xOffset = x - left; @@ -169,10 +167,7 @@ export class DocumentView extends React.Component<DocumentViewProps> { if (e.cancelBubble) { return; } - if ( - Math.abs(this._downX - e.clientX) > 3 || - Math.abs(this._downY - e.clientY) > 3 - ) { + if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) { document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); if (!this.topMost || e.buttons === 2 || e.altKey) { @@ -186,22 +181,17 @@ export class DocumentView extends React.Component<DocumentViewProps> { document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); e.stopPropagation(); - if (!SelectionManager.IsSelected(this) && - e.button !== 2 && - Math.abs(e.clientX - this._downX) < 4 && - Math.abs(e.clientY - this._downY) < 4 - ) { + if (!SelectionManager.IsSelected(this) && e.button !== 2 && + Math.abs(e.clientX - this._downX) < 4 && Math.abs(e.clientY - this._downY) < 4) { SelectionManager.SelectDoc(this, e.ctrlKey); } } - stopPropogation = (e: React.SyntheticEvent) => { + stopPropagation = (e: React.SyntheticEvent) => { e.stopPropagation(); } deleteClicked = (): void => { - if (this.props.removeDocument) { - this.props.removeDocument(this.props.Document); - } + this.props.removeDocument && this.props.removeDocument(this.props.Document); } fieldsClicked = (e: React.MouseEvent): void => { @@ -210,32 +200,22 @@ export class DocumentView extends React.Component<DocumentViewProps> { } } fullScreenClicked = (e: React.MouseEvent): void => { - CollectionDockingView.Instance.OpenFullScreen(this.props.Document); + CollectionDockingView.Instance.OpenFullScreen((this.props.Document.GetPrototype() as Document).MakeDelegate()); ContextMenu.Instance.clearItems(); - ContextMenu.Instance.addItem({ - description: "Close Full Screen", - event: this.closeFullScreenClicked - }); + ContextMenu.Instance.addItem({ description: "Close Full Screen", event: this.closeFullScreenClicked }); ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); } closeFullScreenClicked = (e: React.MouseEvent): void => { CollectionDockingView.Instance.CloseFullScreen(); ContextMenu.Instance.clearItems(); - ContextMenu.Instance.addItem({ - description: "Full Screen", - event: this.fullScreenClicked - }); + ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked }); ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); } @action public minimize = (): void => { - this.props.Document.SetData( - KeyStore.Minimized, - true as boolean, - BooleanField - ); + this.props.Document.SetBoolean(KeyStore.Minimized, true); SelectionManager.DeselectAll(); } @@ -251,9 +231,9 @@ export class DocumentView extends React.Component<DocumentViewProps> { sourceDoc.GetTAsync(KeyStore.Prototype, Document).then(protoSrc => runInAction(() => { let batch = UndoManager.StartBatch("document view drop"); - linkDoc.Set(KeyStore.Title, new TextField("New Link")); - linkDoc.Set(KeyStore.LinkDescription, new TextField("")); - linkDoc.Set(KeyStore.LinkTags, new TextField("Default")); + linkDoc.SetText(KeyStore.Title, "New Link"); + linkDoc.SetText(KeyStore.LinkDescription, ""); + linkDoc.SetText(KeyStore.LinkTags, "Default"); let dstTarg = protoDest ? protoDest : destDoc; let srcTarg = protoSrc ? protoSrc : sourceDoc; @@ -284,11 +264,8 @@ export class DocumentView extends React.Component<DocumentViewProps> { } onDrop = (e: React.DragEvent) => { - if (e.isDefaultPrevented()) { - return; - } let text = e.dataTransfer.getData("text/plain"); - if (text && text.startsWith("<div")) { + if (!e.isDefaultPrevented() && text && text.startsWith("<div")) { let oldLayout = this.props.Document.GetText(KeyStore.Layout, ""); let layout = text.replace("{layout}", oldLayout); this.props.Document.SetText(KeyStore.Layout, layout); @@ -300,145 +277,58 @@ export class DocumentView extends React.Component<DocumentViewProps> { @action onContextMenu = (e: React.MouseEvent): void => { e.stopPropagation(); - let moved = - Math.abs(this._downX - e.clientX) > 3 || - Math.abs(this._downY - e.clientY) > 3; - if (moved || e.isDefaultPrevented()) { + if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3 || + e.isDefaultPrevented()) { e.preventDefault(); return; } e.preventDefault(); - if (!this.isMinimized()) { - ContextMenu.Instance.addItem({ - description: "Minimize", - event: this.minimize - }); - } - ContextMenu.Instance.addItem({ - description: "Full Screen", - event: this.fullScreenClicked - }); - ContextMenu.Instance.addItem({ - description: "Fields", - event: this.fieldsClicked - }); - ContextMenu.Instance.addItem({ - description: "Center", - event: () => this.props.focus(this.props.Document) - }); - ContextMenu.Instance.addItem({ - description: "Open Right", - event: () => - CollectionDockingView.Instance.AddRightSplit(this.props.Document) - }); - ContextMenu.Instance.addItem({ - description: "Copy URL", - event: () => { - Utils.CopyText(ServerUtils.prepend("/doc/" + this.props.Document.Id)); - } - }); - ContextMenu.Instance.addItem({ - description: "Copy ID", - event: () => { - Utils.CopyText(this.props.Document.Id); - } - }); + !this.isMinimized() && ContextMenu.Instance.addItem({ description: "Minimize", event: this.minimize }); + ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked }); + ContextMenu.Instance.addItem({ description: "Fields", event: this.fieldsClicked }); + ContextMenu.Instance.addItem({ description: "Center", event: () => this.props.focus(this.props.Document) }); + ContextMenu.Instance.addItem({ description: "Open Right", event: () => CollectionDockingView.Instance.AddRightSplit(this.props.Document) }); + ContextMenu.Instance.addItem({ description: "Copy URL", event: () => Utils.CopyText(ServerUtils.prepend("/doc/" + this.props.Document.Id)) }); + ContextMenu.Instance.addItem({ description: "Copy ID", event: () => Utils.CopyText(this.props.Document.Id) }); //ContextMenu.Instance.addItem({ description: "Docking", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Docking) }) + ContextMenu.Instance.addItem({ description: "Delete", event: this.deleteClicked }); ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); - if (!this.topMost) { - // DocumentViews should stop propagation of this event - e.stopPropagation(); - } - - ContextMenu.Instance.addItem({ - description: "Delete", - event: this.deleteClicked - }); - ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); - SelectionManager.SelectDoc(this, e.ctrlKey); - } - - isMinimized = () => { - let field = this.props.Document.GetT(KeyStore.Minimized, BooleanField); - if (field && field !== FieldWaiting) { - return field.Data; - } + if (!SelectionManager.IsSelected(this)) + SelectionManager.SelectDoc(this, false); } @action - expand = () => { - this.props.Document.SetData( - KeyStore.Minimized, - false as boolean, - BooleanField - ); - } - + expand = () => this.props.Document.SetBoolean(KeyStore.Minimized, false) + isMinimized = () => this.props.Document.GetBoolean(KeyStore.Minimized, false); isSelected = () => SelectionManager.IsSelected(this); + select = (ctrlPressed: boolean) => SelectionManager.SelectDoc(this, ctrlPressed); - select = (ctrlPressed: boolean) => { - SelectionManager.SelectDoc(this, ctrlPressed); - } - - @computed get nativeWidth(): number { return this.props.Document.GetNumber(KeyStore.NativeWidth, 0); } - @computed get nativeHeight(): number { return this.props.Document.GetNumber(KeyStore.NativeHeight, 0); } - @computed - get contents() { - return (<DocumentContentsView - {...this.props} - isSelected={this.isSelected} - select={this.select} - layoutKey={KeyStore.Layout} - />); - } + @computed get nativeWidth() { return this.props.Document.GetNumber(KeyStore.NativeWidth, 0); } + @computed get nativeHeight() { return this.props.Document.GetNumber(KeyStore.NativeHeight, 0); } + @computed get contents() { return (<DocumentContentsView {...this.props} isSelected={this.isSelected} select={this.select} layoutKey={KeyStore.Layout} />); } render() { - if (!this.props.Document) { - return null; - } - var scaling = this.props.ContentScaling(); - var nativeWidth = this.nativeWidth; - var nativeHeight = this.nativeHeight; + var nativeHeight = this.nativeHeight > 0 ? this.nativeHeight.toString() + "px" : "100%"; + var nativeWidth = this.nativeWidth > 0 ? this.nativeWidth.toString() + "px" : "100%"; if (this.isMinimized()) { - return ( - <div - className="minimized-box" - ref={this._mainCont} - style={{ - transformOrigin: "left top", - transform: `scale(${scaling} , ${scaling})` - }} - onClick={this.expand} - onDrop={this.onDrop} - onPointerDown={this.onPointerDown} - /> - ); - } else { - var backgroundcolor = this.props.Document.GetText( - KeyStore.BackgroundColor, - "" - ); - return ( - <div - className="documentView-node" - ref={this._mainCont} - style={{ - background: backgroundcolor, - width: nativeWidth > 0 ? nativeWidth.toString() + "px" : "100%", - height: nativeHeight > 0 ? nativeHeight.toString() + "px" : "100%", - transformOrigin: "left top", - transform: `scale(${scaling} , ${scaling})` - }} - onDrop={this.onDrop} - onContextMenu={this.onContextMenu} - onPointerDown={this.onPointerDown} - > - {this.contents} - </div> - ); + return <div className="minimized-box" ref={this._mainCont} onClick={this.expand} onDrop={this.onDrop} + style={{ transform: `scale(${scaling} , ${scaling})` }} onPointerDown={this.onPointerDown} />; } + return ( + <div className={`documentView-node${this.props.isTopMost ? "-topmost" : ""}`} + ref={this._mainCont} + style={{ + background: this.props.Document.GetText(KeyStore.BackgroundColor, ""), + width: nativeWidth, height: nativeHeight, + transform: `scale(${scaling}, ${scaling})` + }} + onDrop={this.onDrop} onContextMenu={this.onContextMenu} onPointerDown={this.onPointerDown} + > + {this.contents} + </div> + ); } } |