diff options
author | Tyler Schicke <tyler_schicke@brown.edu> | 2019-01-10 23:52:54 -0500 |
---|---|---|
committer | Tyler Schicke <tyler_schicke@brown.edu> | 2019-01-10 23:52:54 -0500 |
commit | ee068ab30c43125efd2b0ab853531df9777f544f (patch) | |
tree | 9560b014b4de30c3a8f1e3d77ae70db27558fe58 /src | |
parent | 861d61970afc9e67afbafa64e8c1347a18335077 (diff) |
Started adding various controllers
Diffstat (limited to 'src')
-rw-r--r-- | src/controllers/BasicFieldController.ts | 36 | ||||
-rw-r--r-- | src/controllers/DocumentController.ts | 107 | ||||
-rw-r--r-- | src/controllers/DocumentReferenceController.ts | 36 | ||||
-rw-r--r-- | src/controllers/FieldController.ts | 45 | ||||
-rw-r--r-- | src/controllers/FieldUpdatedArgs.ts | 27 | ||||
-rw-r--r-- | src/controllers/KeyController.ts | 25 | ||||
-rw-r--r-- | src/controllers/NumberController.ts | 14 | ||||
-rw-r--r-- | src/controllers/TextController.ts | 14 | ||||
-rw-r--r-- | src/util/TypedEvent.ts | 42 | ||||
-rw-r--r-- | src/views/freeformcanvas/FreeFormCanvas.tsx | 12 |
10 files changed, 356 insertions, 2 deletions
diff --git a/src/controllers/BasicFieldController.ts b/src/controllers/BasicFieldController.ts new file mode 100644 index 000000000..ff88f8781 --- /dev/null +++ b/src/controllers/BasicFieldController.ts @@ -0,0 +1,36 @@ +import { FieldController } from "./FieldController" +import { FieldUpdatedAction } from "./FieldUpdatedArgs"; + +export abstract class BasicFieldController<T> extends FieldController { + get Data(): T { + return this.data; + } + + set Data(value: T) { + if(this.data === value) { + return; + } + this.data = value; + + this.FieldUpdated.emit({ + field: this, + action: FieldUpdatedAction.Update + }); + } + + constructor(private data: T) { + super(); + } + + TrySetValue(value: any): boolean { + if (typeof value == typeof this.data) { + this.Data = value; + return true; + } + return false; + } + + GetValue(): any { + return this.Data; + } +} diff --git a/src/controllers/DocumentController.ts b/src/controllers/DocumentController.ts new file mode 100644 index 000000000..0c53a9c43 --- /dev/null +++ b/src/controllers/DocumentController.ts @@ -0,0 +1,107 @@ +import { FieldController } from "./FieldController" +import { KeyController } from "./KeyController" +import { TypedEvent, Listener, Disposable } from "../util/TypedEvent"; +import { DocumentUpdatedArgs, FieldUpdatedAction } from "./FieldUpdatedArgs"; + +export class DocumentController extends FieldController { + private fields: { [key: string]: { key: KeyController, field: FieldController, disposer: Disposable } } = {}; + private fieldUpdateHandlers: { [key: string]: TypedEvent<DocumentUpdatedArgs> } + + GetField(key: KeyController): FieldController { + if (key.Id in this.fields) { + return this.fields[key.Id].field; + } + return null; + } + + SetField(key: KeyController, field: FieldController): void { + let oldField: FieldController = null; + if (key.Id in this.fields) { + let old = this.fields[key.Id]; + oldField = old.field; + old.disposer.dispose(); + } + + if (oldField === field) { + return; + } + + if (field === null) { + delete this.fields[key.Id]; + } else { + this.fields[key.Id] = { + key: key, + field: field, + disposer: field.FieldUpdated.on((args) => this.DocumentFieldUpdated({ + action: FieldUpdatedAction.Update, + oldValue: null, + newValue: field, + field: this, + fieldArgs: args, + key: key + })) + } + } + + let action = oldField === null ? FieldUpdatedAction.Add : + (field === null ? FieldUpdatedAction.Remove : + FieldUpdatedAction.Replace); + + this.DocumentFieldUpdated({ + field: this, + key: key, + oldValue: oldField, + newValue: field, + fieldArgs: null, + action: action + }) + } + + SetFieldValue<T extends FieldController>(key:KeyController, value:any, ctor: {new():T}) : boolean { + let field = this.GetField(key); + if(field !== null) { + return field.TrySetValue(value); + } else { + field = new ctor(); + if(field.TrySetValue(value)) { + this.SetField(key, field); + return true; + } else { + return false; + } + } + } + + private DocumentFieldUpdated(args: DocumentUpdatedArgs) { + if (args.key.Id in this.fieldUpdateHandlers) { + this.fieldUpdateHandlers[args.key.Id].emit(args); + } + this.FieldUpdated.emit(args); + } + + AddFieldUpdatedHandler(key: KeyController, listener: Listener<DocumentUpdatedArgs>): Disposable { + if (!(key.Id in this.fieldUpdateHandlers)) { + this.fieldUpdateHandlers[key.Id] = new TypedEvent<DocumentUpdatedArgs>(); + } + + return this.fieldUpdateHandlers[key.Id].on(listener); + } + + RemoveFieldUpdatedHandler(key: KeyController, listener: Listener<DocumentUpdatedArgs>) { + if (key.Id in this.fieldUpdateHandlers) { + this.fieldUpdateHandlers[key.Id].off(listener); + } + } + + TrySetValue(value: any): boolean { + throw new Error("Method not implemented."); + } + GetValue() { + throw new Error("Method not implemented."); + } + Copy(): FieldController { + throw new Error("Method not implemented."); + } + + +}
\ No newline at end of file diff --git a/src/controllers/DocumentReferenceController.ts b/src/controllers/DocumentReferenceController.ts new file mode 100644 index 000000000..9d5bb7af2 --- /dev/null +++ b/src/controllers/DocumentReferenceController.ts @@ -0,0 +1,36 @@ +import { FieldController } from "./FieldController"; +import { DocumentController } from "./DocumentController"; +import { KeyController } from "./KeyController"; +import { DocumentUpdatedArgs } from "./FieldUpdatedArgs"; + +export class DocumentReferenceController extends FieldController { + get Key(): KeyController{ + return this.key; + } + + get Document(): DocumentController { + return this.document; + } + + constructor(private document: DocumentController, private key: KeyController) { + super(); + + document.AddFieldUpdatedHandler(key, this.DocFieldUpdated); + } + + private DocFieldUpdated(args: DocumentUpdatedArgs):void{ + this.FieldUpdated.emit(args.fieldArgs); + } + + TrySetValue(value: any): boolean { + throw new Error("Method not implemented."); + } + GetValue() { + throw new Error("Method not implemented."); + } + Copy(): FieldController { + throw new Error("Method not implemented."); + } + + +}
\ No newline at end of file diff --git a/src/controllers/FieldController.ts b/src/controllers/FieldController.ts new file mode 100644 index 000000000..19205014a --- /dev/null +++ b/src/controllers/FieldController.ts @@ -0,0 +1,45 @@ +import { TypedEvent } from "../util/TypedEvent"; +import { FieldUpdatedArgs } from "./FieldUpdatedArgs"; +import { DocumentReferenceController } from "./DocumentReferenceController"; + +export abstract class FieldController { + Id: string; + + FieldUpdated: TypedEvent<FieldUpdatedArgs>; + + protected DereferenceImpl(): FieldController { + return this; + } + protected DereferenceToRootImpl(): FieldController { + let field = this; + while(field instanceof DocumentReferenceController) { + field = field.Dereference(); + } + return field; + } + + Dereference<T extends FieldController = FieldController>(ctor?: { new(): T }): T { + let field = this.DereferenceImpl(); + if (ctor && field instanceof ctor) { + return field; + } else { + return null; + } + } + + DereferenceToRoot<T extends FieldController = FieldController>(ctor?: { new(): T }): T { + let field = this.DereferenceToRootImpl(); + if (ctor && field instanceof ctor) { + return field; + } else { + return null; + } + } + + abstract TrySetValue(value: any): boolean; + + abstract GetValue(): any; + + abstract Copy(): FieldController; + +}
\ No newline at end of file diff --git a/src/controllers/FieldUpdatedArgs.ts b/src/controllers/FieldUpdatedArgs.ts new file mode 100644 index 000000000..786a44aa4 --- /dev/null +++ b/src/controllers/FieldUpdatedArgs.ts @@ -0,0 +1,27 @@ +import { FieldController } from "./FieldController"; +import { DocumentController } from "./DocumentController"; +import { KeyController } from "./KeyController"; + +export enum FieldUpdatedAction { + Add, + Remove, + Replace, + Update +} + +export interface FieldUpdatedArgs { + field: FieldController; + action: FieldUpdatedAction; +} + +export interface DocumentUpdatedArgs { + field: DocumentController; + key: KeyController; + + oldValue: FieldController; + newValue: FieldController; + + fieldArgs: FieldUpdatedArgs; + + action: FieldUpdatedAction; +} diff --git a/src/controllers/KeyController.ts b/src/controllers/KeyController.ts new file mode 100644 index 000000000..96e41eded --- /dev/null +++ b/src/controllers/KeyController.ts @@ -0,0 +1,25 @@ +import { FieldController } from "./FieldController" + +export class KeyController extends FieldController { + get Name():string { + return this.name; + } + + constructor(private name:string){ + super(); + } + + TrySetValue(value: any): boolean { + throw new Error("Method not implemented."); + } + + GetValue() { + return this.Name; + } + + Copy(): FieldController { + return this; + } + + +} diff --git a/src/controllers/NumberController.ts b/src/controllers/NumberController.ts new file mode 100644 index 000000000..aeedf025b --- /dev/null +++ b/src/controllers/NumberController.ts @@ -0,0 +1,14 @@ +import { BasicFieldController } from "./BasicFieldController" +import { FieldUpdatedAction } from "./FieldUpdatedArgs"; + +export class NumberController extends BasicFieldController<number> { + constructor(data: number = 0) { + super(data); + } + + Copy() { + return new NumberController(this.Data); + } + + +}
\ No newline at end of file diff --git a/src/controllers/TextController.ts b/src/controllers/TextController.ts new file mode 100644 index 000000000..5d4b43170 --- /dev/null +++ b/src/controllers/TextController.ts @@ -0,0 +1,14 @@ +import { BasicFieldController } from "./BasicFieldController" +import { FieldUpdatedAction } from "./FieldUpdatedArgs"; + +export class TextController extends BasicFieldController<string> { + constructor(data: string = "") { + super(data); + } + + Copy() { + return new TextController(this.Data); + } + + +} diff --git a/src/util/TypedEvent.ts b/src/util/TypedEvent.ts new file mode 100644 index 000000000..0714a7f5c --- /dev/null +++ b/src/util/TypedEvent.ts @@ -0,0 +1,42 @@ +export interface Listener<T> { + (event: T): any; +} + +export interface Disposable { + dispose(): void; +} + +/** passes through events as they happen. You will not get events from before you start listening */ +export class TypedEvent<T> { + private listeners: Listener<T>[] = []; + private listenersOncer: Listener<T>[] = []; + + on = (listener: Listener<T>): Disposable => { + this.listeners.push(listener); + return { + dispose: () => this.off(listener) + }; + } + + once = (listener: Listener<T>): void => { + this.listenersOncer.push(listener); + } + + off = (listener: Listener<T>) => { + var callbackIndex = this.listeners.indexOf(listener); + if (callbackIndex > -1) this.listeners.splice(callbackIndex, 1); + } + + emit = (event: T) => { + /** Update any general listeners */ + this.listeners.forEach((listener) => listener(event)); + + /** Clear the `once` queue */ + this.listenersOncer.forEach((listener) => listener(event)); + this.listenersOncer = []; + } + + pipe = (te: TypedEvent<T>): Disposable => { + return this.on((e) => te.emit(e)); + } +}
\ No newline at end of file diff --git a/src/views/freeformcanvas/FreeFormCanvas.tsx b/src/views/freeformcanvas/FreeFormCanvas.tsx index f02f677a3..d25341cbb 100644 --- a/src/views/freeformcanvas/FreeFormCanvas.tsx +++ b/src/views/freeformcanvas/FreeFormCanvas.tsx @@ -41,11 +41,19 @@ export class FreeFormCanvas extends React.Component<IProps> { this.props.store.Y += e.movementY; } + onPointerWheel = (e: React.WheelEvent): void => { + e.stopPropagation(); + e.preventDefault(); + + let scaleAmount = 1 - (e.deltaY / 1000); + this.props.store.Scale *= scaleAmount; + } + render() { let store = this.props.store; return ( - <div className="freeformcanvas-container" onPointerDown={this.onPointerDown}> - <div className="freeformcanvas" style={{ transform: store.Transform }}> + <div className="freeformcanvas-container" onPointerDown={this.onPointerDown} onWheel={this.onPointerWheel}> + <div className="freeformcanvas" style={{ transform: store.Transform, transformOrigin: '50% 50%' }}> <NodeContainer store={store} /> </div> </div> |