aboutsummaryrefslogtreecommitdiff
path: root/src/fields/ListField.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/fields/ListField.ts')
-rw-r--r--src/fields/ListField.ts97
1 files changed, 94 insertions, 3 deletions
diff --git a/src/fields/ListField.ts b/src/fields/ListField.ts
index 8607ebe43..700600804 100644
--- a/src/fields/ListField.ts
+++ b/src/fields/ListField.ts
@@ -1,12 +1,103 @@
-import { Field } from "./Field";
+import { action, IArrayChange, IArraySplice, IObservableArray, observe, observable, Lambda } from "mobx";
+import { Server } from "../client/Server";
+import { UndoManager } from "../client/util/UndoManager";
+import { Types } from "../server/Message";
import { BasicField } from "./BasicField";
+import { Field, FieldId } from "./Field";
export class ListField<T extends Field> extends BasicField<T[]> {
- constructor(data: T[] = []) {
- super(data.slice());
+ private _proxies: string[] = []
+ constructor(data: T[] = [], id?: FieldId, save: boolean = true) {
+ super(data, save, id);
+ this.updateProxies();
+ if (save) {
+ Server.UpdateField(this);
+ }
+ this.observeList();
+ }
+
+ private observeDisposer: Lambda | undefined;
+ private observeList(): void {
+ this.observeDisposer = observe(this.Data as IObservableArray<T>, (change: IArrayChange<T> | IArraySplice<T>) => {
+ this.updateProxies()
+ if (change.type == "splice") {
+ UndoManager.AddEvent({
+ undo: () => this.Data.splice(change.index, change.addedCount, ...change.removed),
+ redo: () => this.Data.splice(change.index, change.removedCount, ...change.added)
+ })
+ } else {
+ UndoManager.AddEvent({
+ undo: () => this.Data[change.index] = change.oldValue,
+ redo: () => this.Data[change.index] = change.newValue
+ })
+ }
+ Server.UpdateField(this);
+ });
+ }
+
+ protected setData(value: T[]) {
+ if (this.observeDisposer) {
+ this.observeDisposer()
+ }
+ this.data = observable(value);
+ this.observeList();
+ }
+
+ private updateProxies() {
+ this._proxies = this.Data.map(field => field.Id);
+ }
+
+ UpdateFromServer(fields: string[]) {
+ this._proxies = fields;
+ }
+ private arraysEqual(a: any[], b: any[]) {
+ if (a === b) return true;
+ if (a == null || b == null) return false;
+ if (a.length != b.length) return false;
+
+ // If you don't care about the order of the elements inside
+ // the array, you should sort both arrays here.
+ // Please note that calling sort on an array will modify that array.
+ // you might want to clone your array first.
+
+ for (var i = 0; i < a.length; ++i) {
+ if (a[i] !== b[i]) return false;
+ }
+ return true;
+ }
+
+ init(callback: (field: Field) => any) {
+ Server.GetFields(this._proxies, action((fields: { [index: string]: Field }) => {
+ if (!this.arraysEqual(this._proxies, this.Data.map(field => field.Id))) {
+ this.data = this._proxies.map(id => fields[id] as T)
+ observe(this.Data, () => {
+ this.updateProxies()
+ Server.UpdateField(this);
+ })
+ }
+ callback(this);
+ }))
+ }
+
+ ToScriptString(): string {
+ return "new ListField([" + this.Data.map(field => field.ToScriptString()).join(", ") + "])";
}
Copy(): Field {
return new ListField<T>(this.Data);
}
+
+ ToJson(): { type: Types, data: string[], _id: string } {
+ return {
+ type: Types.List,
+ data: this._proxies,
+ _id: this.Id
+ }
+ }
+
+ static FromJson(id: string, ids: string[]): ListField<Field> {
+ let list = new ListField([], id, false);
+ list._proxies = ids;
+ return list
+ }
} \ No newline at end of file