diff options
Diffstat (limited to 'src/client/views/nodes/DocumentView.tsx')
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 154 |
1 files changed, 90 insertions, 64 deletions
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index bba5becc3..c5270e0cd 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -4,8 +4,6 @@ import { Document } from "../../../fields/Document"; import { Opt, FieldWaiting } from "../../../fields/Field"; import { Key, KeyStore } from "../../../fields/Key"; import { ListField } from "../../../fields/ListField"; -import { NumberField } from "../../../fields/NumberField"; -import { TextField } from "../../../fields/TextField"; import { Utils } from "../../../Utils"; import { CollectionDockingView } from "../collections/CollectionDockingView"; import { CollectionFreeFormView } from "../collections/CollectionFreeFormView"; @@ -13,31 +11,44 @@ import { CollectionSchemaView } from "../collections/CollectionSchemaView"; import { CollectionViewBase, COLLECTION_BORDER_WIDTH } from "../collections/CollectionViewBase"; import { FormattedTextBox } from "../nodes/FormattedTextBox"; import { ImageBox } from "../nodes/ImageBox"; -import "./NodeView.scss"; +import "./DocumentView.scss"; import React = require("react"); +import { Transform } from "../../util/Transform"; const JsxParser = require('react-jsx-parser').default;//TODO Why does this need to be imported like this? export interface DocumentViewProps { - Document: Document; DocumentView: Opt<DocumentView> // needed only to set ContainingDocumentView on CollectionViewProps when invoked from JsxParser -- is there a better way? ContainingCollectionView: Opt<CollectionViewBase>; - Scaling: number; + + Document: Document; + AddDocument?: (doc: Document) => void; + RemoveDocument?: (doc: Document) => boolean; + GetTransform: () => Transform; + ParentScaling: number; } + @observer export class DocumentView extends React.Component<DocumentViewProps> { + protected _renderDoc = React.createRef<any>(); protected _mainCont = React.createRef<any>(); get MainContent() { return this._mainCont; } + + @computed + get parentScaling(): number { + return this._renderDoc.current ? this._renderDoc.current.props.ParentScaling : this.props.ParentScaling > 0 ? this.props.ParentScaling : 1; + } + @computed get layout(): string { - return this.props.Document.GetData(KeyStore.Layout, TextField, String("<p>Error loading layout data</p>")); + return this.props.Document.GetText(KeyStore.Layout, "<p>Error loading layout data</p>"); } @computed - get annotatedlayout(): string { - return this.props.Document.GetData(KeyStore.AnnotatedLayout, TextField, String("<p>Error loading layout data</p>")); + get backgroundLayout(): string { + return this.props.Document.GetText(KeyStore.BackgroundLayout, ""); } @computed @@ -63,75 +74,78 @@ export class DocumentView extends React.Component<DocumentViewProps> { return 1; } + + public LeftCorner(): number { + if (this.props.ContainingCollectionView) { + if (this.props.ContainingCollectionView instanceof CollectionDockingView) { + // this is a hacky way to account for the titles/pane placement/etc of a CollectionDockingView + // this only works if the collectionDockingView is the root collection, too. + // need to find a better way. + var { translateX: rx, translateY: ry } = Utils.GetScreenTransform(this.MainContent.current!); + return rx + COLLECTION_BORDER_WIDTH; + } + return COLLECTION_BORDER_WIDTH; // assumes all collections have the same border + } + return 0; + } + + public TopCorner(): number { + if (this.props.ContainingCollectionView) { + if (this.props.ContainingCollectionView instanceof CollectionDockingView) { + // this is a hacky way to account for the titles/pane placement/etc of a CollectionDockingView + // this only works if the collectionDockingView is the root collection, too. + // need to find a better way. + var { translateX: rx, translateY: ry } = Utils.GetScreenTransform(this.MainContent.current!); + return ry + COLLECTION_BORDER_WIDTH; + } + return COLLECTION_BORDER_WIDTH; // assumes all collections have the same border + } + return 0; + } // - // Converts a coordinate in the screen space of the app into a local document coordinate. + // Converts a coordinate in the screen space of the app to a local point in the space of the DocumentView. + // This also returns the point in the coordinate space of this document's containing CollectionView // 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.ContainingCollectionView != undefined && - this.props.ContainingCollectionView.props.ContainingDocumentView != undefined ? - this.props.ContainingCollectionView.props.ContainingDocumentView.TransformToLocalPoint(screenX, screenY) : - { LocalX: screenX, LocalY: screenY }; + let containingCollectionViewDoc = this.props.ContainingCollectionView ? this.props.ContainingCollectionView.props.ContainingDocumentView : undefined; + let { LocalX: parentX, LocalY: parentY } = !containingCollectionViewDoc ? { LocalX: screenX, LocalY: screenY } : + containingCollectionViewDoc.TransformToLocalPoint(screenX, screenY); let ContainerX: number = parentX - COLLECTION_BORDER_WIDTH; let ContainerY: number = parentY - COLLECTION_BORDER_WIDTH; - var Xx = this.props.Document.GetData(KeyStore.X, NumberField, Number(0)); - var Yy = this.props.Document.GetData(KeyStore.Y, NumberField, Number(0)); - // CollectionDockingViews change the location of their children frames without using a Dash transformation. - // They also ignore any transformation that may have been applied to their content document. - // NOTE: this currently assumes CollectionDockingViews aren't nested. - if (this.props.ContainingCollectionView instanceof CollectionDockingView) { - var { translateX: rx, translateY: ry } = Utils.GetScreenTransform(this.MainContent.current!); - Xx = rx - COLLECTION_BORDER_WIDTH; - Yy = ry - COLLECTION_BORDER_WIDTH; - } - let Ss = this.props.Document.GetNumber(KeyStore.Scale, 1); - let Panxx = this.props.Document.GetData(KeyStore.PanX, NumberField, Number(0)); - let Panyy = this.props.Document.GetData(KeyStore.PanY, NumberField, Number(0)); - let LocalX = (ContainerX - (Xx + Panxx)) / Ss; - let LocalY = (ContainerY - (Yy + Panyy)) / Ss; + let Panxx = this.props.Document.GetNumber(KeyStore.PanX, 0); + let Panyy = this.props.Document.GetNumber(KeyStore.PanY, 0); + let LocalX = (ContainerX - (this.LeftCorner() + Panxx)) / Ss; + let LocalY = (ContainerY - (this.TopCorner() + Panyy)) / Ss; - return { LocalX, Ss, Panxx, Xx, LocalY, Panyy, Yy, ContainerX, ContainerY }; + return { LocalX, LocalY, ContainerX, ContainerY }; } // - // Converts a point in the coordinate space of a document to a screen space coordinate. + // Converts a point in the coordinate space of the document to coordinate in app screen coordinates // - public TransformToScreenPoint(localX: number, localY: number, Ss: number = 1, Panxx: number = 0, Panyy: number = 0): { ScreenX: number, ScreenY: number } { - - var Xx = this.props.Document.GetData(KeyStore.X, NumberField, Number(0)); - var Yy = this.props.Document.GetData(KeyStore.Y, NumberField, Number(0)); - // CollectionDockingViews change the location of their children frames without using a Dash transformation. - // They also ignore any transformation that may have been applied to their content document. - // NOTE: this currently assumes CollectionDockingViews aren't nested. - if (this.props.ContainingCollectionView instanceof CollectionDockingView) { - var { translateX: rx, translateY: ry } = Utils.GetScreenTransform(this.MainContent.current!); - Xx = rx - COLLECTION_BORDER_WIDTH; - Yy = ry - COLLECTION_BORDER_WIDTH; - } - - let W = COLLECTION_BORDER_WIDTH; - let H = COLLECTION_BORDER_WIDTH; - let parentX = (localX - W) * Ss + (Xx + Panxx) + W; - let parentY = (localY - H) * Ss + (Yy + Panyy) + H; - + public TransformToScreenPoint(localX: number, localY: number, applyViewXf: boolean = false): { ScreenX: number, ScreenY: number } { + var parentScaling = applyViewXf ? this.parentScaling : 1; + let Panxx = applyViewXf ? this.props.Document.GetNumber(KeyStore.PanX, 0) : 0; + let Panyy = applyViewXf ? this.props.Document.GetNumber(KeyStore.PanY, 0) : 0; + var Zoom = applyViewXf ? this.props.Document.GetNumber(KeyStore.Scale, 1) : 1; + + let parentX = this.LeftCorner() + (Panxx + (localX - COLLECTION_BORDER_WIDTH) * Zoom) * parentScaling; + let parentY = this.TopCorner() + (Panyy + (localY - COLLECTION_BORDER_WIDTH) * Zoom) * parentScaling; // 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.ContainingCollectionView != undefined ? this.props.ContainingCollectionView.props.ContainingDocumentView : undefined; - if (containingDocView != undefined) { - let ss = containingDocView.props.Document.GetNumber(KeyStore.Scale, 1) * this.props.Scaling; - let panxx = containingDocView.props.Document.GetData(KeyStore.PanX, NumberField, Number(0)) + COLLECTION_BORDER_WIDTH * ss; - let panyy = containingDocView.props.Document.GetData(KeyStore.PanY, NumberField, Number(0)) + COLLECTION_BORDER_WIDTH * ss; - let { ScreenX, ScreenY } = containingDocView.TransformToScreenPoint(parentX, parentY, ss, panxx, panyy); + let containingDocView = this.props.ContainingCollectionView ? this.props.ContainingCollectionView.props.ContainingDocumentView : undefined; + if (containingDocView) { + let { ScreenX, ScreenY } = containingDocView.TransformToScreenPoint(parentX + COLLECTION_BORDER_WIDTH * parentScaling, parentY + COLLECTION_BORDER_WIDTH * parentScaling, true); parentX = ScreenX; parentY = ScreenY; } return { ScreenX: parentX, ScreenY: parentY }; } - render() { let bindings = { ...this.props } as any; for (const key of this.layoutKeys) { @@ -144,16 +158,28 @@ export class DocumentView extends React.Component<DocumentViewProps> { if (bindings.DocumentView === undefined) { bindings.DocumentView = this; // set the DocumentView to this if it hasn't already been set by a sub-class during its render method. } - var annotated = <JsxParser - components={{ FormattedTextBox: FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView }} - bindings={bindings} - jsx={this.annotatedlayout} - showWarnings={true} - onError={(test: any) => { console.log(test) }} - />; - bindings["BackgroundView"] = this.annotatedlayout ? annotated : null; + if (this.backgroundLayout) { + var backgroundview = <JsxParser + components={{ FormattedTextBox: FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView }} + bindings={bindings} + jsx={this.backgroundLayout} + showWarnings={true} + onError={(test: any) => { console.log(test) }} + />; + bindings["BackgroundView"] = backgroundview; + } + var nativewidth = this.props.Document.GetNumber(KeyStore.NativeWidth, 0); + var nativeheight = this.props.Document.GetNumber(KeyStore.NativeHeight, 0); + var width = nativewidth > 0 ? nativewidth + "px" : "100%"; + var height = nativeheight > 0 ? nativeheight + "px" : "100%"; return ( - <div className="node" ref={this._mainCont} style={{ width: "100%", height: "100%", }}> + <div className="documentView-node" ref={this._mainCont} + style={{ + width: width, + height: height, + transformOrigin: "top left", + transform: `scale(${this.props.ParentScaling},${this.props.ParentScaling})` + }}> <JsxParser components={{ FormattedTextBox: FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView }} bindings={bindings} |