aboutsummaryrefslogtreecommitdiff
path: root/src/new_fields/Doc.ts
diff options
context:
space:
mode:
authorMohammad Amoush <47069173+mamoush34@users.noreply.github.com>2020-02-08 17:03:12 -0500
committerMohammad Amoush <47069173+mamoush34@users.noreply.github.com>2020-02-08 17:03:12 -0500
commitf9855e8d1ec83405ae3cc7d0113b46de63fc0848 (patch)
treebf4be61a021e59b771c1cd5958fd9fd43cac8693 /src/new_fields/Doc.ts
parent87f5f043388b591c52e96a795fa461a79770550d (diff)
parent1b046f76cf39f1f6cb1875aa84b45db74b6d994e (diff)
Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web into webcam_mohammad
Diffstat (limited to 'src/new_fields/Doc.ts')
-rw-r--r--src/new_fields/Doc.ts362
1 files changed, 201 insertions, 161 deletions
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index e0ab5d97c..b1c1fda05 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -1,21 +1,23 @@
-import { observable, ObservableMap, runInAction, action, untracked } from "mobx";
+import { observable, ObservableMap, runInAction, action, computed } from "mobx";
import { alias, map, serializable } from "serializr";
import { DocServer } from "../client/DocServer";
import { DocumentType } from "../client/documents/DocumentTypes";
import { Scripting, scriptingGlobal } from "../client/util/Scripting";
import { afterDocDeserialize, autoObject, Deserializable, SerializationHelper } from "../client/util/SerializationHelper";
-import { Copy, HandleUpdate, Id, OnUpdate, Parent, Self, SelfProxy, ToScriptString, Update } from "./FieldSymbols";
+import { Copy, HandleUpdate, Id, OnUpdate, Parent, Self, SelfProxy, ToScriptString, ToString, Update } from "./FieldSymbols";
import { List } from "./List";
import { ObjectField } from "./ObjectField";
import { PrefetchProxy, ProxyField } from "./Proxy";
import { FieldId, RefField } from "./RefField";
import { listSpec } from "./Schema";
import { ComputedField, ScriptField } from "./ScriptField";
-import { BoolCast, Cast, FieldValue, NumCast, PromiseValue, StrCast, ToConstructor } from "./Types";
+import { BoolCast, Cast, FieldValue, NumCast, StrCast, ToConstructor } from "./Types";
import { deleteProperty, getField, getter, makeEditable, makeReadOnly, setter, updateFunction } from "./util";
import { intersectRect } from "../Utils";
import { UndoManager } from "../client/util/UndoManager";
import { computedFn } from "mobx-utils";
+import { RichTextField } from "./RichTextField";
+import { Script } from "vm";
export namespace Field {
export function toKeyValueString(doc: Doc, key: string): string {
@@ -36,6 +38,18 @@ export namespace Field {
return field[ToScriptString]();
}
}
+ export function toString(field: Field): string {
+ if (typeof field === "string") {
+ return field;
+ } else if (typeof field === "number" || typeof field === "boolean") {
+ return String(field);
+ } else if (field instanceof ObjectField) {
+ return field[ToString]();
+ } else if (field instanceof RefField) {
+ return field[ToString]();
+ }
+ return "(null)";
+ }
export function IsField(field: any): field is Field;
export function IsField(field: any, includeUndefined: true): field is Field | undefined;
export function IsField(field: any, includeUndefined: boolean = false): field is Field | undefined {
@@ -75,6 +89,8 @@ export function DocListCast(field: FieldResult): Doc[] {
export const WidthSym = Symbol("Width");
export const HeightSym = Symbol("Height");
+export const DataSym = Symbol("Data");
+export const LayoutSym = Symbol("Layout");
export const UpdatingFromServer = Symbol("UpdatingFromServer");
const CachedUpdates = Symbol("Cached updates");
@@ -96,8 +112,11 @@ export class Doc extends RefField {
get: getter,
// getPrototypeOf: (target) => Cast(target[SelfProxy].proto, Doc) || null, // TODO this might be able to replace the proto logic in getter
has: (target, key) => key in target.__fields,
- ownKeys: target => Object.keys(target.__fields),
+ ownKeys: target => Object.keys(target.__allfields),
getOwnPropertyDescriptor: (target, prop) => {
+ if (prop.toString() === "__LAYOUT__") {
+ return Reflect.getOwnPropertyDescriptor(target, prop);
+ }
if (prop in target.__fields) {
return {
configurable: true,//TODO Should configurable be true?
@@ -124,6 +143,13 @@ export class Doc extends RefField {
private get __fields() {
return this.___fields;
}
+ private get __allfields() {
+ let obj = {} as any;
+ Object.assign(obj, this.___fields);
+ runInAction(() => obj.__LAYOUT__ = this.__LAYOUT__);
+ return obj;
+ }
+
private set __fields(value) {
this.___fields = value;
@@ -150,12 +176,25 @@ export class Doc extends RefField {
private [Self] = this;
private [SelfProxy]: any;
- public [WidthSym] = () => NumCast(this[SelfProxy].width);
- public [HeightSym] = () => NumCast(this[SelfProxy].height);
+ public [WidthSym] = () => NumCast(this[SelfProxy]._width);
+ public [HeightSym] = () => NumCast(this[SelfProxy]._height);
+ public get [DataSym]() { return Cast(this[SelfProxy].resolvedDataDoc, Doc, null) || this[SelfProxy]; }
+ public get [LayoutSym]() { return this[SelfProxy].__LAYOUT__; }
+ @computed get __LAYOUT__() {
+ const templateLayoutDoc = Cast(Doc.LayoutField(this[SelfProxy]), Doc, null);
+ if (templateLayoutDoc) {
+ const renderFieldKey = (templateLayoutDoc[StrCast(templateLayoutDoc.layoutKey, "layout")] as string).split("'")[1];
+ return Cast(this[SelfProxy][renderFieldKey + "-layout[" + templateLayoutDoc[Id] + "]"], Doc, null) || templateLayoutDoc;
+ }
+ return undefined;
+ }
[ToScriptString]() {
return "invalid";
}
+ [ToString]() {
+ return "Doc";
+ }
private [CachedUpdates]: { [key: string]: () => void | Promise<any> } = {};
public static CurrentUserEmail: string = "";
@@ -403,92 +442,85 @@ export namespace Doc {
doc.title = title;
return doc;
}
- export function MakeAlias(doc: Doc) {
- const alias = !GetT(doc, "isPrototype", "boolean", true) ? Doc.MakeCopy(doc) : Doc.MakeDelegate(doc);
- const layout = Doc.Layout(alias);
- if (layout instanceof Doc && layout !== alias) {
+ export function MakeAlias(doc: Doc, id?: string) {
+ const alias = !GetT(doc, "isPrototype", "boolean", true) ? Doc.MakeCopy(doc, undefined, id) : Doc.MakeDelegate(doc, id);
+ const layout = Doc.LayoutField(alias);
+ if (layout instanceof Doc && layout !== alias && layout === Doc.Layout(alias)) {
Doc.SetLayout(alias, Doc.MakeAlias(layout));
}
- const aliasNumber = Doc.GetProto(doc).aliasNumber = NumCast(Doc.GetProto(doc).aliasNumber) + 1;
- alias.title = ComputedField.MakeFunction(`renameAlias(this, ${aliasNumber})`);
+ alias.aliasOf = doc;
+ alias.title = ComputedField.MakeFunction(`renameAlias(this, ${Doc.GetProto(doc).aliasNumber = NumCast(Doc.GetProto(doc).aliasNumber) + 1})`);
return alias;
}
//
// Determines whether the combination of the layoutDoc and dataDoc represents
- // a template relationship. If so, the layoutDoc will be expanded into a new
- // document that inherits the properties of the original layout while allowing
- // for individual layout properties to be overridden in the expanded layout.
+ // a template relationship : there is a dataDoc and it doesn't match the layoutDoc an
+ // the lyouatDoc's layout is layout string (not a document)
//
export function WillExpandTemplateLayout(layoutDoc: Doc, dataDoc?: Doc) {
- return BoolCast(layoutDoc.isTemplateField) && dataDoc && layoutDoc !== dataDoc && !(layoutDoc[StrCast(layoutDoc.layoutKey, "layout")] instanceof Doc);
+ return (layoutDoc.isTemplateForField || layoutDoc.isTemplateDoc) && dataDoc && layoutDoc !== dataDoc && !(Doc.LayoutField(layoutDoc) instanceof Doc);
}
//
- // Returns an expanded template layout for a target data document.
- // First it checks if an expanded layout already exists -- if so it will be stored on the dataDoc
- // using the template layout doc's id as the field key.
- // If it doesn't find the expanded layout, then it makes a delegate of the template layout and
- // saves it on the data doc indexed by the template layout's id
+ // Returns an expanded template layout for a target data document if there is a template relationship
+ // between the two. If so, the layoutDoc is expanded into a new document that inherits the properties
+ // of the original layout while allowing for individual layout properties to be overridden in the expanded layout.
//
- export function expandTemplateLayout(templateLayoutDoc: Doc, dataDoc?: Doc) {
- if (!WillExpandTemplateLayout(templateLayoutDoc, dataDoc) || !dataDoc) return templateLayoutDoc;
- // if we have a data doc that doesn't match the layout, then we're rendering a template.
- // ... which means we change the layout to be an expanded view of the template layout.
- // This allows the view override the template's properties and be referenceable as its own document.
-
- const expandedLayoutFieldKey = "Layout[" + templateLayoutDoc[Id] + "]";
- const expandedTemplateLayout = dataDoc[expandedLayoutFieldKey];
- if (expandedTemplateLayout instanceof Doc) {
- return expandedTemplateLayout;
- }
- if (expandedTemplateLayout === undefined) {
- setTimeout(() => dataDoc[expandedLayoutFieldKey] === undefined &&
- (dataDoc[expandedLayoutFieldKey] = Doc.MakeDelegate(templateLayoutDoc, undefined, "[" + templateLayoutDoc.title + "]")), 0);
+ export function expandTemplateLayout(templateLayoutDoc: Doc, targetDoc?: Doc) {
+ if (!WillExpandTemplateLayout(templateLayoutDoc, targetDoc) || !targetDoc) return templateLayoutDoc;
+
+ const templateField = StrCast(templateLayoutDoc.isTemplateForField); // the field that the template renders
+ // First it checks if an expanded layout already exists -- if so it will be stored on the dataDoc
+ // using the template layout doc's id as the field key.
+ // If it doesn't find the expanded layout, then it makes a delegate of the template layout and
+ // saves it on the data doc indexed by the template layout's id.
+ //
+ const layoutFielddKey = Doc.LayoutFieldKey(templateLayoutDoc);
+ const expandedLayoutFieldKey = (templateField || layoutFielddKey) + "-layout[" + templateLayoutDoc[Id] + "]";
+ let expandedTemplateLayout = targetDoc?.[expandedLayoutFieldKey];
+ if (templateLayoutDoc.resolvedDataDoc instanceof Promise) {
+
+ expandedTemplateLayout = undefined;
+ } else if (templateLayoutDoc.resolvedDataDoc === Doc.GetDataDoc(targetDoc)) {
+ expandedTemplateLayout = templateLayoutDoc;
+ } else if (expandedTemplateLayout === undefined) {
+ setTimeout(action(() => {
+ if (!targetDoc[expandedLayoutFieldKey]) {
+ const newLayoutDoc = Doc.MakeDelegate(templateLayoutDoc, undefined, "[" + templateLayoutDoc.title + "]");
+ newLayoutDoc.expandedTemplate = targetDoc;
+ targetDoc[expandedLayoutFieldKey] = newLayoutDoc;
+ const dataDoc = Doc.GetDataDoc(targetDoc);
+ newLayoutDoc.resolvedDataDoc = dataDoc;
+ if (dataDoc[templateField] === undefined && templateLayoutDoc[templateField] instanceof List && Cast(templateLayoutDoc[templateField], listSpec(Doc), []).length) {
+ dataDoc[templateField] = ComputedField.MakeFunction(`ObjectField.MakeCopy(templateLayoutDoc["${templateField}"] as List)`, { templateLayoutDoc: Doc.name }, { templateLayoutDoc: templateLayoutDoc });
+ }
+ }
+ }), 0);
}
- return undefined; // use the templateLayout when it's not a template or the expandedTemplate is pending.
+ return expandedTemplateLayout instanceof Doc ? expandedTemplateLayout : undefined; // layout is undefined if the expandedTemplate is pending.
}
- export function GetLayoutDataDocPair(doc: Doc, dataDoc: Doc | undefined, fieldKey: string, childDocLayout: Doc) {
- let layoutDoc: Doc | undefined = childDocLayout;
- const resolvedDataDoc = !doc.isTemplateField && dataDoc !== doc && dataDoc ? Doc.GetDataDoc(dataDoc) : undefined;
- if (resolvedDataDoc && Doc.WillExpandTemplateLayout(childDocLayout, resolvedDataDoc)) {
- const extensionDoc = fieldExtensionDoc(resolvedDataDoc, StrCast(childDocLayout.templateField, StrCast(childDocLayout.title)));
- layoutDoc = Doc.expandTemplateLayout(childDocLayout, extensionDoc !== resolvedDataDoc ? extensionDoc : undefined);
- setTimeout(() => layoutDoc && (layoutDoc.resolvedDataDoc = resolvedDataDoc), 0);
- } else layoutDoc = childDocLayout;
- return { layout: layoutDoc, data: resolvedDataDoc };
- }
-
- //
- // Resolves a reference to a field by returning 'doc' if no field extension is specified,
- // otherwise, it returns the extension document stored in doc.<fieldKey>_ext.
- // This mechanism allows any fields to be extended with an extension document that can
- // be used to capture field-specific metadata. For example, an image field can be extended
- // to store annotations, ink, and other data.
- //
- export function fieldExtensionDoc(doc: Doc, fieldKey: string) {
- const extension = doc[fieldKey + "_ext"];
- if (doc instanceof Doc && extension === undefined) {
- setTimeout(() => CreateDocumentExtensionForField(doc, fieldKey), 0);
- }
- return extension ? extension as Doc : undefined;
- }
- export function fieldExtensionDocSync(doc: Doc, fieldKey: string) {
- return (doc[fieldKey + "_ext"] as Doc) || CreateDocumentExtensionForField(doc, fieldKey);
+ // if the childDoc is a template for a field, then this will return the expanded layout with its data doc.
+ // otherwise, it just returns the childDoc
+ export function GetLayoutDataDocPair(containerDoc: Doc, containerDataDoc: Opt<Doc>, childDoc: Doc) {
+ const resolvedDataDoc = containerDataDoc === containerDoc || !containerDataDoc || (!childDoc.isTemplateDoc && !childDoc.isTemplateForField) ? undefined : containerDataDoc;
+ return { layout: Doc.expandTemplateLayout(childDoc, resolvedDataDoc), data: resolvedDataDoc };
}
-
export function CreateDocumentExtensionForField(doc: Doc, fieldKey: string) {
- const docExtensionForField = new Doc(doc[Id] + fieldKey, true);
- docExtensionForField.title = fieldKey + ".ext"; // courtesy field--- shouldn't be needed except maybe for debugging
- docExtensionForField.extendsDoc = doc; // this is used by search to map field matches on the extension doc back to the document it extends.
- docExtensionForField.extendsField = fieldKey; // this can be used by search to map matches on the extension doc back to the field that was extended.
- docExtensionForField.type = DocumentType.EXTENSION;
let proto: Doc | undefined = doc;
while (proto && !Doc.IsPrototype(proto) && proto.proto) {
proto = proto.proto;
}
- (proto ? proto : doc)[fieldKey + "_ext"] = new PrefetchProxy(docExtensionForField);
+ let docExtensionForField = ((proto || doc)[fieldKey + "_ext"] as Doc);
+ if (!docExtensionForField) {
+ docExtensionForField = new Doc(doc[Id] + fieldKey, true);
+ docExtensionForField.title = fieldKey + ".ext"; // courtesy field--- shouldn't be needed except maybe for debugging
+ docExtensionForField.extendsDoc = doc; // this is used by search to map field matches on the extension doc back to the document it extends.
+ docExtensionForField.extendsField = fieldKey; // this can be used by search to map matches on the extension doc back to the field that was extended.
+ docExtensionForField.type = DocumentType.EXTENSION;
+ (proto || doc)[fieldKey + "_ext"] = new PrefetchProxy(docExtensionForField);
+ }
return docExtensionForField;
}
@@ -517,7 +549,9 @@ export namespace Doc {
export function MakeCopy(doc: Doc, copyProto: boolean = false, copyProtoId?: string): Doc {
const copy = new Doc(copyProtoId, true);
+ const exclude = Cast(doc.excludeFields, listSpec("string"), []);
Object.keys(doc).forEach(key => {
+ if (exclude.includes(key)) return;
const cfield = ComputedField.WithoutComputed(() => FieldValue(doc[key]));
const field = ProxyField.WithoutProxy(() => doc[key]);
if (key === "proto" && copyProto) {
@@ -530,7 +564,7 @@ export namespace Doc {
} else if (cfield instanceof ComputedField) {
copy[key] = ComputedField.MakeFunction(cfield.script.originalScript);
} else if (field instanceof ObjectField) {
- copy[key] = ObjectField.MakeCopy(field);
+ copy[key] = key.includes("layout[") && doc[key] instanceof Doc ? Doc.MakeCopy(doc[key] as Doc, false) : ObjectField.MakeCopy(field);
} else if (field instanceof Promise) {
debugger; //This shouldn't happend...
} else {
@@ -557,68 +591,68 @@ export namespace Doc {
let _applyCount: number = 0;
export function ApplyTemplate(templateDoc: Doc) {
if (templateDoc) {
- const applied = ApplyTemplateTo(templateDoc, Doc.MakeDelegate(new Doc()), "layoutCustom", templateDoc.title + "(..." + _applyCount++ + ")");
+ const applied = ApplyTemplateTo(templateDoc, Doc.MakeDelegate(new Doc()), "layout", templateDoc.title + "(..." + _applyCount++ + ")");
applied && (Doc.GetProto(applied).layout = applied.layout);
return applied;
}
return undefined;
}
- export function ApplyTemplateTo(templateDoc: Doc, target: Doc, targetKey: string, titleTarget: string | undefined = undefined) {
+ export function ApplyTemplateTo(templateDoc: Doc, target: Doc, targetKey: string, titleTarget: string | undefined) {
if (!templateDoc) {
target.layout = undefined;
- target.nativeWidth = undefined;
- target.nativeHeight = undefined;
+ target._nativeWidth = undefined;
+ target._nativeHeight = undefined;
target.onClick = undefined;
target.type = undefined;
return;
}
- if ((target[targetKey] as Doc)?.proto !== templateDoc) {
- const layoutCustomLayout = Doc.MakeDelegate(templateDoc);
-
+ if (!Doc.AreProtosEqual(target[targetKey] as Doc, templateDoc)) {
titleTarget && (Doc.GetProto(target).title = titleTarget);
- Doc.GetProto(target).type = DocumentType.TEMPLATE;
- target.onClick = templateDoc.onClick instanceof ObjectField && templateDoc.onClick[Copy]();
-
- Doc.GetProto(target)[targetKey] = layoutCustomLayout;
+ Doc.GetProto(target)[targetKey] = new PrefetchProxy(templateDoc);
}
target.layoutKey = targetKey;
return target;
}
- export function MakeMetadataFieldTemplate(fieldTemplate: Doc, templateDataDoc: Doc, suppressTitle: boolean = false): boolean {
- // move data doc fields to layout doc as needed (nativeWidth/nativeHeight, data, ??)
- const metadataFieldName = StrCast(fieldTemplate.title).replace(/^-/, "");
- let fieldLayoutDoc = fieldTemplate;
- if (fieldTemplate.layout instanceof Doc) {
- fieldLayoutDoc = Doc.MakeDelegate(fieldTemplate.layout);
- }
-
- fieldTemplate.templateField = metadataFieldName;
- fieldTemplate.title = metadataFieldName;
- fieldTemplate.isTemplateField = true;
- /* move certain layout properties from the original data doc to the template layout to avoid
- inheriting them from the template's data doc which may also define these fields for its own use.
- */
- fieldTemplate.ignoreAspect = fieldTemplate.ignoreAspect === undefined ? undefined : BoolCast(fieldTemplate.ignoreAspect);
- fieldTemplate.singleColumn = BoolCast(fieldTemplate.singleColumn);
- fieldTemplate.nativeWidth = Cast(fieldTemplate.nativeWidth, "number");
- fieldTemplate.nativeHeight = Cast(fieldTemplate.nativeHeight, "number");
- fieldTemplate.type = fieldTemplate.type;
- fieldTemplate.panX = 0;
- fieldTemplate.panY = 0;
- fieldTemplate.scale = 1;
- fieldTemplate.showTitle = suppressTitle ? undefined : "title";
- const data = fieldTemplate.data;
- // setTimeout(action(() => {
- !templateDataDoc[metadataFieldName] && data instanceof ObjectField && (Doc.GetProto(templateDataDoc)[metadataFieldName] = ObjectField.MakeCopy(data));
- const layout = StrCast(fieldLayoutDoc.layout).replace(/fieldKey={'[^']*'}/, `fieldKey={'${metadataFieldName}'}`);
- const layoutDelegate = Doc.Layout(fieldTemplate);
- layoutDelegate.layout = layout;
- fieldTemplate.layout = layoutDelegate !== fieldTemplate ? layoutDelegate : layout;
- if (fieldTemplate.backgroundColor !== templateDataDoc.defaultBackgroundColor) fieldTemplate.defaultBackgroundColor = fieldTemplate.backgroundColor;
- fieldTemplate.proto = templateDataDoc;
- // }), 0);
+ //
+ // This function converts a generic field layout display into a field layout that displays a specific
+ // metadata field indicated by the title of the template field (not the default field that it was rendering)
+ //
+ export function MakeMetadataFieldTemplate(templateField: Doc, templateDoc: Opt<Doc>): boolean {
+
+ // find the metadata field key that this template field doc will display (indicated by its title)
+ const metadataFieldKey = StrCast(templateField.title).replace(/^-/, "");
+
+ // update the original template to mark it as a template
+ templateField.isTemplateForField = metadataFieldKey;
+ templateField.title = metadataFieldKey;
+
+ // move any data that the template field had been rendering over to the template doc so that things will still be rendered
+ // when the template field is adjusted to point to the new metadatafield key.
+ // note 1: if the template field contained a list of documents, each of those documents will be converted to templates as well.
+ // note 2: this will not overwrite any field that already exists on the template doc at the field key
+ if (!templateDoc?.[metadataFieldKey] && templateField.data instanceof ObjectField) {
+ Cast(templateField.data, listSpec(Doc), [])?.map(d => d instanceof Doc && MakeMetadataFieldTemplate(d, templateDoc));
+ (Doc.GetProto(templateField)[metadataFieldKey] = ObjectField.MakeCopy(templateField.data));
+ }
+ if (templateField.data instanceof RichTextField && (templateField.data.Text || templateField.data.Data.toString().includes("dashField"))) {
+ templateField._textTemplate = ComputedField.MakeFunction(`copyField(this.${metadataFieldKey})`, { this: Doc.name });
+ }
+
+ // get the layout string that the template uses to specify its layout
+ const templateFieldLayoutString = StrCast(Doc.LayoutField(Doc.Layout(templateField)));
+
+ // change itto render the target metadata field instead of what it was rendering before and assign it to the template field layout document.
+ Doc.Layout(templateField).layout = templateFieldLayoutString.replace(/fieldKey={'[^']*'}/, `fieldKey={'${metadataFieldKey}'}`);
+
+ // assign the template field doc a delegate of any extension document that was previously used to render the template field (since extension doc's carry rendering informatino)
+ Doc.Layout(templateField)[metadataFieldKey + "_ext"] = Doc.MakeDelegate(templateField[templateFieldLayoutString?.split("'")[1] + "_ext"] as Doc);
+
+ if (templateField.backgroundColor !== templateDoc?.defaultBackgroundColor) {
+ templateField.defaultBackgroundColor = templateField.backgroundColor;
+ }
+
return true;
}
@@ -627,12 +661,12 @@ export namespace Doc {
const doc1Layout = Doc.Layout(doc1);
const x2 = NumCast(doc2.x) - clusterDistance;
const y2 = NumCast(doc2.y) - clusterDistance;
- const w2 = NumCast(doc2Layout.width) + clusterDistance;
- const h2 = NumCast(doc2Layout.height) + clusterDistance;
+ const w2 = NumCast(doc2Layout._width) + clusterDistance;
+ const h2 = NumCast(doc2Layout._height) + clusterDistance;
const x = NumCast(doc1.x) - clusterDistance;
const y = NumCast(doc1.y) - clusterDistance;
- const w = NumCast(doc1Layout.width) + clusterDistance;
- const h = NumCast(doc1Layout.height) + clusterDistance;
+ const w = NumCast(doc1Layout._width) + clusterDistance;
+ const h = NumCast(doc1Layout._height) + clusterDistance;
return doc1.z === doc2.z && intersectRect({ left: x, top: y, width: w, height: h }, { left: x2, top: y2, width: w2, height: h2 });
}
@@ -657,9 +691,10 @@ export namespace Doc {
// the document containing the view layout information - will be the Document itself unless the Document has
// a layout field. In that case, all layout information comes from there unless overriden by Document
- export function Layout(doc: Doc) { return Doc.LayoutField(doc) instanceof Doc ? doc[StrCast(doc.layoutKey, "layout")] as Doc : doc; }
+ export function Layout(doc: Doc): Doc { return doc[LayoutSym] || doc; }
export function SetLayout(doc: Doc, layout: Doc | string) { doc[StrCast(doc.layoutKey, "layout")] = layout; }
export function LayoutField(doc: Doc) { return doc[StrCast(doc.layoutKey, "layout")]; }
+ export function LayoutFieldKey(doc: Doc): string { return StrCast(Doc.Layout(doc).layout).split("'")[1]; }
const manager = new DocData();
export function SearchQuery(): string { return manager._searchQuery; }
export function SetSearchQuery(query: string) { runInAction(() => manager._searchQuery = query); }
@@ -692,7 +727,7 @@ export namespace Doc {
export function LinkOtherAnchor(linkDoc: Doc, anchorDoc: Doc) { return Doc.AreProtosEqual(anchorDoc, Cast(linkDoc.anchor1, Doc) as Doc) ? Cast(linkDoc.anchor2, Doc) as Doc : Cast(linkDoc.anchor1, Doc) as Doc; }
- export function LinkEndpoint(linkDoc: Doc, anchorDoc: Doc) { return Doc.AreProtosEqual(anchorDoc, Cast(linkDoc.anchor1, Doc) as Doc) ? "layoutKey1" : "layoutKey2"; }
+ export function LinkEndpoint(linkDoc: Doc, anchorDoc: Doc) { return Doc.AreProtosEqual(anchorDoc, Cast(linkDoc.anchor1, Doc) as Doc) ? "layout_key1" : "layout_key2"; }
export function linkFollowUnhighlight() {
Doc.UnhighlightAll();
@@ -700,9 +735,9 @@ export namespace Doc {
}
let dt = 0;
- export function linkFollowHighlight(destDoc: Doc) {
+ export function linkFollowHighlight(destDoc: Doc, dataAndDisplayDocs = true) {
linkFollowUnhighlight();
- Doc.HighlightDoc(destDoc);
+ Doc.HighlightDoc(destDoc, dataAndDisplayDocs);
document.removeEventListener("pointerdown", linkFollowUnhighlight);
document.addEventListener("pointerdown", linkFollowUnhighlight);
const x = dt = Date.now();
@@ -716,10 +751,10 @@ export namespace Doc {
export function IsHighlighted(doc: Doc) {
return highlightManager.HighlightedDoc.get(doc) || highlightManager.HighlightedDoc.get(Doc.GetDataDoc(doc));
}
- export function HighlightDoc(doc: Doc) {
+ export function HighlightDoc(doc: Doc, dataAndDisplayDocs = true) {
runInAction(() => {
highlightManager.HighlightedDoc.set(doc, true);
- highlightManager.HighlightedDoc.set(Doc.GetDataDoc(doc), true);
+ dataAndDisplayDocs && highlightManager.HighlightedDoc.set(Doc.GetDataDoc(doc), true);
});
}
export function UnHighlightDoc(doc: Doc) {
@@ -746,61 +781,66 @@ export namespace Doc {
source.dragFactory instanceof Doc && source.dragFactory.isTemplateDoc ? source.dragFactory :
source && source.layout instanceof Doc && source.layout.isTemplateDoc ? source.layout : undefined;
}
+ export function setChildDetailedLayout(target: Doc, source?: Doc) {
+ target.childDetailed = source && source.isTemplateDoc ? source : source &&
+ source.dragFactory instanceof Doc && source.dragFactory.isTemplateDoc ? source.dragFactory :
+ source && source.layout instanceof Doc && source.layout.isTemplateDoc ? source.layout : undefined;
+ }
+
+ export function matchFieldValue(doc: Doc, key: string, value: any): boolean {
+ const fieldVal = doc[key];
+ if (Cast(fieldVal, listSpec("string"), []).length) {
+ const vals = Cast(fieldVal, listSpec("string"), []);
+ return vals.some(v => v === value);
+ }
+ const fieldStr = Field.toString(fieldVal as Field);
+ return fieldStr === value;
+ }
- export function MakeDocFilter(docFilters: string[]) {
- let docFilterText = "";
+ export function setNativeView(doc: any) {
+ const prevLayout = StrCast(doc.layoutKey).split("_")[1];
+ const deiconify = prevLayout === "icon" && StrCast(doc.deiconifyLayout) ? "layout_" + StrCast(doc.deiconifyLayout) : "";
+ doc.deiconifyLayout = undefined;
+ if (StrCast(doc.title).endsWith("_" + prevLayout)) doc.title = StrCast(doc.title).replace("_" + prevLayout, "");
+ doc.layoutKey = deiconify || "layout";
+ }
+ export function setDocFilter(container: Doc, key: string, value: any, modifiers?: string) {
+ const docFilters = Cast(container._docFilter, listSpec("string"), []);
for (let i = 0; i < docFilters.length; i += 3) {
- const key = docFilters[i];
- const value = docFilters[i + 1];
- const modifiers = docFilters[i + 2];
- const scriptText = `${modifiers === "x" ? "!" : ""}matchFieldValue(doc, "${key}", "${value}")`;
- docFilterText = docFilterText ? docFilterText + " || " + scriptText : scriptText;
+ if (docFilters[i] === key && docFilters[i + 1] === value) {
+ docFilters.splice(i, 3);
+ break;
+ }
+ }
+ if (modifiers !== undefined) {
+ docFilters.push(key);
+ docFilters.push(value);
+ docFilters.push(modifiers);
+ container._docFilter = new List<string>(docFilters);
}
- return docFilterText ? "(" + docFilterText + ")" : "";
}
}
Scripting.addGlobal(function renameAlias(doc: any, n: any) { return StrCast(Doc.GetProto(doc).title).replace(/\([0-9]*\)/, "") + `(${n})`; });
Scripting.addGlobal(function getProto(doc: any) { return Doc.GetProto(doc); });
Scripting.addGlobal(function setChildLayout(target: any, source: any) { Doc.setChildLayout(target, source); });
+Scripting.addGlobal(function setChildDetailedLayout(target: any, source: any) { Doc.setChildDetailedLayout(target, source); });
Scripting.addGlobal(function getAlias(doc: any) { return Doc.MakeAlias(doc); });
Scripting.addGlobal(function getCopy(doc: any, copyProto: any) { return doc.isTemplateDoc ? Doc.ApplyTemplate(doc) : Doc.MakeCopy(doc, copyProto); });
Scripting.addGlobal(function copyField(field: any) { return ObjectField.MakeCopy(field); });
Scripting.addGlobal(function aliasDocs(field: any) { return new List<Doc>(field.map((d: any) => Doc.MakeAlias(d))); });
Scripting.addGlobal(function docList(field: any) { return DocListCast(field); });
Scripting.addGlobal(function sameDocs(doc1: any, doc2: any) { return Doc.AreProtosEqual(doc1, doc2); });
+Scripting.addGlobal(function setNativeView(doc: any) { Doc.setNativeView(doc); });
Scripting.addGlobal(function undo() { return UndoManager.Undo(); });
Scripting.addGlobal(function redo() { return UndoManager.Redo(); });
+Scripting.addGlobal(function curPresentationItem() {
+ const curPres = Doc.UserDoc().curPresentation as Doc;
+ return curPres && DocListCast(curPres[Doc.LayoutFieldKey(curPres)])[NumCast(curPres._itemIndex)];
+})
Scripting.addGlobal(function selectDoc(doc: any) { Doc.UserDoc().SelectedDocs = new List([doc]); });
Scripting.addGlobal(function selectedDocs(container: Doc, excludeCollections: boolean, prevValue: any) {
const docs = DocListCast(Doc.UserDoc().SelectedDocs).filter(d => !Doc.AreProtosEqual(d, container) && !d.annotationOn && d.type !== DocumentType.DOCUMENT && d.type !== DocumentType.KVP && (!excludeCollections || !Cast(d.data, listSpec(Doc), null)));
return docs.length ? new List(docs) : prevValue;
});
-Scripting.addGlobal(function matchFieldValue(doc: Doc, key: string, value: any) {
- const fieldVal = doc[key] ? doc[key] : doc[key + "_ext"];
- if (StrCast(fieldVal, null) !== undefined) return StrCast(fieldVal) === value;
- if (NumCast(fieldVal, null) !== undefined) return NumCast(fieldVal) === value;
- if (Cast(fieldVal, listSpec("string"), []).length) {
- const vals = Cast(fieldVal, listSpec("string"), []);
- return vals.some(v => v === value);
- }
- return false;
-});
-Scripting.addGlobal(function setDocFilter(container: Doc, key: string, value: any, modifiers: string) {
- const docFilters = Cast(container.docFilter, listSpec("string"), []);
- let found = false;
- for (let i = 0; i < docFilters.length && !found; i += 3) {
- if (docFilters[i] === key && docFilters[i + 1] === value) {
- found = true;
- docFilters.splice(i, 3);
- }
- }
- if (!found || modifiers !== "none") {
- docFilters.push(key);
- docFilters.push(value);
- docFilters.push(modifiers);
- container.docFilter = new List<string>(docFilters);
- }
- const docFilterText = Doc.MakeDocFilter(docFilters);
- container.viewSpecScript = docFilterText ? ScriptField.MakeFunction(docFilterText, { doc: Doc.name }) : undefined;
-}); \ No newline at end of file
+Scripting.addGlobal(function setDocFilter(container: Doc, key: string, value: any, modifiers?: string) { Doc.setDocFilter(container, key, value, modifiers); }); \ No newline at end of file