diff options
author | Tyler Schicke <tyler_schicke@brown.edu> | 2019-01-17 04:27:26 -0500 |
---|---|---|
committer | Tyler Schicke <tyler_schicke@brown.edu> | 2019-01-17 04:27:26 -0500 |
commit | 7943126ce9694af8e53d2997481c18ca0c17754c (patch) | |
tree | 7c3563e9a07345d1a110e8abb5b8563a3aec90fa | |
parent | 89204d74d2a5014b4e241973b1bdb8461ed4f78c (diff) |
Added editable text and image notes
-rw-r--r-- | src/Main.tsx | 14 | ||||
-rw-r--r-- | src/documents/Documents.ts | 71 | ||||
-rw-r--r-- | src/fields/Key.ts | 12 | ||||
-rw-r--r-- | src/views/freeformcanvas/FreeFormCanvas.tsx | 12 | ||||
-rw-r--r-- | src/views/nodes/DocumentView.tsx | 27 | ||||
-rw-r--r-- | src/views/nodes/FieldTextBox.tsx | 37 | ||||
-rw-r--r-- | src/views/nodes/NodeView.scss | 4 |
7 files changed, 148 insertions, 29 deletions
diff --git a/src/Main.tsx b/src/Main.tsx index 21d8b4c1a..583761dbd 100644 --- a/src/Main.tsx +++ b/src/Main.tsx @@ -13,6 +13,7 @@ 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({ enforceActions: "observed" @@ -42,17 +43,14 @@ for (let i = 0; i < 20; i++) { runInAction(() => { mainNodeCollection.AddNodes(nodes); - let doc1 = new Document(); - doc1.SetField(KS.X, new NumberField(5)); - doc1.SetField(KS.Y, new NumberField(5)); - doc1.SetField(KS.Width, new NumberField(100)); - doc1.SetField(KS.Height, new NumberField(50)); - doc1.SetField(KS.Data, new TextField("Hello world")); - doc1.SetField(KS.View, new TextField('<p style="color:blue; font-size:40px">{Data + X}</p>')); - doc1.SetField(KS.ViewProps, new ListField([KS.Data, KS.X])); + let doc1 = Documents.TextDocument("Hello world"); let doc2 = doc1.MakeDelegate(); 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: 100, y: 400 + }); mainNodeCollection.Docs.push(doc1); mainNodeCollection.Docs.push(doc2); + mainNodeCollection.Docs.push(doc3); });
\ No newline at end of file diff --git a/src/documents/Documents.ts b/src/documents/Documents.ts new file mode 100644 index 000000000..20d4596fd --- /dev/null +++ b/src/documents/Documents.ts @@ -0,0 +1,71 @@ +import { Document } from "../fields/Document"; +import { KeyStore } from "../fields/Key"; +import { TextField } from "../fields/TextField"; +import { NumberField } from "../fields/NumberField"; +import { ListField } from "../fields/ListField"; + +interface DocumentOptions { + x?: number; + y?: number; + width?: number; + height?: number; +} + +export namespace Documents { + function setupOptions(doc: Document, options: DocumentOptions): void { + if(options.x) { + doc.SetFieldValue(KeyStore.X, options.x, NumberField); + } + if(options.y) { + doc.SetFieldValue(KeyStore.Y, options.y, NumberField); + } + if(options.width) { + doc.SetFieldValue(KeyStore.Width, options.width, NumberField); + } + if(options.height) { + doc.SetFieldValue(KeyStore.Height, options.height, NumberField); + } + } + + let textProto:Document; + function GetTextPrototype(): Document { + if(!textProto) { + textProto = new Document(); + textProto.SetField(KeyStore.X, new NumberField(0)); + textProto.SetField(KeyStore.Y, new NumberField(0)); + textProto.SetField(KeyStore.Width, new NumberField(300)); + textProto.SetField(KeyStore.Height, new NumberField(150)); + textProto.SetField(KeyStore.Layout, new TextField("<FieldTextBox doc={doc} fieldKey={DataKey} />")); + textProto.SetField(KeyStore.LayoutKeys, new ListField([KeyStore.Data])); + } + return textProto; + } + + export function TextDocument(text: string, options:DocumentOptions = {}): Document { + let doc = GetTextPrototype().MakeDelegate(); + setupOptions(doc, options); + doc.SetField(KeyStore.Data, new TextField(text)); + return doc; + } + + let imageProto:Document; + function GetImagePrototype(): Document { + if(!imageProto) { + imageProto = new Document(); + imageProto.SetField(KeyStore.X, new NumberField(0)); + imageProto.SetField(KeyStore.Y, new NumberField(0)); + imageProto.SetField(KeyStore.Width, new NumberField(300)); + imageProto.SetField(KeyStore.Height, new NumberField(300)); + imageProto.SetField(KeyStore.Layout, new TextField('<img src={Data} alt="Image not found"/>')); + imageProto.SetField(KeyStore.LayoutFields, new ListField([KeyStore.Data])); + } + return imageProto; + } + + export function ImageDocument(url: string, options:DocumentOptions = {}): Document { + let doc = GetImagePrototype().MakeDelegate(); + setupOptions(doc, options); + doc.SetField(KeyStore.Data, new TextField(url)); + return doc; + } +}
\ No newline at end of file diff --git a/src/fields/Key.ts b/src/fields/Key.ts index 42881c8a6..cd67e0a00 100644 --- a/src/fields/Key.ts +++ b/src/fields/Key.ts @@ -1,13 +1,18 @@ import { Field } from "./Field" import { Utils } from "../Utils"; +import { observable } from "mobx"; export class Key extends Field { + private name:string; + get Name():string { return this.name; } - constructor(private name:string){ + constructor(name:string){ super(Utils.GenerateDeterministicGuid(name)); + + this.name = name; } TrySetValue(value: any): boolean { @@ -32,6 +37,7 @@ export namespace KeyStore { export let Width = new Key("Width"); export let Height = new Key("Height"); export let Data = new Key("Data"); - export let View = new Key("View"); - export let ViewProps = new Key("ViewProps"); + export let Layout = new Key("Layout"); + export let LayoutKeys = new Key("LayoutKeys"); + export let LayoutFields = new Key("LayoutFields"); }
\ No newline at end of file diff --git a/src/views/freeformcanvas/FreeFormCanvas.tsx b/src/views/freeformcanvas/FreeFormCanvas.tsx index 3552ffa54..344eb2bd8 100644 --- a/src/views/freeformcanvas/FreeFormCanvas.tsx +++ b/src/views/freeformcanvas/FreeFormCanvas.tsx @@ -20,7 +20,6 @@ export class FreeFormCanvas extends React.Component<IProps> { @action onPointerDown = (e: React.PointerEvent): void => { e.stopPropagation(); - e.preventDefault(); this._isPointerDown = true; document.removeEventListener("pointermove", this.onPointerMove); document.addEventListener("pointermove", this.onPointerMove); @@ -31,21 +30,19 @@ export class FreeFormCanvas extends React.Component<IProps> { @action onPointerUp = (e: PointerEvent): void => { e.stopPropagation(); - e.preventDefault(); this._isPointerDown = false; document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); - let doc = this.props.store.Docs[0]; - let dataField = doc.GetFieldT(KeyStore.Data, TextField); - let data = dataField ? dataField.Data : ""; - this.props.store.Docs[0].SetFieldValue(KeyStore.Data, data + " hello", TextField); + // let doc = this.props.store.Docs[0]; + // let dataField = doc.GetFieldT(KeyStore.Data, TextField); + // let data = dataField ? dataField.Data : ""; + // this.props.store.Docs[0].SetFieldValue(KeyStore.Data, data + " hello", TextField); } @action onPointerMove = (e: PointerEvent): void => { e.stopPropagation(); - e.preventDefault(); if (!this._isPointerDown) { return; } @@ -56,7 +53,6 @@ export class FreeFormCanvas extends React.Component<IProps> { @action onPointerWheel = (e: React.WheelEvent): void => { e.stopPropagation(); - e.preventDefault(); let scaleAmount = 1 - (e.deltaY / 1000); this.props.store.Scale *= scaleAmount; diff --git a/src/views/nodes/DocumentView.tsx b/src/views/nodes/DocumentView.tsx index 059d6c69e..f31069aa3 100644 --- a/src/views/nodes/DocumentView.tsx +++ b/src/views/nodes/DocumentView.tsx @@ -6,10 +6,12 @@ import { NumberField } from "../../fields/NumberField"; import { TextField } from "../../fields/TextField"; import { DocumentViewModel } from "../../viewmodels/DocumentViewModel"; import { ListField } from "../../fields/ListField"; +import { FieldTextBox } from "../nodes/FieldTextBox" +import "./NodeView.scss" const JsxParser = require('react-jsx-parser').default;//TODO Why does this need to be imported like this? interface IProps { - dvm:DocumentViewModel; + dvm: DocumentViewModel; } @observer @@ -47,20 +49,30 @@ export class DocumentView extends React.Component<IProps> { @computed get layout(): string { - return this.props.dvm.Doc.GetFieldValue(KeyStore.View, TextField, String("<p>Error loading layout data</p>")); + return this.props.dvm.Doc.GetFieldValue(KeyStore.Layout, TextField, String("<p>Error loading layout data</p>")); + } + + @computed + get layoutKeys(): Key[] { + return this.props.dvm.Doc.GetFieldValue(KeyStore.LayoutKeys, ListField, new Array<Key>()); } @computed get layoutFields(): Key[] { - return this.props.dvm.Doc.GetFieldValue(KeyStore.ViewProps, ListField, new Array<Key>()); + return this.props.dvm.Doc.GetFieldValue(KeyStore.LayoutFields, ListField, new Array<Key>()); } render() { - let doc = this.props.dvm.Doc; - let bindings:any = {}; + let doc = this.props.dvm.Doc; + let bindings: any = { + doc: doc + }; + for (const key of this.layoutKeys) { + bindings[key.Name + "Key"] = key; + } for (const key of this.layoutFields) { let field = doc.GetField(key); - if(field) { + if (field) { bindings[key.Name] = field.GetValue(); } } @@ -70,7 +82,8 @@ export class DocumentView extends React.Component<IProps> { width: this.width, height: this.height }}> - <JsxParser + <JsxParser + components={{ FieldTextBox }} bindings={bindings} jsx={this.layout} /> diff --git a/src/views/nodes/FieldTextBox.tsx b/src/views/nodes/FieldTextBox.tsx new file mode 100644 index 000000000..4615940bd --- /dev/null +++ b/src/views/nodes/FieldTextBox.tsx @@ -0,0 +1,37 @@ +import { Key } from "../../fields/Key"; +import { Document } from "../../fields/Document"; +import { observer } from "mobx-react"; +import { TextField } from "../../fields/TextField"; +import React = require("react") +import { action, observable } from "mobx"; + +interface IProps { + fieldKey:Key; + doc:Document; + test:string; +} + +@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); + } + + @action + onChange(e: React.ChangeEvent<HTMLInputElement>) { + const {fieldKey, doc} = this.props; + doc.SetFieldValue(fieldKey, e.target.value, TextField); + } + + render() { + const {fieldKey, doc} = this.props; + const value = doc.GetFieldValue(fieldKey, TextField, String("")); + return (<input value={value} onChange={this.onChange} />) + } +}
\ No newline at end of file diff --git a/src/views/nodes/NodeView.scss b/src/views/nodes/NodeView.scss index 2dfdee6fa..e8964399b 100644 --- a/src/views/nodes/NodeView.scss +++ b/src/views/nodes/NodeView.scss @@ -1,9 +1,7 @@ .node { position: absolute; - background: #cdcdcd; + // background: #cdcdcd; - width: 300px; - height: 300px; overflow: hidden; |