diff options
Diffstat (limited to 'src/fields/Document.ts')
-rw-r--r-- | src/fields/Document.ts | 132 |
1 files changed, 106 insertions, 26 deletions
diff --git a/src/fields/Document.ts b/src/fields/Document.ts index 6f9752a8e..0d7d357a0 100644 --- a/src/fields/Document.ts +++ b/src/fields/Document.ts @@ -1,15 +1,38 @@ -import { Field, Cast, Opt, FieldWaiting, FIELD_ID, FieldValue } from "./Field" -import { Key, KeyStore } from "./Key" +import { Key } from "./Key" +import { KeyStore } from "./KeyStore"; +import { Field, Cast, FieldWaiting, FieldValue, FieldId } from "./Field" import { NumberField } from "./NumberField"; -import { ObservableMap, computed, action, observable } from "mobx"; +import { ObservableMap, computed, action } from "mobx"; import { TextField } from "./TextField"; import { ListField } from "./ListField"; -import { findDOMNode } from "react-dom"; import { Server } from "../client/Server"; +import { Types } from "../server/Message"; +import { UndoManager } from "../client/util/UndoManager"; export class Document extends Field { - public fields: ObservableMap<Key, Opt<Field>> = new ObservableMap(); - public _proxies: ObservableMap<Key, FIELD_ID> = new ObservableMap(); + public fields: ObservableMap<string, { key: Key, field: Field }> = new ObservableMap(); + public _proxies: ObservableMap<string, FieldId> = new ObservableMap(); + + constructor(id?: string, save: boolean = true) { + super(id) + + if (save) { + var title = (this._proxies.has(KeyStore.Title.Id) ? "???" : this.Title) + "(" + this.Id + ")"; + console.log("Save " + title); + Server.UpdateField(this) + } + } + + UpdateFromServer(data: [string, string][]) { + for (const key in data) { + const element = data[key]; + this._proxies.set(element[0], element[1]); + } + } + + public Width = () => { return this.GetNumber(KeyStore.Width, 0) } + public Height = () => { return this.GetNumber(KeyStore.Height, 0) } + public Scale = () => { return this.GetNumber(KeyStore.Scale, 1) } @computed public get Title() { @@ -19,33 +42,67 @@ export class Document extends Field { Get(key: Key, ignoreProto: boolean = false): FieldValue<Field> { let field: FieldValue<Field>; if (ignoreProto) { - if (this.fields.has(key)) { - field = this.fields.get(key); - } else if (this._proxies.has(key)) { - field = Server.GetDocumentField(this, key); + if (this.fields.has(key.Id)) { + field = this.fields.get(key.Id)!.field; + } else if (this._proxies.has(key.Id)) { + Server.GetDocumentField(this, key); + /* + The field might have been instantly filled from the cache + Maybe we want to just switch back to returning the value + from Server.GetDocumentField if it's in the cache + */ + if (this.fields.has(key.Id)) { + field = this.fields.get(key.Id)!.field; + } else { + field = FieldWaiting; + } } } else { let doc: FieldValue<Document> = this; while (doc && doc != FieldWaiting && field != FieldWaiting) { - if (!doc.fields.has(key)) { - if (doc._proxies.has(key)) { - field = Server.GetDocumentField(doc, key); + let curField = doc.fields.get(key.Id); + let curProxy = doc._proxies.get(key.Id); + if (!curField || (curProxy && curField.field.Id !== curProxy)) { + if (curProxy) { + Server.GetDocumentField(doc, key); + /* + The field might have been instantly filled from the cache + Maybe we want to just switch back to returning the value + from Server.GetDocumentField if it's in the cache + */ + if (this.fields.has(key.Id)) { + field = this.fields.get(key.Id)!.field; + } else { + field = FieldWaiting; + } break; } - if ((doc.fields.has(KeyStore.Prototype) || doc._proxies.has(KeyStore.Prototype))) { + if ((doc.fields.has(KeyStore.Prototype.Id) || doc._proxies.has(KeyStore.Prototype.Id))) { doc = doc.GetPrototype(); - } else + } else { break; + } } else { - field = doc.fields.get(key); + field = curField.field; break; } } + if (doc == FieldWaiting) + field = FieldWaiting; } return field; } + GetAsync(key: Key, callback: (field: Field) => void): boolean { + //This currently doesn't deal with prototypes + if (this._proxies.has(key.Id)) { + Server.GetDocumentField(this, key, callback); + return true; + } + return false; + } + GetT<T extends Field = Field>(key: Key, ctor: { new(...args: any[]): T }, ignoreProto: boolean = false): FieldValue<T> { var getfield = this.Get(key, ignoreProto); if (getfield != FieldWaiting) { @@ -84,29 +141,37 @@ export class Document extends Field { @action Set(key: Key, field: Field | undefined): void { + let old = this.fields.get(key.Id); + let oldField = old ? old.field : undefined; if (field) { - this.fields.set(key, field); - Server.AddDocumentField(this, key, field); + this.fields.set(key.Id, { key, field }); + this._proxies.set(key.Id, field.Id) + // Server.AddDocumentField(this, key, field); } else { - this.fields.delete(key); - Server.DeleteDocumentField(this, key); + this.fields.delete(key.Id); + this._proxies.delete(key.Id) + // Server.DeleteDocumentField(this, key); + } + if (oldField || field) { + UndoManager.AddEvent({ + undo: () => this.Set(key, oldField), + redo: () => this.Set(key, field) + }) } + Server.UpdateField(this); } @action SetData<T, U extends Field & { Data: T }>(key: Key, value: T, ctor: { new(): U }, replaceWrongType = true) { let field = this.Get(key, true); - //if (field != WAITING) { // do we want to wait for the field to come back from the server to set it, or do we overwrite? if (field instanceof ctor) { field.Data = value; - Server.SetFieldValue(field, value); } else if (!field || replaceWrongType) { let newField = new ctor(); newField.Data = value; this.Set(key, newField); } - //} } @action @@ -133,8 +198,8 @@ export class Document extends Field { return protos; } - MakeDelegate(): Document { - let delegate = new Document(); + MakeDelegate(id?: string): Document { + let delegate = new Document(id); delegate.Set(KeyStore.Prototype, this); @@ -149,11 +214,26 @@ export class Document extends Field { throw new Error("Method not implemented."); } GetValue() { - throw new Error("Method not implemented."); + var title = (this._proxies.has(KeyStore.Title.Id) ? "???" : this.Title) + "(" + this.Id + ")"; + return title; + //throw new Error("Method not implemented."); } Copy(): Field { throw new Error("Method not implemented."); } + ToJson(): { type: Types, data: [string, string][], _id: string } { + let fields: [string, string][] = [] + this._proxies.forEach((field, key) => { + if (field) { + fields.push([key, field as string]) + } + }); + return { + type: Types.Document, + data: fields, + _id: this.Id + } + } }
\ No newline at end of file |