diff options
-rw-r--r-- | src/Main.tsx | 8 | ||||
-rw-r--r-- | src/documents/Documents.ts | 21 | ||||
-rw-r--r-- | src/fields/Key.ts | 2 | ||||
-rw-r--r-- | src/views/freeformcanvas/CollectionFreeFormView.scss | 15 | ||||
-rw-r--r-- | src/views/freeformcanvas/CollectionFreeFormView.tsx | 83 | ||||
-rw-r--r-- | src/views/freeformcanvas/FreeFormCanvas.tsx | 23 | ||||
-rw-r--r-- | src/views/freeformcanvas/NodeContainer.tsx | 28 | ||||
-rw-r--r-- | src/views/nodes/DocumentView.tsx | 4 | ||||
-rw-r--r-- | src/views/nodes/FieldTextBox.tsx | 20 |
9 files changed, 162 insertions, 42 deletions
diff --git a/src/Main.tsx b/src/Main.tsx index 583761dbd..a3b9bc96f 100644 --- a/src/Main.tsx +++ b/src/Main.tsx @@ -2,17 +2,14 @@ import * as React from 'react'; import * as ReactDOM from 'react-dom'; import "./Main.scss"; import { NodeCollectionStore } from './stores/NodeCollectionStore'; -import { RootStore } from './stores/RootStore'; import { StaticTextNodeStore } from './stores/StaticTextNodeStore'; import { VideoNodeStore } from './stores/VideoNodeStore'; import { FreeFormCanvas } from './views/freeformcanvas/FreeFormCanvas'; import { Key, KeyStore as KS } from './fields/Key'; import { NumberField } from './fields/NumberField'; import { Document } from './fields/Document'; -import { TextField } from './fields/TextField'; import { configure, runInAction } from 'mobx'; import { NodeStore } from './stores/NodeStore'; -import { ListField } from './fields/ListField'; import { Documents } from './documents/Documents'; configure({ @@ -48,9 +45,14 @@ runInAction(() => { doc2.SetField(KS.X, new NumberField(150)); doc2.SetField(KS.Y, new NumberField(20)); let doc3 = Documents.ImageDocument("https://static.boredpanda.com/blog/wp-content/uploads/2018/04/5acb63d83493f__700-png.jpg", { + x: 150, y: 500 + }); + let docset = new Array<Document>(doc1, doc2); + let doc4 = Documents.CollectionDocument(docset, { x: 100, y: 400 }); mainNodeCollection.Docs.push(doc1); mainNodeCollection.Docs.push(doc2); + mainNodeCollection.Docs.push(doc4); mainNodeCollection.Docs.push(doc3); });
\ No newline at end of file diff --git a/src/documents/Documents.ts b/src/documents/Documents.ts index 20d4596fd..bba678bbd 100644 --- a/src/documents/Documents.ts +++ b/src/documents/Documents.ts @@ -68,4 +68,25 @@ export namespace Documents { doc.SetField(KeyStore.Data, new TextField(url)); return doc; } + + let collectionProto:Document; + function GetCollectionPrototype(): Document { + if(!collectionProto) { + collectionProto = new Document(); + collectionProto.SetField(KeyStore.X, new NumberField(150)); + collectionProto.SetField(KeyStore.Y, new NumberField(0)); + collectionProto.SetField(KeyStore.Width, new NumberField(300)); + collectionProto.SetField(KeyStore.Height, new NumberField(300)); + collectionProto.SetField(KeyStore.Layout, new TextField('<CollectionFreeFormView doc={doc} fieldKey={DataKey}/>')); + collectionProto.SetField(KeyStore.LayoutKeys, new ListField([KeyStore.Data])); + } + return collectionProto; + } + + export function CollectionDocument( documents: Array<Document>, options:DocumentOptions = {}): Document { + let doc = GetCollectionPrototype().MakeDelegate(); + setupOptions(doc, options); + doc.SetField(KeyStore.Data, new ListField(documents)); + return doc; + } }
\ No newline at end of file diff --git a/src/fields/Key.ts b/src/fields/Key.ts index cd67e0a00..db30f545d 100644 --- a/src/fields/Key.ts +++ b/src/fields/Key.ts @@ -34,6 +34,8 @@ export namespace KeyStore { export let Prototype = new Key("Prototype"); export let X = new Key("X"); export let Y = new Key("Y"); + export let PanX = new Key("PanX"); + export let PanY = new Key("PanY"); export let Width = new Key("Width"); export let Height = new Key("Height"); export let Data = new Key("Data"); diff --git a/src/views/freeformcanvas/CollectionFreeFormView.scss b/src/views/freeformcanvas/CollectionFreeFormView.scss new file mode 100644 index 000000000..cb4805eb3 --- /dev/null +++ b/src/views/freeformcanvas/CollectionFreeFormView.scss @@ -0,0 +1,15 @@ +.collectionfreeformview-container { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + overflow: hidden; + + .collectionfreeformview { + position: absolute; + top: 0; + left: 0; + } +} + diff --git a/src/views/freeformcanvas/CollectionFreeFormView.tsx b/src/views/freeformcanvas/CollectionFreeFormView.tsx new file mode 100644 index 000000000..7c523e70d --- /dev/null +++ b/src/views/freeformcanvas/CollectionFreeFormView.tsx @@ -0,0 +1,83 @@ +import { observer } from "mobx-react"; +import { Key, KeyStore } from "../../fields/Key"; +import "./FreeFormCanvas.scss"; +import React = require("react"); +import { action } from "mobx"; +import { Document } from "../../fields/Document"; +import {DocumentViewModel} from "../../viewmodels/DocumentViewModel"; +import {DocumentView} from "../nodes/DocumentView"; +import {ListField} from "../../fields/ListField"; +import {NumberField} from "../../fields/NumberField"; + +interface IProps { + fieldKey:Key; + doc:Document; +} + +@observer +export class CollectionFreeFormView extends React.Component<IProps> { + + private _isPointerDown: boolean = false; + + constructor(props:IProps) { + super(props); + } + + @action + onPointerDown = (e: React.PointerEvent): void => { + e.stopPropagation(); + this._isPointerDown = true; + document.removeEventListener("pointermove", this.onPointerMove); + document.addEventListener("pointermove", this.onPointerMove); + document.removeEventListener("pointerup", this.onPointerUp); + document.addEventListener("pointerup", this.onPointerUp); + } + + @action + onPointerUp = (e: PointerEvent): void => { + e.stopPropagation(); + this._isPointerDown = false; + document.removeEventListener("pointermove", this.onPointerMove); + document.removeEventListener("pointerup", this.onPointerUp); + } + + @action + onPointerMove = (e: PointerEvent): void => { + e.preventDefault(); + e.stopPropagation(); + if (!this._isPointerDown) { + return; + } + const {doc} = this.props; + let x = doc.GetFieldValue(KeyStore.PanX, NumberField, Number(0)); + let y = doc.GetFieldValue(KeyStore.PanY, NumberField, Number(0)); + doc.SetFieldValue(KeyStore.PanX, x+e.movementX, NumberField); + doc.SetFieldValue(KeyStore.PanY, y+e.movementY, NumberField); + } + + @action + onPointerWheel = (e: React.WheelEvent): void => { + e.stopPropagation(); + + let scaleAmount = 1 - (e.deltaY / 1000); + //this.props.store.Scale *= scaleAmount; + } + + render() { + const {fieldKey, doc} = this.props; + const value: Document[] = doc.GetFieldValue(fieldKey, ListField, []); + const panx: number = doc.GetFieldValue(KeyStore.PanX, NumberField, Number(0)); + const pany: number = doc.GetFieldValue(KeyStore.PanY, NumberField, Number(0)); + return ( + <div className="collectionfreeformview-container" onPointerDown={this.onPointerDown} onWheel={this.onPointerWheel}> + <div className="collectionfreeformview" style={{ transform: `translate(${panx}px, ${pany}px)`, transformOrigin: '50% 50%' }}> + <div className="node-container"> + {value.map(doc => { + return (<DocumentView key={doc.Id} dvm={new DocumentViewModel(doc)} />); + })} + </div> + </div> + </div> + ); + } +}
\ No newline at end of file diff --git a/src/views/freeformcanvas/FreeFormCanvas.tsx b/src/views/freeformcanvas/FreeFormCanvas.tsx index 344eb2bd8..cee093fcb 100644 --- a/src/views/freeformcanvas/FreeFormCanvas.tsx +++ b/src/views/freeformcanvas/FreeFormCanvas.tsx @@ -1,15 +1,18 @@ import { observer } from "mobx-react"; +import { Key } from "../../fields/Key"; import { NodeCollectionStore } from "../../stores/NodeCollectionStore"; import "./FreeFormCanvas.scss"; -import { NodeContainer } from "./NodeContainer"; import React = require("react"); -import { KeyStore } from "../../fields/Key"; -import { NumberField } from "../../fields/NumberField"; -import { TextField } from "../../fields/TextField"; import { action } from "mobx"; +import { Document } from "../../fields/Document"; +import {DocumentViewModel} from "../../viewmodels/DocumentViewModel"; +import {DocumentView} from "../nodes/DocumentView"; +import {TextField} from "../../fields/TextField"; +import {ListField} from "../../fields/ListField"; +import {Field} from "../../fields/Field"; interface IProps { - store: NodeCollectionStore + store: NodeCollectionStore; } @observer @@ -17,6 +20,10 @@ export class FreeFormCanvas extends React.Component<IProps> { private _isPointerDown: boolean = false; + constructor(props:IProps) { + super(props); + } + @action onPointerDown = (e: React.PointerEvent): void => { e.stopPropagation(); @@ -63,7 +70,11 @@ export class FreeFormCanvas extends React.Component<IProps> { return ( <div className="freeformcanvas-container" onPointerDown={this.onPointerDown} onWheel={this.onPointerWheel}> <div className="freeformcanvas" style={{ transform: store.Transform, transformOrigin: '50% 50%' }}> - <NodeContainer store={store} /> + <div className="node-container"> + {this.props.store.Docs.map(doc => { + return (<DocumentView key={doc.Id} dvm={new DocumentViewModel(doc)} />); + })} + </div> </div> </div> ); diff --git a/src/views/freeformcanvas/NodeContainer.tsx b/src/views/freeformcanvas/NodeContainer.tsx deleted file mode 100644 index 6c3cb2af2..000000000 --- a/src/views/freeformcanvas/NodeContainer.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { observer } from "mobx-react"; -import { NodeCollectionStore } from "../../stores/NodeCollectionStore"; -import { StaticTextNodeStore } from "../../stores/StaticTextNodeStore"; -import { VideoNodeStore } from "../../stores/VideoNodeStore"; -import { TextNodeView } from "../nodes/TextNodeView"; -import { VideoNodeView } from "../nodes/VideoNodeView"; -import "./FreeFormCanvas.scss"; -import React = require("react"); -import { DocumentView } from "../nodes/DocumentView"; -import { DocumentViewModel } from "../../viewmodels/DocumentViewModel"; - -interface IProps { - store: NodeCollectionStore -} - -@observer -export class NodeContainer extends React.Component<IProps> { - - render() { - return ( - <div className="node-container"> - {this.props.store.Docs.map(doc => { - return (<DocumentView key={doc.Id} dvm={new DocumentViewModel(doc)} />); - })} - </div> - ); - } -}
\ No newline at end of file diff --git a/src/views/nodes/DocumentView.tsx b/src/views/nodes/DocumentView.tsx index f31069aa3..b9fbef91c 100644 --- a/src/views/nodes/DocumentView.tsx +++ b/src/views/nodes/DocumentView.tsx @@ -7,6 +7,8 @@ import { TextField } from "../../fields/TextField"; import { DocumentViewModel } from "../../viewmodels/DocumentViewModel"; import { ListField } from "../../fields/ListField"; import { FieldTextBox } from "../nodes/FieldTextBox" +import { FreeFormCanvas } from "../freeformcanvas/FreeFormCanvas" +import { CollectionFreeFormView } from "../freeformcanvas/CollectionFreeFormView" import "./NodeView.scss" const JsxParser = require('react-jsx-parser').default;//TODO Why does this need to be imported like this? @@ -83,7 +85,7 @@ export class DocumentView extends React.Component<IProps> { height: this.height }}> <JsxParser - components={{ FieldTextBox }} + components={{ FieldTextBox, FreeFormCanvas, CollectionFreeFormView }} bindings={bindings} jsx={this.layout} /> diff --git a/src/views/nodes/FieldTextBox.tsx b/src/views/nodes/FieldTextBox.tsx index 4615940bd..5df3e6012 100644 --- a/src/views/nodes/FieldTextBox.tsx +++ b/src/views/nodes/FieldTextBox.tsx @@ -11,15 +11,27 @@ interface IProps { test:string; } +// FieldTextBox: Displays an editable plain text node that maps to a specified Key of a Document +// +// HTML Markup: <FieldTextBox Doc={Document's ID} FieldKey={Key's name + "Key"} +// +// In Code, the node's HTML is specified in the document's parameterized structure as: +// document.SetField(KeyStore.Layout, "<FieldTextBox doc={doc} fieldKey={<KEYNAME>Key} />"); +// and the node's binding to the specified document KEYNAME as: +// document.SetField(KeyStore.LayoutKeys, new ListField([KeyStore.<KEYNAME>])); +// The Jsx parser at run time will bind: +// 'fieldKey' property to the Key stored in LayoutKeys +// and 'doc' property to the document that is being rendered +// +// When rendered() by React, this extracts the TextController from the Document stored at the +// specified Key and assigns it to an HTML input node. When changes are made tot his node, +// this will edit the document and assign the new value to that field. +// @observer export class FieldTextBox extends React.Component<IProps, IProps> { - readonly doc:Document; - readonly fieldKey:Key; constructor(props:IProps) { super(props); - this.doc = props.doc; - this.fieldKey = props.fieldKey; this.onChange = this.onChange.bind(this); } |