aboutsummaryrefslogtreecommitdiff
path: root/src/client/documents/Documents.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/documents/Documents.ts')
-rw-r--r--src/client/documents/Documents.ts84
1 files changed, 67 insertions, 17 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index c64916897..45687f597 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -1,7 +1,7 @@
import { CollectionView } from "../views/collections/CollectionView";
import { CollectionViewType } from "../views/collections/CollectionView";
import { AudioBox } from "../views/nodes/AudioBox";
-import { FormattedTextBox } from "../views/nodes/FormattedTextBox";
+import { FormattedTextBox } from "../views/nodes/formattedText/FormattedTextBox";
import { ImageBox } from "../views/nodes/ImageBox";
import { KeyValueBox } from "../views/nodes/KeyValueBox";
import { PDFBox } from "../views/nodes/PDFBox";
@@ -75,12 +75,15 @@ export interface DocumentOptions {
_itemIndex?: number; // which item index the carousel viewer is showing
_showSidebar?: boolean; //whether an annotationsidebar should be displayed for text docuemnts
_singleLine?: boolean; // whether text document is restricted to a single line (carriage returns make new document)
+ "_carousel-caption-xMargin"?: number;
+ "_carousel-caption-yMargin"?: number;
x?: number;
y?: number;
z?: number;
author?: string;
dropAction?: dropActionType;
childDropAction?: dropActionType;
+ targetDropAction?: dropActionType;
layoutKey?: string;
type?: string;
title?: string;
@@ -90,12 +93,16 @@ export interface DocumentOptions {
scale?: number;
isDisplayPanel?: boolean; // whether the panel functions as GoldenLayout "stack" used to display documents
forceActive?: boolean;
- layout?: string | Doc;
+ layout?: string | Doc; // default layout string for a document
+ childLayoutTemplate?: Doc; // template for collection to use to render its children (see PresBox or Buxton layout in tree view)
+ childLayoutString?: string; // template string for collection to use to render its children
hideFilterView?: boolean; // whether to hide the filter popout on collections
hideHeadings?: boolean; // whether stacking view column headings should be hidden
isTemplateForField?: string; // the field key for which the containing document is a rendering template
isTemplateDoc?: boolean;
+ targetScriptKey?: string; // where to write a template script (used by collections with click templates which need to target onClick, onDoubleClick, etc)
templates?: List<string>;
+ hero?: ImageField; // primary image that best represents a compound document (e.g., for a buxton device document that has multiple images)
backgroundColor?: string | ScriptField; // background color for data doc
_backgroundColor?: string | ScriptField; // background color for each template layout doc ( overrides backgroundColor )
color?: string; // foreground color data doc
@@ -117,7 +124,8 @@ export interface DocumentOptions {
displayTimecode?: number; // the time that a document should be displayed (e.g., time an annotation should be displayed on a video)
borderRounding?: string;
boxShadow?: string;
- dontRegisterChildren?: boolean;
+ dontRegisterChildViews?: boolean;
+ "onDoubleClick-rawScript"?: string; // onDoubleClick script in raw text form
"onClick-rawScript"?: string; // onClick script in raw text form
"onCheckedClick-rawScript"?: string; // onChecked script in raw text form
"onCheckedClick-params"?: List<string>; // parameter list for onChecked treeview functions
@@ -131,7 +139,9 @@ export interface DocumentOptions {
ischecked?: ScriptField; // returns whether a font icon box is checked
activePen?: Doc; // which pen document is currently active (used as the radio button state for the 'unhecked' pen tool scripts)
onClick?: ScriptField;
+ onDoubleClick?: ScriptField;
onChildClick?: ScriptField; // script given to children of a collection to execute when they are clicked
+ onChildDoubleClick?: ScriptField; // script given to children of a collection to execute when they are double clicked
onPointerDown?: ScriptField;
onPointerUp?: ScriptField;
dropConverter?: ScriptField; // script to run when documents are dropped on this Document.
@@ -377,6 +387,15 @@ export namespace Docs {
*/
export namespace Create {
+ /**
+ * Synchronously returns a collection into which
+ * the device documents will be put. This is initially empty,
+ * but gets populated by updates from the web socket. When everything is over,
+ * this function cleans up after itself.
+ * s
+ * Look at Websocket.ts for the server-side counterpart to this
+ * function.
+ */
export function Buxton() {
let responded = false;
const loading = new Doc;
@@ -389,9 +408,13 @@ export namespace Docs {
});
const parentProto = Doc.GetProto(parent);
const { _socket } = DocServer;
+
+ // just in case, clean up
_socket.off(MessageStore.BuxtonDocumentResult.Message);
_socket.off(MessageStore.BuxtonImportComplete.Message);
- Utils.AddServerHandler(_socket, MessageStore.BuxtonDocumentResult, ({ device, errors }) => {
+
+ // this is where the client handles the receipt of a new valid parsed document
+ Utils.AddServerHandler(_socket, MessageStore.BuxtonDocumentResult, ({ device, invalid: errors }) => {
if (!responded) {
responded = true;
parentProto.data = new List<Doc>();
@@ -406,10 +429,10 @@ export namespace Docs {
_nativeWidth: nativeWidth,
_nativeHeight: nativeHeight
}));
- const doc = StackingDocument(deviceImages, { title: device.title, _LODdisable: true });
- const deviceProto = Doc.GetProto(doc);
- deviceProto.hero = new ImageField(constructed[0].url);
- Docs.Get.FromJson({ data: device, appendToExisting: { targetDoc: deviceProto } });
+ // the main document we create
+ const doc = StackingDocument(deviceImages, { title: device.title, _LODdisable: true, hero: new ImageField(constructed[0].url) });
+ // add the parsed attributes to this main document
+ Docs.Get.FromJson({ data: device, appendToExisting: { targetDoc: Doc.GetProto(doc) } });
Doc.AddDocToList(parentProto, "data", doc);
} else if (errors) {
console.log(errors);
@@ -417,14 +440,17 @@ export namespace Docs {
alert("A Buxton document import was completely empty (??)");
}
});
+
+ // when the import is complete, we stop listening for these creation
+ // and termination events and alert the user
Utils.AddServerHandler(_socket, MessageStore.BuxtonImportComplete, ({ deviceCount, errorCount }) => {
_socket.off(MessageStore.BuxtonDocumentResult.Message);
_socket.off(MessageStore.BuxtonImportComplete.Message);
alert(`Successfully imported ${deviceCount} device${deviceCount === 1 ? "" : "s"}, with ${errorCount} error${errorCount === 1 ? "" : "s"}, in ${(Date.now() - startTime) / 1000} seconds.`);
});
const startTime = Date.now();
- Utils.Emit(_socket, MessageStore.BeginBuxtonImport, "");
- return parent;
+ Utils.Emit(_socket, MessageStore.BeginBuxtonImport, ""); // signal the server to start importing
+ return parent; // synchronously return the collection, to be populateds
}
Scripting.addGlobal(Buxton);
@@ -468,7 +494,7 @@ export namespace Docs {
const dataDoc = MakeDataDelegate(proto, protoProps, data, fieldKey);
const viewDoc = Doc.MakeDelegate(dataDoc, delegId);
- viewDoc.type !== DocumentType.LINK && AudioBox.ActiveRecordings.map(d => DocUtils.MakeLink({ doc: viewDoc }, { doc: d }, "audio link", "audio timeline"));
+ viewDoc.type !== DocumentType.LINK && DocUtils.MakeLinkToActiveAudio(viewDoc);
return Doc.assign(viewDoc, delegateProps, true);
}
@@ -541,8 +567,23 @@ export namespace Docs {
return InstanceFromProto(Prototypes.get(DocumentType.COLOR), "", options);
}
- export function TextDocument(text: string, options: DocumentOptions = {}) {
- return InstanceFromProto(Prototypes.get(DocumentType.RTF), text, options, undefined, "text");
+ export function TextDocument(text: string, options: DocumentOptions = {}, fieldKey: string = "text") {
+ const rtf = {
+ doc: {
+ type: "doc", content: [{
+ type: "paragraph",
+ content: [{
+ type: "text",
+ text
+ }]
+ }]
+ },
+ selection: { type: "text", anchor: 1, head: 1 },
+ storedMarks: []
+ };
+
+ const field = text ? new RichTextField(JSON.stringify(rtf), text) : undefined;
+ return InstanceFromProto(Prototypes.get(DocumentType.RTF), field, options, undefined, fieldKey);
}
export function LinkDocument(source: { doc: Doc, ctx?: Doc }, target: { doc: Doc, ctx?: Doc }, options: DocumentOptions = {}, id?: string) {
@@ -553,9 +594,7 @@ export namespace Docs {
linkDocProto.anchor1_timecode = source.doc.currentTimecode || source.doc.displayTimecode;
linkDocProto.anchor2_timecode = target.doc.currentTimecode || target.doc.displayTimecode;
- if (linkDocProto.layout_key1 === undefined) {
- Cast(linkDocProto.proto, Doc, null).layout_key1 = LinkAnchorBox.LayoutString("anchor1");
- Cast(linkDocProto.proto, Doc, null).layout_key2 = LinkAnchorBox.LayoutString("anchor2");
+ if (linkDocProto.linkBoxExcludedKeys === undefined) {
Cast(linkDocProto.proto, Doc, null).linkBoxExcludedKeys = new List(["treeViewExpandedView", "treeViewHideTitle", "removeDropProperties", "linkBoxExcludedKeys", "treeViewOpen", "aliasNumber", "isPrototype", "lastOpened", "creationDate", "author"]);
Cast(linkDocProto.proto, Doc, null).layoutKey = undefined;
}
@@ -607,7 +646,7 @@ export namespace Docs {
}
export function DocumentDocument(document?: Doc, options: DocumentOptions = {}) {
- return InstanceFromProto(Prototypes.get(DocumentType.DOCHOLDER), document, { title: document ? document.title + "" : "container", ...options });
+ return InstanceFromProto(Prototypes.get(DocumentType.DOCHOLDER), document, { title: document ? document.title + "" : "container", targetDropAction: "move", ...options });
}
export function FreeformDocument(documents: Array<Doc>, options: DocumentOptions, id?: string) {
@@ -708,6 +747,10 @@ export namespace Docs {
};
return DockDocument(configs.map(c => c.doc), JSON.stringify(layoutConfig), options, id);
}
+
+ export function DelegateDocument(proto: Doc, options: DocumentOptions = {}) {
+ return InstanceFromProto(proto, undefined, options);
+ }
}
export namespace Get {
@@ -963,6 +1006,11 @@ export namespace DocUtils {
});
}
+ export let ActiveRecordings: Doc[] = [];
+
+ export function MakeLinkToActiveAudio(doc: Doc) {
+ DocUtils.ActiveRecordings.map(d => DocUtils.MakeLink({ doc: doc }, { doc: d }, "audio link", "audio timeline"));
+ }
export function MakeLink(source: { doc: Doc }, target: { doc: Doc }, linkRelationship: string = "", id?: string) {
const sv = DocumentManager.Instance.getDocumentView(source.doc);
if (sv && sv.props.ContainingCollectionDoc === target.doc) return;
@@ -1014,3 +1062,5 @@ export namespace DocUtils {
}
Scripting.addGlobal("Docs", Docs);
+Scripting.addGlobal(function makeDelegate(proto: any) { const d = Docs.Create.DelegateDocument(proto, { title: "child of " + proto.title }); return d; });
+