aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/views/collections/CollectionSubView.tsx6
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx43
-rw-r--r--src/client/views/nodes/ImageBox.tsx2
-rw-r--r--src/debug/Test.tsx13
-rw-r--r--src/new_fields/Doc.ts13
-rw-r--r--src/new_fields/List.ts5
-rw-r--r--src/new_fields/Schema.ts20
-rw-r--r--src/new_fields/Types.ts27
8 files changed, 74 insertions, 55 deletions
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 3add288fd..1a839fdcb 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -20,6 +20,8 @@ import { CollectionPDFView } from "./CollectionPDFView";
import { CollectionVideoView } from "./CollectionVideoView";
import { Doc } from "../../../new_fields/Doc";
import { DocComponent } from "../DocComponent";
+import { listSpec } from "../../../new_fields/Schema";
+import { Cast } from "../../../new_fields/Types";
export interface CollectionViewProps extends FieldViewProps {
addDocument: (document: Doc, allowDuplicates?: boolean) => boolean;
@@ -50,6 +52,10 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
this.createDropTarget(ele);
}
+ get children() {
+ return Cast(this.props.Document[this.props.fieldKey], listSpec(Doc));
+ }
+
@action
protected setCursorPosition(position: [number, number]) {
let ind;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 32104b49d..ee7d65d23 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -20,17 +20,19 @@ import { MarqueeView } from "./MarqueeView";
import React = require("react");
import v5 = require("uuid/v5");
import { createSchema, makeInterface } from "../../../../new_fields/Schema";
-import { Doc } from "../../../../new_fields/Doc";
-import { FieldValue } from "../../../../new_fields/Types";
+import { Doc, Id } from "../../../../new_fields/Doc";
+import { FieldValue, Cast } from "../../../../new_fields/Types";
+import { pageSchema } from "../../nodes/ImageBox";
+import { List } from "../../../../new_fields/List";
export const panZoomSchema = createSchema({
panX: "number",
panY: "number",
- zoom: "number"
+ scale: "number"
});
-type PanZoomDocument = makeInterface<[typeof panZoomSchema, typeof positionSchema]>;
-const PanZoomDocument: (doc: Doc) => PanZoomDocument = makeInterface(panZoomSchema, positionSchema);
+type PanZoomDocument = makeInterface<[typeof panZoomSchema, typeof positionSchema, typeof pageSchema]>;
+const PanZoomDocument = makeInterface(panZoomSchema, positionSchema, pageSchema);
@observer
export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
@@ -41,24 +43,24 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
private get _pheight() { return this.props.PanelHeight(); }
@computed get nativeWidth() { return FieldValue(this.Document.nativeWidth, 0); }
- @computed get nativeHeight() { return this.props.Document.GetNumber(KeyStore.NativeHeight, 0); }
+ @computed get nativeHeight() { return FieldValue(this.Document.nativeHeight, 0); }
private get borderWidth() { return this.isAnnotationOverlay ? 0 : COLLECTION_BORDER_WIDTH; }
- private get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldKey.Id === KeyStore.Annotations.Id; } // bcz: ? Why do we need to compare Id's?
+ private get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldKey === "annotations"; }
private childViews = () => this.views;
- private panX = () => this.props.Document.GetNumber(KeyStore.PanX, 0);
- private panY = () => this.props.Document.GetNumber(KeyStore.PanY, 0);
- private zoomScaling = () => this.props.Document.GetNumber(KeyStore.Scale, 1);
+ private panX = () => FieldValue(this.Document.panX, 0);
+ private panY = () => FieldValue(this.Document.panY, 0);
+ private zoomScaling = () => FieldValue(this.Document.scale, 1);
private centeringShiftX = () => !this.nativeWidth ? this._pwidth / 2 : 0; // shift so pan position is at center of window for non-overlay collections
private centeringShiftY = () => !this.nativeHeight ? this._pheight / 2 : 0;// shift so pan position is at center of window for non-overlay collections
private getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth, -this.borderWidth).translate(-this.centeringShiftX(), -this.centeringShiftY()).transform(this.getLocalTransform());
private getContainerTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth, -this.borderWidth);
private getLocalTransform = (): Transform => Transform.Identity().scale(1 / this.zoomScaling()).translate(this.panX(), this.panY());
- private addLiveTextBox = (newBox: Document) => {
- this._selectOnLoaded = newBox.Id;// track the new text box so we can give it a prop that tells it to focus itself when it's displayed
+ private addLiveTextBox = (newBox: Doc) => {
+ this._selectOnLoaded = newBox[Id];// track the new text box so we can give it a prop that tells it to focus itself when it's displayed
this.addDocument(newBox, false);
}
- private addDocument = (newBox: Document, allowDuplicates: boolean) => {
- newBox.SetNumber(KeyStore.Zoom, this.props.Document.GetNumber(KeyStore.Scale, 1));
+ private addDocument = (newBox: Doc, allowDuplicates: boolean) => {
+ newBox.zoom = FieldValue(this.Document.scale, 1);
return this.props.addDocument(this.bringToFront(newBox), false);
}
private selectDocuments = (docs: Document[]) => {
@@ -67,14 +69,11 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
SelectionManager.SelectDoc(dv!, true));
}
public getActiveDocuments = () => {
- var curPage = this.props.Document.GetNumber(KeyStore.CurPage, -1);
- return this.props.Document.GetList(this.props.fieldKey, [] as Document[]).reduce((active, doc) => {
- var page = doc.GetNumber(KeyStore.Page, -1);
- if (page === curPage || page === -1) {
- active.push(doc);
- }
- return active;
- }, [] as Document[]);
+ const curPage = FieldValue(this.Document.curPage, -1);
+ return FieldValue(this.children, [] as Doc[]).filter(doc => {
+ var page = Cast(doc.page, "number", -1);
+ return page === curPage || page === -1;
+ });
}
@undoBatch
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index c11aee56e..cd003ba71 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -71,7 +71,7 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD
@undoBatch
drop = (e: Event, de: DragManager.DropEvent) => {
if (de.data instanceof DragManager.DocumentDragData) {
- de.data.droppedDocuments.map(action((drop: Document) => {
+ de.data.droppedDocuments.forEach(action((drop: Document) => {
let layout = drop.GetText(KeyStore.BackgroundLayout, "");
if (layout.indexOf(ImageBox.name) !== -1) {
let imgData = this.props.Document.Get(KeyStore.Data);
diff --git a/src/debug/Test.tsx b/src/debug/Test.tsx
index 22a39f31e..179f987e0 100644
--- a/src/debug/Test.tsx
+++ b/src/debug/Test.tsx
@@ -1,12 +1,10 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { SerializationHelper } from '../client/util/SerializationHelper';
-import { createSchema, makeInterface, makeStrictInterface } from '../new_fields/Schema';
+import { createSchema, makeInterface, makeStrictInterface, listSpec } from '../new_fields/Schema';
import { ImageField } from '../new_fields/URLField';
import { Doc } from '../new_fields/Doc';
-import { ListSpec } from '../new_fields/Types';
import { List } from '../new_fields/List';
-const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this?
const schema1 = createSchema({
hello: "number",
@@ -22,7 +20,7 @@ type TestDoc = makeInterface<[typeof schema1]>;
const schema2 = createSchema({
hello: ImageField,
test: "boolean",
- fields: { List: "number" } as ListSpec<number>,
+ fields: listSpec("number"),
url: "number",
testDoc: ImageField
});
@@ -30,13 +28,6 @@ const schema2 = createSchema({
const Test2Doc = makeStrictInterface(schema2);
type Test2Doc = makeStrictInterface<typeof schema2>;
-const schema3 = createSchema({
- test: "boolean",
-});
-
-const Test3Doc = makeStrictInterface(schema3);
-type Test3Doc = makeStrictInterface<typeof schema3>;
-
const assert = (bool: boolean) => {
if (!bool) throw new Error();
};
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 5d18cbb2e..60abccce6 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -4,7 +4,7 @@ import { autoObject, SerializationHelper, Deserializable } from "../client/util/
import { Utils } from "../Utils";
import { DocServer } from "../client/DocServer";
import { setter, getter, getField } from "./util";
-import { Cast, FieldCtor } from "./Types";
+import { Cast, ToConstructor } from "./Types";
export type FieldId = string;
export const HandleUpdate = Symbol("HandleUpdate");
@@ -28,6 +28,7 @@ export const Parent = Symbol("Parent");
export class ObjectField {
protected [OnUpdate]?: (diff?: any) => void;
private [Parent]?: Doc;
+ readonly [Id] = "";
}
export type Field = number | string | boolean | ObjectField | RefField;
@@ -71,7 +72,7 @@ export namespace Doc {
const self = doc[Self];
return new Promise(res => getField(self, key, ignoreProto, res));
}
- export function GetTAsync<T extends Field>(doc: Doc, key: string, ctor: FieldCtor<T>, ignoreProto: boolean = false): Promise<T | undefined> {
+ export function GetTAsync<T extends Field>(doc: Doc, key: string, ctor: ToConstructor<T>, ignoreProto: boolean = false): Promise<T | undefined> {
return new Promise(async res => {
const field = await GetAsync(doc, key, ignoreProto);
return Cast(field, ctor);
@@ -81,9 +82,15 @@ export namespace Doc {
const self = doc[Self];
return getField(self, key, ignoreProto);
}
- export function GetT<T extends Field>(doc: Doc, key: string, ctor: FieldCtor<T>, ignoreProto: boolean = false): T | null | undefined {
+ export function GetT<T extends Field>(doc: Doc, key: string, ctor: ToConstructor<T>, ignoreProto: boolean = false): T | null | undefined {
return Cast(Get(doc, key, ignoreProto), ctor) as T | null | undefined;
}
+ export async function SetOnPrototype(doc: Doc, key: string, value: Field) {
+ const proto = await Cast(doc.prototype, Doc);
+ if (proto) {
+ proto[key] = value;
+ }
+ }
export function MakeDelegate(doc: Opt<Doc>): Opt<Doc> {
if (!doc) {
return undefined;
diff --git a/src/new_fields/List.ts b/src/new_fields/List.ts
index 58b252f7b..f3ec9e2c5 100644
--- a/src/new_fields/List.ts
+++ b/src/new_fields/List.ts
@@ -6,8 +6,9 @@ import { observable } from "mobx";
@Deserializable("list")
class ListImpl<T extends Field> extends ObjectField {
- constructor() {
+ constructor(fields: T[] = []) {
super();
+ this.__fields = fields;
const list = new Proxy<this>(this, {
set: setter,
get: getter,
@@ -21,7 +22,7 @@ class ListImpl<T extends Field> extends ObjectField {
@serializable(alias("fields", list(autoObject())))
@observable
- private __fields: (T | null | undefined)[] = [];
+ private __fields: (T | null | undefined)[];
private [Update] = (diff: any) => {
console.log(diff);
diff --git a/src/new_fields/Schema.ts b/src/new_fields/Schema.ts
index 3b7078cb0..59c6db0bd 100644
--- a/src/new_fields/Schema.ts
+++ b/src/new_fields/Schema.ts
@@ -1,5 +1,7 @@
-import { Interface, ToInterface, Cast, FieldCtor, ToConstructor, HasTail, Head, Tail } from "./Types";
+import { Interface, ToInterface, Cast, ToConstructor, HasTail, Head, Tail, ListSpec, ToType } from "./Types";
import { Doc, Field, ObjectField } from "./Doc";
+import { URLField } from "./URLField";
+import { List } from "./List";
type AllToInterface<T extends Interface[]> = {
1: ToInterface<Head<T>> & AllToInterface<Tail<T>>,
@@ -10,10 +12,10 @@ export const emptySchema = createSchema({});
export const Document = makeInterface(emptySchema);
export type Document = makeInterface<[typeof emptySchema]>;
-export type makeInterface<T extends Interface[], U extends Doc = Doc> = Partial<AllToInterface<T>> & U;
+export type makeInterface<T extends Interface[]> = Partial<AllToInterface<T>> & Doc;
// export function makeInterface<T extends Interface[], U extends Doc>(schemas: T): (doc: U) => All<T, U>;
// export function makeInterface<T extends Interface, U extends Doc>(schema: T): (doc: U) => makeInterface<T, U>;
-export function makeInterface<T extends Interface[], U extends Doc>(...schemas: T): (doc: U) => makeInterface<T, U> {
+export function makeInterface<T extends Interface[]>(...schemas: T): (doc: Doc) => makeInterface<T> {
let schema: Interface = {};
for (const s of schemas) {
for (const key in s) {
@@ -33,7 +35,10 @@ export function makeInterface<T extends Interface[], U extends Doc>(...schemas:
return true;
}
});
- return function (doc: any) {
+ return function (doc: Doc) {
+ if (!(doc instanceof Doc)) {
+ throw new Error("Currently wrapping a schema in another schema isn't supported");
+ }
const obj = Object.create(proto, { doc: { value: doc, writable: false } });
return obj;
};
@@ -59,6 +64,9 @@ export function makeStrictInterface<T extends Interface>(schema: T): (doc: Doc)
});
}
return function (doc: any) {
+ if (!(doc instanceof Doc)) {
+ throw new Error("Currently wrapping a schema in another schema isn't supported");
+ }
const obj = Object.create(proto);
obj.__doc = doc;
return obj;
@@ -69,3 +77,7 @@ export function createSchema<T extends Interface>(schema: T): T & { prototype: T
schema.prototype = Doc;
return schema as any;
}
+
+export function listSpec<U extends ToConstructor<Field>>(type: U): ListSpec<ToType<U>> {
+ return { List: type as any };//TODO Types
+} \ No newline at end of file
diff --git a/src/new_fields/Types.ts b/src/new_fields/Types.ts
index f4f66fe5c..fbf002c84 100644
--- a/src/new_fields/Types.ts
+++ b/src/new_fields/Types.ts
@@ -1,25 +1,28 @@
import { Field, Opt, FieldWaiting, FieldResult } from "./Doc";
import { List } from "./List";
-export type ToType<T> =
+export type ToType<T extends ToConstructor<Field> | ListSpec<Field>> =
T extends "string" ? string :
T extends "number" ? number :
T extends "boolean" ? boolean :
T extends ListSpec<infer U> ? List<U> :
// T extends { new(...args: any[]): infer R } ? (R | Promise<R>) : never;
+ T extends { new(...args: any[]): List<Field> } ? never :
T extends { new(...args: any[]): infer R } ? R : never;
-export type ToConstructor<T> =
+export type ToConstructor<T extends Field> =
T extends string ? "string" :
T extends number ? "number" :
- T extends boolean ? "boolean" : new (...args: any[]) => T;
+ T extends boolean ? "boolean" :
+ T extends List<infer U> ? ListSpec<U> :
+ new (...args: any[]) => T;
-export type ToInterface<T> = {
+export type ToInterface<T extends Interface> = {
[P in keyof T]: ToType<T[P]>;
};
-// type ListSpec<T extends Field[]> = { List: FieldCtor<Head<T>> | ListSpec<Tail<T>> };
-export type ListSpec<T> = { List: FieldCtor<T> };
+// type ListSpec<T extends Field[]> = { List: ToContructor<Head<T>> | ListSpec<Tail<T>> };
+export type ListSpec<T extends Field> = { List: ToConstructor<T> };
// type ListType<U extends Field[]> = { 0: List<ListType<Tail<U>>>, 1: ToType<Head<U>> }[HasTail<U> extends true ? 0 : 1];
@@ -34,11 +37,9 @@ export interface Interface {
// [key: string]: ToConstructor<Field> | ListSpec<Field[]>;
}
-export type FieldCtor<T extends Field> = T extends List<infer R> ? ListSpec<R> : ToConstructor<T>;
-
-export function Cast<T extends FieldCtor<Field>>(field: Field | FieldWaiting | undefined, ctor: T): FieldResult<ToType<T>>;
-export function Cast<T extends FieldCtor<Field>>(field: Field | FieldWaiting | undefined, ctor: T, defaultVal: ToType<T>): ToType<T>;
-export function Cast<T extends FieldCtor<Field>>(field: Field | FieldWaiting | undefined, ctor: T, defaultVal?: ToType<T>): FieldResult<ToType<T>> | undefined {
+export function Cast<T extends ToConstructor<Field> | ListSpec<Field>>(field: Field | FieldWaiting | undefined, ctor: T): FieldResult<ToType<T>>;
+export function Cast<T extends ToConstructor<Field> | ListSpec<Field>>(field: Field | FieldWaiting | undefined, ctor: T, defaultVal: ToType<T>): ToType<T>;
+export function Cast<T extends ToConstructor<Field> | ListSpec<Field>>(field: Field | FieldWaiting | undefined, ctor: T, defaultVal?: ToType<T>): FieldResult<ToType<T>> | undefined {
if (field instanceof Promise) {
return defaultVal === undefined ? field.then(f => Cast(f, ctor) as any) : defaultVal;
}
@@ -58,7 +59,9 @@ export function Cast<T extends FieldCtor<Field>>(field: Field | FieldWaiting | u
return defaultVal;
}
-export function FieldValue<T extends Field, U extends T>(field: Opt<T> | Promise<Opt<T>>, defaultValue: U): T;
+type WithoutList<T extends Field> = T extends List<infer R> ? R[] : T;
+
+export function FieldValue<T extends Field, U extends WithoutList<T>>(field: Opt<T> | Promise<Opt<T>>, defaultValue: U): WithoutList<T>;
export function FieldValue<T extends Field>(field: Opt<T> | Promise<Opt<T>>): Opt<T>;
export function FieldValue<T extends Field>(field: Opt<T> | Promise<Opt<T>>, defaultValue?: T): Opt<T> {
return field instanceof Promise ? defaultValue : field;