1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
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[]> {
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
}
}
|