aboutsummaryrefslogtreecommitdiff
path: root/src/fields
diff options
context:
space:
mode:
Diffstat (limited to 'src/fields')
-rw-r--r--src/fields/BooleanField.ts25
-rw-r--r--src/fields/Document.ts221
-rw-r--r--src/fields/KeyStore.ts87
-rw-r--r--src/fields/ListField.ts5
4 files changed, 227 insertions, 111 deletions
diff --git a/src/fields/BooleanField.ts b/src/fields/BooleanField.ts
new file mode 100644
index 000000000..7378b30a1
--- /dev/null
+++ b/src/fields/BooleanField.ts
@@ -0,0 +1,25 @@
+import { BasicField } from "./BasicField";
+import { FieldId } from "./Field";
+import { Types } from "../server/Message";
+
+export class BooleanField extends BasicField<boolean> {
+ constructor(data: boolean = false as boolean, id?: FieldId, save: boolean = true as boolean) {
+ super(data, save, id);
+ }
+
+ ToScriptString(): string {
+ return `new BooleanField("${this.Data}")`;
+ }
+
+ Copy() {
+ return new BooleanField(this.Data);
+ }
+
+ ToJson(): { type: Types; data: boolean; _id: string } {
+ return {
+ type: Types.Minimized,
+ data: this.Data,
+ _id: this.Id
+ };
+ }
+}
diff --git a/src/fields/Document.ts b/src/fields/Document.ts
index b6439364a..92d03d765 100644
--- a/src/fields/Document.ts
+++ b/src/fields/Document.ts
@@ -1,6 +1,6 @@
-import { Key } from "./Key"
+import { Key } from "./Key";
import { KeyStore } from "./KeyStore";
-import { Field, Cast, FieldWaiting, FieldValue, FieldId, Opt } from "./Field"
+import { Field, Cast, FieldWaiting, FieldValue, FieldId, Opt } from "./Field";
import { NumberField } from "./NumberField";
import { ObservableMap, computed, action, runInAction } from "mobx";
import { TextField } from "./TextField";
@@ -9,17 +9,21 @@ import { Server } from "../client/Server";
import { Types } from "../server/Message";
import { UndoManager } from "../client/util/UndoManager";
import { HtmlField } from "./HtmlField";
+import { BooleanField } from "./BooleanField";
export class Document extends Field {
//TODO tfs: We should probably store FieldWaiting in fields when we request it from the server so that we don't set up multiple server gets for the same document and field
- public fields: ObservableMap<string, { key: Key, field: Field }> = 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)
+ super(id);
if (save) {
- Server.UpdateField(this)
+ Server.UpdateField(this);
}
}
@@ -30,13 +34,35 @@ export class Document extends Field {
}
}
- public Width = () => { return this.GetNumber(KeyStore.Width, 0) }
- public Height = () => { return this.GetNumber(KeyStore.Height, this.GetNumber(KeyStore.NativeWidth, 0) ? this.GetNumber(KeyStore.NativeHeight, 0) / this.GetNumber(KeyStore.NativeWidth, 0) * this.GetNumber(KeyStore.Width, 0) : 0) }
- public Scale = () => { return this.GetNumber(KeyStore.Scale, 1) }
+ public Width = () => {
+ return this.GetNumber(KeyStore.Width, 0);
+ };
+ public Height = () => {
+ return this.GetNumber(
+ KeyStore.Height,
+ this.GetNumber(KeyStore.NativeWidth, 0)
+ ? (this.GetNumber(KeyStore.NativeHeight, 0) /
+ this.GetNumber(KeyStore.NativeWidth, 0)) *
+ this.GetNumber(KeyStore.Width, 0)
+ : 0
+ );
+ };
+ public Scale = () => {
+ return this.GetNumber(KeyStore.Scale, 1);
+ };
@computed
- public get Title() {
- return this.GetText(KeyStore.Title, "<untitled>");
+ public get Title(): string {
+ let title = this.Get(KeyStore.Title, true);
+ if (title)
+ if (title != FieldWaiting && title instanceof TextField)
+ return title.Data;
+ else return "-waiting-";
+ let parTitle = this.GetT(KeyStore.Title, TextField);
+ if (parTitle)
+ if (parTitle != FieldWaiting) return parTitle.Data + ".alias";
+ else return "-waiting-.alias";
+ return "-untitled-";
}
@computed
@@ -47,7 +73,7 @@ export class Document extends Field {
/**
* Get the field in the document associated with the given key. If the
* associated field has not yet been filled in from the server, a request
- * to the server will automatically be sent, the value will be filled in
+ * to the server will automatically be sent, the value will be filled in
* when the request is completed, and {@link Field.ts#FieldWaiting} will be returned.
* @param key - The key of the value to get
* @param ignoreProto - If true, ignore any prototype this document
@@ -55,7 +81,7 @@ export class Document extends Field {
* If false (default), search up the prototype chain, starting at this document,
* for a document that has a field associated with the given key, and return the first
* one found.
- *
+ *
* @returns If the document does not have a field associated with the given key, returns `undefined`.
* If the document does have an associated field, but the field has not been fetched from the server, returns {@link Field.ts#FieldWaiting}.
* If the document does have an associated field, and the field has not been fetched from the server, returns the associated field.
@@ -68,10 +94,10 @@ export class Document extends 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
- */
+ 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 {
@@ -87,10 +113,10 @@ export class Document extends Field {
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
- */
+ 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 {
@@ -98,7 +124,10 @@ export class Document extends Field {
}
break;
}
- if ((doc.fields.has(KeyStore.Prototype.Id) || doc._proxies.has(KeyStore.Prototype.Id))) {
+ if (
+ doc.fields.has(KeyStore.Prototype.Id) ||
+ doc._proxies.has(KeyStore.Prototype.Id)
+ ) {
doc = doc.GetPrototype();
} else {
break;
@@ -108,8 +137,7 @@ export class Document extends Field {
break;
}
}
- if (doc == FieldWaiting)
- field = FieldWaiting;
+ if (doc == FieldWaiting) field = FieldWaiting;
}
return field;
@@ -124,22 +152,47 @@ export class Document extends Field {
* Note: The callback will not be called if there is no associated field.
* @returns `true` if the field exists on the document and `callback` will be called, and `false` otherwise
*/
- GetAsync(key: Key, callback: (field: Field) => void): boolean {
+ GetAsync(key: Key, callback: (field: Opt<Field>) => void): void {
//TODO: This currently doesn't deal with prototypes
let field = this.fields.get(key.Id);
if (field && field.field) {
callback(field.field);
} else if (this._proxies.has(key.Id)) {
Server.GetDocumentField(this, key, callback);
- return true;
+ } else if (this._proxies.has(KeyStore.Prototype.Id)) {
+ this.GetTAsync(KeyStore.Prototype, Document, proto => {
+ if (proto) {
+ proto.GetAsync(key, callback);
+ } else {
+ callback(undefined);
+ }
+ });
+ } else {
+ callback(undefined);
}
- return false;
}
- GetTAsync<T extends Field>(key: Key, ctor: { new(): T }, callback: (field: Opt<T>) => void): boolean {
- return this.GetAsync(key, (field) => {
- callback(Cast(field, ctor));
- })
+ GetTAsync<T extends Field>(key: Key, ctor: { new(): T }): Promise<Opt<T>>;
+ GetTAsync<T extends Field>(
+ key: Key,
+ ctor: { new(): T },
+ callback: (field: Opt<T>) => void
+ ): void;
+ GetTAsync<T extends Field>(
+ key: Key,
+ ctor: { new(): T },
+ callback?: (field: Opt<T>) => void
+ ): Promise<Opt<T>> | void {
+ let fn = (cb: (field: Opt<T>) => void) => {
+ return this.GetAsync(key, field => {
+ cb(Cast(field, ctor));
+ });
+ };
+ if (callback) {
+ fn(callback);
+ } else {
+ return new Promise(res => fn(res));
+ }
}
/**
@@ -148,10 +201,14 @@ export class Document extends Field {
* or the field associated with the given key is not of the given type.
* @param ctor - Constructor of the field type to get. E.g., TextField, ImageField, etc.
*/
- GetOrCreateAsync<T extends Field>(key: Key, ctor: { new(): T }, callback: (field: T) => void): void {
+ GetOrCreateAsync<T extends Field>(
+ key: Key,
+ ctor: { new(): T },
+ callback: (field: T) => void
+ ): void {
//This currently doesn't deal with prototypes
if (this._proxies.has(key.Id)) {
- Server.GetDocumentField(this, key, (field) => {
+ Server.GetDocumentField(this, key, field => {
if (field && field instanceof ctor) {
callback(field);
} else {
@@ -174,7 +231,11 @@ export class Document extends Field {
* @returns Same as {@link Document#Get}, except will return `undefined`
* if there is an associated field but it is of the wrong type.
*/
- GetT<T extends Field = Field>(key: Key, ctor: { new(...args: any[]): T }, ignoreProto: boolean = false): FieldValue<T> {
+ 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) {
return Cast(getfield, ctor);
@@ -182,7 +243,11 @@ export class Document extends Field {
return FieldWaiting;
}
- GetOrCreate<T extends Field>(key: Key, ctor: { new(): T }, ignoreProto: boolean = false): T {
+ GetOrCreate<T extends Field>(
+ key: Key,
+ ctor: { new(): T },
+ ignoreProto: boolean = false
+ ): T {
const field = this.GetT(key, ctor, ignoreProto);
if (field && field != FieldWaiting) {
return field;
@@ -192,9 +257,13 @@ export class Document extends Field {
return newField;
}
- GetData<T, U extends Field & { Data: T }>(key: Key, ctor: { new(): U }, defaultVal: T): T {
+ GetData<T, U extends Field & { Data: T }>(
+ key: Key,
+ ctor: { new(): U },
+ defaultVal: T
+ ): T {
let val = this.Get(key);
- let vval = (val && val instanceof ctor) ? val.Data : defaultVal;
+ let vval = val && val instanceof ctor ? val.Data : defaultVal;
return vval;
}
@@ -202,6 +271,10 @@ export class Document extends Field {
return this.GetData(key, HtmlField, defaultVal);
}
+ GetBoolean(key: Key, defaultVal: boolean): boolean {
+ return this.GetData(key, BooleanField, defaultVal);
+ }
+
GetNumber(key: Key, defaultVal: number): number {
return this.GetData(key, NumberField, defaultVal);
}
@@ -211,14 +284,7 @@ export class Document extends Field {
}
GetList<T extends Field>(key: Key, defaultVal: T[]): T[] {
- return this.GetData<T[], ListField<T>>(key, ListField, defaultVal)
- }
-
- @action
- SetOnPrototype(key: Key, field: Field | undefined): void {
- this.GetAsync(KeyStore.Prototype, (f: Field) => {
- (f as Document).Set(key, field)
- })
+ return this.GetData<T[], ListField<T>>(key, ListField, defaultVal);
}
@action
@@ -226,16 +292,15 @@ export class Document extends Field {
let old = this.fields.get(key.Id);
let oldField = old ? old.field : undefined;
if (setOnPrototype) {
- this.SetOnPrototype(key, field)
- }
- else {
+ this.SetOnPrototype(key, field);
+ } else {
if (field) {
this.fields.set(key.Id, { key, field });
- this._proxies.set(key.Id, field.Id)
+ this._proxies.set(key.Id, field.Id);
// Server.AddDocumentField(this, key, field);
} else {
this.fields.delete(key.Id);
- this._proxies.delete(key.Id)
+ this._proxies.delete(key.Id);
// Server.DeleteDocumentField(this, key);
}
Server.UpdateField(this);
@@ -244,26 +309,42 @@ export class Document extends Field {
UndoManager.AddEvent({
undo: () => this.Set(key, oldField, setOnPrototype),
redo: () => this.Set(key, field, setOnPrototype)
- })
+ });
}
}
@action
- SetDataOnPrototype<T, U extends Field & { Data: T }>(key: Key, value: T, ctor: { new(): U }, replaceWrongType = true) {
- this.GetAsync(KeyStore.Prototype, (f: Field) => {
- (f as Document).SetData(key, value, ctor)
- })
+ SetOnPrototype(key: Key, field: Field | undefined): void {
+ this.GetTAsync(KeyStore.Prototype, Document, (f: Opt<Document>) => {
+ f && f.Set(key, field);
+ });
}
@action
- SetData<T, U extends Field & { Data: T }>(key: Key, value: T, ctor: { new(): U }, replaceWrongType = true) {
+ SetDataOnPrototype<T, U extends Field & { Data: T }>(
+ key: Key,
+ value: T,
+ ctor: { new(): U },
+ replaceWrongType = true
+ ) {
+ this.GetTAsync(KeyStore.Prototype, Document, (f: Opt<Document>) => {
+ f && f.SetData(key, value, ctor);
+ });
+ }
+ @action
+ SetData<T, U extends Field & { Data: T }>(
+ key: Key,
+ value: T,
+ ctor: { new(data: T): U },
+ replaceWrongType = true
+ ) {
let field = this.Get(key, true);
if (field instanceof ctor) {
field.Data = value;
} else if (!field || replaceWrongType) {
- let newField = new ctor();
- newField.Data = value;
+ let newField = new ctor(value);
+ // newField.Data = value;
this.Set(key, newField);
}
}
@@ -293,12 +374,12 @@ export class Document extends Field {
}
CreateAlias(id?: string): Document {
- let alias = new Document(id)
- this.GetAsync(KeyStore.Prototype, (f: Field) => {
- alias.Set(KeyStore.Prototype, f)
- })
+ let alias = new Document(id);
+ this.GetTAsync(KeyStore.Prototype, Document, (f: Opt<Document>) => {
+ f && alias.Set(KeyStore.Prototype, f);
+ });
- return alias
+ return alias;
}
MakeDelegate(id?: string): Document {
@@ -318,7 +399,11 @@ export class Document extends Field {
}
GetValue() {
return this.Title;
- var title = (this._proxies.has(KeyStore.Title.Id) ? "???" : this.Title) + "(" + this.Id + ")";
+ var title =
+ (this._proxies.has(KeyStore.Title.Id) ? "???" : this.Title) +
+ "(" +
+ this.Id +
+ ")";
return title;
//throw new Error("Method not implemented.");
}
@@ -326,11 +411,11 @@ export class Document extends Field {
throw new Error("Method not implemented.");
}
- ToJson(): { type: Types, data: [string, string][], _id: string } {
- let fields: [string, string][] = []
+ 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])
+ fields.push([key, field as string]);
}
});
@@ -338,6 +423,6 @@ export class Document extends Field {
type: Types.Document,
data: fields,
_id: this.Id
- }
+ };
}
-} \ No newline at end of file
+}
diff --git a/src/fields/KeyStore.ts b/src/fields/KeyStore.ts
index 319702cc4..6ed3b1604 100644
--- a/src/fields/KeyStore.ts
+++ b/src/fields/KeyStore.ts
@@ -1,45 +1,50 @@
import { Key } from "./Key";
+import { KeyTransfer } from "../server/Message";
export namespace KeyStore {
- export const Prototype = new Key("Prototype");
- export const X = new Key("X");
- export const Y = new Key("Y");
- export const Page = new Key("Page");
- export const Title = new Key("Title");
- export const Author = new Key("Author");
- export const PanX = new Key("PanX");
- export const PanY = new Key("PanY");
- export const Scale = new Key("Scale");
- export const NativeWidth = new Key("NativeWidth");
- export const NativeHeight = new Key("NativeHeight");
- export const Width = new Key("Width");
- export const Height = new Key("Height");
- export const ZIndex = new Key("ZIndex");
- export const Data = new Key("Data");
- export const Annotations = new Key("Annotations");
- export const ViewType = new Key("ViewType");
- export const Layout = new Key("Layout");
- export const BackgroundColor = new Key("BackgroundColor");
- export const BackgroundLayout = new Key("BackgroundLayout");
- export const OverlayLayout = new Key("OverlayLayout");
- export const LayoutKeys = new Key("LayoutKeys");
- export const LayoutFields = new Key("LayoutFields");
- export const ColumnsKey = new Key("SchemaColumns");
- export const SchemaSplitPercentage = new Key("SchemaSplitPercentage");
- export const Caption = new Key("Caption");
- export const ActiveFrame = new Key("ActiveFrame");
- export const ActiveDB = new Key("ActiveDB");
- export const DocumentText = new Key("DocumentText");
- export const LinkedToDocs = new Key("LinkedToDocs");
- export const LinkedFromDocs = new Key("LinkedFromDocs");
- export const LinkDescription = new Key("LinkDescription");
- export const LinkTags = new Key("LinkTag");
- export const Thumbnail = new Key("Thumbnail");
- export const CurPage = new Key("CurPage");
- export const NumPages = new Key("NumPages");
- export const Ink = new Key("Ink");
- export const Cursors = new Key("Cursors");
- export const OptionalRightCollection = new Key("OptionalRightCollection");
- export const Archives = new Key("Archives");
- export const Updated = new Key("Updated");
+ export const Prototype = new Key("Prototype");
+ export const X = new Key("X");
+ export const Y = new Key("Y");
+ export const Page = new Key("Page");
+ export const Title = new Key("Title");
+ export const Author = new Key("Author");
+ export const PanX = new Key("PanX");
+ export const PanY = new Key("PanY");
+ export const Scale = new Key("Scale");
+ export const NativeWidth = new Key("NativeWidth");
+ export const NativeHeight = new Key("NativeHeight");
+ export const Width = new Key("Width");
+ export const Height = new Key("Height");
+ export const ZIndex = new Key("ZIndex");
+ export const Data = new Key("Data");
+ export const Annotations = new Key("Annotations");
+ export const ViewType = new Key("ViewType");
+ export const Layout = new Key("Layout");
+ export const BackgroundColor = new Key("BackgroundColor");
+ export const BackgroundLayout = new Key("BackgroundLayout");
+ export const OverlayLayout = new Key("OverlayLayout");
+ export const LayoutKeys = new Key("LayoutKeys");
+ export const LayoutFields = new Key("LayoutFields");
+ export const ColumnsKey = new Key("SchemaColumns");
+ export const SchemaSplitPercentage = new Key("SchemaSplitPercentage");
+ export const Caption = new Key("Caption");
+ export const ActiveWorkspace = new Key("ActiveWorkspace");
+ export const DocumentText = new Key("DocumentText");
+ export const BrushingDocs = new Key("BrushingDocs");
+ export const LinkedToDocs = new Key("LinkedToDocs");
+ export const LinkedFromDocs = new Key("LinkedFromDocs");
+ export const LinkDescription = new Key("LinkDescription");
+ export const LinkTags = new Key("LinkTag");
+ export const Thumbnail = new Key("Thumbnail");
+ export const ThumbnailPage = new Key("ThumbnailPage");
+ export const CurPage = new Key("CurPage");
+ export const AnnotationOn = new Key("AnnotationOn");
+ export const NumPages = new Key("NumPages");
+ export const Ink = new Key("Ink");
+ export const Cursors = new Key("Cursors");
+ export const OptionalRightCollection = new Key("OptionalRightCollection");
+ export const Archives = new Key("Archives");
+ export const Updated = new Key("Updated");
+ export const Workspaces = new Key("Workspaces");
+ export const Minimized = new Key("Minimized");
}
diff --git a/src/fields/ListField.ts b/src/fields/ListField.ts
index 4527ee548..c4008bd12 100644
--- a/src/fields/ListField.ts
+++ b/src/fields/ListField.ts
@@ -4,6 +4,7 @@ import { UndoManager } from "../client/util/UndoManager";
import { Types } from "../server/Message";
import { BasicField } from "./BasicField";
import { Field, FieldId } from "./Field";
+import { FieldMap } from "../client/SocketStub";
export class ListField<T extends Field> extends BasicField<T[]> {
private _proxies: string[] = []
@@ -71,7 +72,7 @@ export class ListField<T extends Field> extends BasicField<T[]> {
}
init(callback: (field: Field) => any) {
- Server.GetFields(this._proxies, action((fields: { [index: string]: Field }) => {
+ Server.GetFields(this._proxies, action((fields: FieldMap) => {
if (!this.arraysEqual(this._proxies, this.data.map(field => field.Id))) {
var dataids = this.data.map(d => d.Id);
var proxies = this._proxies.map(p => p);
@@ -111,7 +112,7 @@ export class ListField<T extends Field> extends BasicField<T[]> {
ToJson(): { type: Types, data: string[], _id: string } {
return {
type: Types.List,
- data: this._proxies,
+ data: this._proxies || [],
_id: this.Id
}
}