aboutsummaryrefslogtreecommitdiff
path: root/src/client/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/util')
-rw-r--r--src/client/util/CurrentUserUtils.ts58
-rw-r--r--src/client/util/DictationManager.ts10
-rw-r--r--src/client/util/DocumentManager.ts4
-rw-r--r--src/client/util/DragManager.ts56
-rw-r--r--src/client/util/DropConverter.ts10
-rw-r--r--src/client/util/LinkFollower.ts32
-rw-r--r--src/client/util/Scripting.ts8
-rw-r--r--src/client/util/SelectionManager.ts45
-rw-r--r--src/client/util/SettingsManager.tsx4
9 files changed, 134 insertions, 93 deletions
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 2820c66ee..76ea3e3ea 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -25,6 +25,7 @@ import { OpenWhere } from "../views/nodes/DocumentView";
import { OverlayView } from "../views/OverlayView";
import { DragManager } from "./DragManager";
import { MakeTemplate } from "./DropConverter";
+import { FollowLinkScript } from "./LinkFollower";
import { LinkManager } from "./LinkManager";
import { ScriptingGlobals } from "./ScriptingGlobals";
import { ColorScheme } from "./SettingsManager";
@@ -41,11 +42,13 @@ interface Button {
numBtnMax?: number;
switchToggle?: boolean;
width?: number;
+ linearBtnWidth?: number;
toolType?: string; // type of pen tool
expertMode?: boolean;// available only in expert mode
btnList?: List<string>;
ignoreClick?: boolean;
buttonText?: string;
+ backgroundColor?: string;
// fields that do not correspond to DocumentOption fields
scripts?: { script?: string; onClick?: string; onDoubleClick?: string }
@@ -61,7 +64,7 @@ export class CurrentUserUtils {
const requiredTypeNameFields:{btnOpts:DocumentOptions, templateOpts:DocumentOptions, template:(opts:DocumentOptions) => Doc}[] = [
{
btnOpts: { title: "slide", icon: "address-card" },
- templateOpts: { _width: 400, _height: 300, title: "slideView", childDocumentsActive: true, _xMargin: 3, _yMargin: 3, system: true },
+ templateOpts: { _width: 400, _height: 300, title: "slideView", _xMargin: 3, _yMargin: 3, system: true },
template: (opts:DocumentOptions) => Docs.Create.MultirowDocument(
[
Docs.Create.MulticolumnDocument([], { title: "data", _height: 200, system: true }),
@@ -94,7 +97,7 @@ export class CurrentUserUtils {
const reqdOpts:DocumentOptions = {
title: "Experimental Tools", _xMargin: 0, _showTitle: "title", _chromeHidden: true,
- _stayInCollection: true, _hideContextMenu: true, _forceActive: true, system: true, childDocumentsActive: true,
+ _stayInCollection: true, _hideContextMenu: true, _forceActive: true, system: true,
_autoHeight: true, _width: 500, _height: 300, _fitWidth: true, _columnWidth: 35, ignoreClick: true, _lockedPosition: true,
};
const reqdScripts = { dropConverter : "convertToButtons(dragData)" };
@@ -148,7 +151,7 @@ export class CurrentUserUtils {
{ noteType: "Idea", backgroundColor: "pink", icon: "lightbulb" },
{ noteType: "Topic", backgroundColor: "lightblue", icon: "book-open" }];
const reqdNoteList = reqdTempOpts.map(opts => {
- const reqdOpts = {...opts, title: "text", width:200, autoHeight: true, fitWidth: true, system: true};
+ const reqdOpts = {...opts, title: "text", width:200, autoHeight: true, fitWidth: true};
const noteType = tempNotes ? DocListCast(tempNotes.data).find(doc => doc.noteType === opts.noteType): undefined;
return DocUtils.AssignOpts(noteType, reqdOpts) ?? MakeTemplate(Docs.Create.TextDocument("",reqdOpts), true, opts.noteType??"Note");
});
@@ -183,10 +186,10 @@ export class CurrentUserUtils {
case DocumentType.IMG : creator = imageBox; break;
case DocumentType.FONTICON: creator = fontBox; break;
}
- const allopts = {system: true, ...opts};
+ const allopts = {system: true, onClickScriptDisable: "never", ...opts};
return DocUtils.AssignScripts( (curIcon?.iconTemplate === opts.iconTemplate ?
DocUtils.AssignOpts(curIcon, allopts):undefined) ?? ((templateIconsDoc[iconFieldName] = MakeTemplate(creator(allopts), true, iconFieldName, templateField))),
- {onClick:"deiconifyView(documentView)", onDoubleClick: "deiconifyViewToLightbox(documentView)"});
+ {onClick:"deiconifyView(documentView)", onDoubleClick: "deiconifyViewToLightbox(documentView)", });
};
const labelBox = (opts: DocumentOptions, data?:string) => Docs.Create.LabelDocument({
textTransform: "unset", letterSpacing: "unset", _singleLine: false, _minFontSize: 14, _maxFontSize: 24, borderRounding: "5px", _width: 150, _height: 70, _xPadding: 10, _yPadding: 10, ...opts
@@ -224,11 +227,11 @@ export class CurrentUserUtils {
{
type: "paragraph", attrs: {}, content: [{
type: "dashField",
- attrs: { fieldKey: "author", docid: "", hideKey: false },
+ attrs: { fieldKey: "author", docId: "", hideKey: false },
marks: [{ type: "strong" }]
}, {
type: "dashField",
- attrs: { fieldKey: "creationDate", docid: "", hideKey: false },
+ attrs: { fieldKey: "creationDate", docId: "", hideKey: false },
marks: [{ type: "strong" }]
}]
}]
@@ -269,9 +272,9 @@ export class CurrentUserUtils {
{key: "Map", creator: opts => Docs.Create.MapDocument([], opts), opts: { _width: 800, _height: 600, _fitWidth: true, _showSidebar: true, }},
{key: "Screengrab", creator: Docs.Create.ScreenshotDocument, opts: { _width: 400, _height: 200 }},
{key: "WebCam", creator: opts => Docs.Create.WebCamDocument("", opts), opts: { _width: 400, _height: 200, recording:true, system: true, cloneFieldFilter: new List<string>(["system"]) }},
- {key: "Button", creator: Docs.Create.ButtonDocument, opts: { _width: 150, _height: 50, _xPadding: 10, _yPadding: 10, _isLinkButton: true }},
+ {key: "Button", creator: Docs.Create.ButtonDocument, opts: { _width: 150, _height: 50, _xPadding: 10, _yPadding: 10, onClick: FollowLinkScript()}},
{key: "Script", creator: opts => Docs.Create.ScriptingDocument(null, opts), opts: { _width: 200, _height: 250, }},
- // {key: "DataViz", creator: opts => Docs.Create.DataVizDocument(opts), opts: { _width: 300, _height: 300 }},
+ {key: "DataViz", creator: opts => Docs.Create.DataVizDocument("/users/rz/Downloads/addresses.csv", opts), opts: { _width: 300, _height: 300 }},
{key: "Header", creator: headerTemplate, opts: { _width: 300, _height: 70, _headerPointerEvents: "all", _headerHeight: 12, _headerFontSize: 9, _autoHeight: true, treeViewHideUnrendered: true}},
{key: "Trail", creator: Docs.Create.PresDocument, opts: { _width: 400, _height: 30, _viewType: CollectionViewType.Stacking, targetDropAction: "alias" as any, treeViewHideTitle: true, _fitWidth:true, _chromeHidden: true, boxShadow: "0 0" }},
{key: "Tab", creator: opts => Docs.Create.FreeformDocument([], opts), opts: { _width: 500, _height: 800, _fitWidth: true, _backgroundGridShow: true, }},
@@ -300,7 +303,7 @@ export class CurrentUserUtils {
{ toolTip: "Tap or drag to create a data viz node", title: "DataViz", icon: "file", dragFactory: doc.emptyDataViz as Doc, clickFactory: DocCast(doc.emptyDataViz)},
{ toolTip: "Tap or drag to create a bullet slide", title: "PPT Slide", icon: "file", dragFactory: doc.emptySlide as Doc, clickFactory: DocCast(doc.emptySlide), openFactoryLocation: OpenWhere.overlay},
{ toolTip: "Tap or drag to create a data note", title: "DataNote", icon: "window-maximize", dragFactory: doc.emptyHeader as Doc, clickFactory: DocCast(doc.emptyHeader), openFactoryAsDelegate: true },
- { toolTip: "Toggle a Calculator REPL", title: "repl", icon: "calculator", clickFactory: "repl" as any, openFactoryLocation: OpenWhere.overlay},
+ { toolTip: "Toggle a Calculator REPL", title: "repl", icon: "calculator", clickFactory: 'repl' as any, openFactoryLocation: OpenWhere.overlay},
].map(tuple => (
{ openFactoryLocation: OpenWhere.addRight,
scripts: { onClick: 'openDoc(copyDragFactory(this.clickFactory,this.openFactoryAsDelegate), this.openFactoryLocation)',
@@ -313,7 +316,7 @@ export class CurrentUserUtils {
const creatorBtns = CurrentUserUtils.creatorBtnDescriptors(doc).map((reqdOpts) => {
const btn = dragCreatorDoc ? DocListCast(dragCreatorDoc.data).find(doc => doc.title === reqdOpts.title): undefined;
const opts:DocumentOptions = {...OmitKeys(reqdOpts, ["funcs", "scripts", "backgroundColor"]).omit,
- _nativeWidth: 50, _nativeHeight: 50, _width: 35, _height: 35, _hideContextMenu: true, _stayInCollection: true,
+ _width: 35, _height: 35, _hideContextMenu: true, _stayInCollection: true,
btnType: ButtonType.ToolButton, backgroundColor: reqdOpts.backgroundColor ?? Colors.DARK_GRAY, color: Colors.WHITE, system: true,
_removeDropProperties: new List<string>(["_stayInCollection"]),
};
@@ -323,7 +326,7 @@ export class CurrentUserUtils {
const reqdOpts:DocumentOptions = {
title: "Basic Item Creators", _showTitle: "title", _xMargin: 0, _stayInCollection: true, _hideContextMenu: true, _chromeHidden: true, system: true,
_autoHeight: true, _width: 500, _height: 300, _fitWidth: true, _columnWidth: 40, ignoreClick: true, _lockedPosition: true, _forceActive: true,
- childDocumentsActive: true, childDropAction: 'alias'
+ childDropAction: 'alias'
};
const reqdScripts = { dropConverter: "convertToButtons(dragData)" };
return DocUtils.AssignScripts(DocUtils.AssignOpts(dragCreatorDoc, reqdOpts, creatorBtns) ?? Docs.Create.MasonryDocument(creatorBtns, reqdOpts), reqdScripts);
@@ -608,6 +611,22 @@ export class CurrentUserUtils {
return DocUtils.AssignDocField(doc, field, (opts, items) => this.linearButtonList(opts, items??[]), dockBtnsReqdOpts, btns);
}
+ static freeTools(): Button[] {
+ return [
+ { title: "Bottom", icon: "arrows-down-to-line",toolTip: "Make doc topmost", btnType: ButtonType.ClickButton, expertMode: false, funcs: {}, scripts: { onClick: 'sendToBack()'}}, // Only when floating document is selected in freeform
+ { title: "Top", icon: "arrows-up-to-line", toolTip: "Make doc bottommost", btnType: ButtonType.ClickButton, expertMode: false, funcs: {}, scripts: { onClick: 'bringToFront()'}}, // Only when floating document is selected in freeform
+ ]
+ }
+ static viewTools(): Button[] {
+ return [
+ { title: "Grid", icon: "border-all", toolTip: "Show Grid", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"grid", funcs: {}, scripts: { onClick: 'showFreeform(self.toolType, _readOnly_)'}}, // Only when floating document is selected in freeform
+ { title: "Snap\xA0Lines",icon: "th", toolTip: "Show Snap Lines", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"snap lines", funcs: {}, scripts: { onClick: 'showFreeform(self.toolType, _readOnly_)'}}, // Only when floating document is selected in freeform
+ { title: "View\xA0All", icon: "object-group",toolTip: "Fit all Docs to View",btnType: ButtonType.ToggleButton, expertMode: false, toolType:"viewAll", funcs: {}, scripts: { onClick: 'showFreeform(self.toolType, _readOnly_)'}}, // Only when floating document is selected in freeform
+ { title: "Clusters", icon: "braille", toolTip: "Show Doc Clusters", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"clusters", funcs: {}, scripts: { onClick: 'showFreeform(self.toolType, _readOnly_)'}}, // Only when floating document is selected in freeform
+ { title: "Arrange", icon: "window", toolTip: "Toggle Auto Arrange", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"arrange", funcs: {hidden: 'IsNoviceMode()'}, scripts: { onClick: 'showFreeform(self.toolType, _readOnly_)'}}, // Only when floating document is selected in freeform
+ { title: "Reset", icon: "check", toolTip: "Reset View", btnType: ButtonType.ClickButton, expertMode: false, backgroundColor:"transparent", scripts: { onClick: 'resetView()'}}, // Only when floating document is selected in freeform
+ ]
+ }
static textTools():Button[] {
return [
{ title: "Font", toolTip: "Font", width: 100, btnType: ButtonType.DropdownList, toolType:"font", ignoreClick: true, scripts: {script: '{ return setFontAttr(self.toolType, value, _readOnly_);}'},
@@ -666,17 +685,20 @@ export class CurrentUserUtils {
CollectionViewType.Carousel3D, CollectionViewType.Linear, CollectionViewType.Map,
CollectionViewType.Grid, CollectionViewType.NoteTaking]),
title: "Perspective", toolTip: "View", btnType: ButtonType.DropdownList, ignoreClick: true, width: 100, scripts: { script: 'setView(value, _readOnly_)'}},
- { title: "Pin", icon: "map-pin", toolTip: "Pin View to Trail", btnType: ButtonType.ClickButton, expertMode: false, toolType:"tab", funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`}, width: 20, scripts: { onClick: 'pinWithView(_readOnly_, altKey)'}},
- { title: "Fill", icon: "fill-drip", toolTip: "Background Fill Color",btnType: ButtonType.ColorButton, expertMode: false, toolType:"tab", ignoreClick: true, width: 20, scripts: { script: 'return setBackgroundColor(value, _readOnly_)'}}, // Only when a document is selected
- { title: "Header", icon: "heading", toolTip: "Header Color", btnType: ButtonType.ColorButton, expertMode: false, toolType:"tab", ignoreClick: true, scripts: { script: 'return setHeaderColor(value, _readOnly_)'}},
+ { title: "Pin", icon: "map-pin", toolTip: "Pin View to Trail", btnType: ButtonType.ClickButton, expertMode: false, width: 20, scripts: { onClick: 'pinWithView(altKey)'}},
+ { title: "Fill", icon: "fill-drip", toolTip: "Background Fill Color",btnType: ButtonType.ColorButton, expertMode: false, ignoreClick: true, width: 20, scripts: { script: 'return setBackgroundColor(value, _readOnly_)'}}, // Only when a document is selected
+ { title: "Header", icon: "heading", toolTip: "Header Color", btnType: ButtonType.ColorButton, expertMode: false, ignoreClick: true, scripts: { script: 'return setHeaderColor(value, _readOnly_)'}},
{ title: "Overlay", icon: "layer-group", toolTip: "Overlay", btnType: ButtonType.ToggleButton, expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectionManager_selectedDocType(self.toolType, self.expertMode, true)'}, scripts: { onClick: 'toggleOverlay(_readOnly_)'}}, // Only when floating document is selected in freeform
+ { title: "Z order", icon: "z", toolTip: "Bring Forward on Drag",btnType: ButtonType.ToggleButton, expertMode: false, toolType:CollectionViewType.Freeform, funcs: {}, scripts: { onClick: 'toggleRaiseOnDrag(_readOnly_)'}}, // Only when floating document is selected in freeform
{ title: "Back", icon: "chevron-left", toolTip: "Prev Animation Frame", btnType: ButtonType.ClickButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectionManager_selectedDocType(self.toolType, self.expertMode)'}, width: 20, scripts: { onClick: 'prevKeyFrame(_readOnly_)'}},
{ title: "Num", icon:"",toolTip: "Frame Number (click to toggle edit mode)",btnType: ButtonType.TextButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectionManager_selectedDocType(self.toolType, self.expertMode)', buttonText: 'selectedDocs()?.lastElement()?.currentFrame?.toString()'}, width: 20, scripts: { onClick: '{ return curKeyFrame(_readOnly_);}'}},
{ title: "Fwd", icon: "chevron-right", toolTip: "Next Animation Frame", btnType: ButtonType.ClickButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectionManager_selectedDocType(self.toolType, self.expertMode)'}, width: 20, scripts: { onClick: 'nextKeyFrame(_readOnly_)'}},
{ title: "Text", icon: "Text", toolTip: "Text functions", subMenu: CurrentUserUtils.textTools(), expertMode: false, toolType:DocumentType.RTF, funcs: { linearViewIsExpanded: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Always available
{ title: "Ink", icon: "Ink", toolTip: "Ink functions", subMenu: CurrentUserUtils.inkTools(), expertMode: false, toolType:DocumentType.INK, funcs: { linearViewIsExpanded: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`}, scripts: { onClick: 'setInkToolDefaults()'} }, // Always available
+ { title: "Doc", icon: "Doc", toolTip: "Freeform Doc tools", subMenu: CurrentUserUtils.freeTools(), expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode, true)`, linearViewIsExpanded: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Always available
+ { title: "View", icon: "View", toolTip: "View tools", subMenu: CurrentUserUtils.viewTools(), expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearViewIsExpanded: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Always available
{ title: "Web", icon: "Web", toolTip: "Web functions", subMenu: CurrentUserUtils.webTools(), expertMode: false, toolType:DocumentType.WEB, funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearViewIsExpanded: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Only when Web is selected
- { title: "Schema", icon: "Schema", toolTip: "Schema functions", subMenu: CurrentUserUtils.schemaTools(), expertMode: false, toolType:CollectionViewType.Schema, funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearViewIsExpanded: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} } // Only when Schema is selected
+ { title: "Schema", icon: "Schema",linearBtnWidth:58,toolTip: "Schema functions", subMenu: CurrentUserUtils.schemaTools(), expertMode: false, toolType:CollectionViewType.Schema, funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearViewIsExpanded: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} } // Only when Schema is selected
];
}
@@ -684,10 +706,10 @@ export class CurrentUserUtils {
static setupContextMenuButton(params:Button, btnDoc?:Doc) {
const reqdOpts:DocumentOptions = {
...OmitKeys(params, ["scripts", "funcs", "subMenu"]).omit,
- backgroundColor: params.scripts?.onClick ? undefined: "transparent", /// a bit hacky. if an onClick is specified, then assume a toggle uses onClick to get the backgroundColor (see below). Otherwise, assume a transparent background
+ backgroundColor: params.backgroundColor ??"transparent", /// a bit hacky. if an onClick is specified, then assume a toggle uses onClick to get the backgroundColor (see below). Otherwise, assume a transparent background
color: Colors.WHITE, system: true, dontUndo: true,
_nativeWidth: params.width ?? 30, _width: params.width ?? 30,
- _height: 30, _nativeHeight: 30,
+ _height: 30, _nativeHeight: 30, linearBtnWidth: params.linearBtnWidth,
toolType: params.toolType, expertMode: params.expertMode,
_stayInCollection: true, _hideContextMenu: true, _lockedPosition: true,
_removeDropProperties: new List<string>([ "_stayInCollection"]),
diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts
index 203d4ad62..e116ae14b 100644
--- a/src/client/util/DictationManager.ts
+++ b/src/client/util/DictationManager.ts
@@ -324,16 +324,6 @@ export namespace DictationManager {
],
[
- 'open fields',
- {
- action: (target: DocumentView) => {
- const kvp = Docs.Create.KVPDocument(target.props.Document, { _width: 300, _height: 300 });
- target.props.addDocTab(kvp, OpenWhere.addRight);
- },
- },
- ],
-
- [
'new outline',
{
action: (target: DocumentView) => {
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index f2c554866..ccf370662 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -262,9 +262,11 @@ export class DocumentManager {
finished?: () => void
) => {
const docContextPath = DocumentManager.GetContextPath(targetDoc, true);
+ if (docContextPath.some(doc => doc.hidden)) options.toggleTarget = false;
let rootContextView = await new Promise<DocumentView>(res => {
const viewIndex = docContextPath.findIndex(doc => this.getDocumentView(doc));
if (viewIndex !== -1) return res(this.getDocumentView(docContextPath[viewIndex])!);
+ options.didMove = true;
docContextPath.some(doc => TabDocView.Activate(doc)) || MainView.addDocTabFunc(docContextPath[0], options.openLocation as OpenWhere);
this.AddViewRenderedCb(docContextPath[0], dv => res(dv));
});
@@ -299,7 +301,7 @@ export class DocumentManager {
PresBox.restoreTargetDocView(docView, viewSpec, options.zoomTime ?? 500);
Doc.linkFollowHighlight(docView.rootDoc, undefined, options.effect);
if (options.playAudio) DocumentManager.playAudioAnno(docView.rootDoc);
- if (options.toggleTarget) docView.rootDoc.hidden = !docView.rootDoc.hidden;
+ if (options.toggleTarget && (!options.didMove || docView.rootDoc.hidden)) docView.rootDoc.hidden = !docView.rootDoc.hidden;
if (options.effect) docView.rootDoc[AnimationSym] = options.effect;
if (options.zoomTextSelections && Doc.UnhighlightTimer && contextView && viewSpec.textHtml) {
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index a56f87075..7d2aa813f 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -1,6 +1,6 @@
import { action, observable, runInAction } from 'mobx';
import { DateField } from '../../fields/DateField';
-import { Doc, Field, Opt } from '../../fields/Doc';
+import { Doc, Field, Opt, StrListCast } from '../../fields/Doc';
import { List } from '../../fields/List';
import { PrefetchProxy } from '../../fields/Proxy';
import { listSpec } from '../../fields/Schema';
@@ -10,7 +10,9 @@ import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../fields/Types
import { emptyFunction, Utils } from '../../Utils';
import { Docs, DocUtils } from '../documents/Documents';
import * as globalCssVariables from '../views/global/globalCssVariables.scss';
+import { Colors } from '../views/global/globalEnums';
import { DocumentView } from '../views/nodes/DocumentView';
+import { ScriptingGlobals } from './ScriptingGlobals';
import { SnappingManager } from './SnappingManager';
import { UndoManager } from './UndoManager';
@@ -149,10 +151,14 @@ export namespace DragManager {
linkDragView: DocumentView;
}
export class ColumnDragData {
- constructor(colKey: SchemaHeaderField) {
- this.colKey = colKey;
+ // constructor(colKey: SchemaHeaderField) {
+ // this.colKey = colKey;
+ // }
+ // colKey: SchemaHeaderField;
+ constructor(colIndex: number) {
+ this.colIndex = colIndex;
}
- colKey: SchemaHeaderField;
+ colIndex: number;
}
// used by PDFs,Text,Image,Video,Web to conditionally (if the drop completes) create a text annotation when dragging the annotate button from the AnchorMenu when a text/region selection has been made.
// this is pretty clunky and should be rethought out using linkDrag or DocumentDrag
@@ -162,7 +168,6 @@ export namespace DragManager {
this.dropDocCreator = dropDocCreator;
this.offset = [0, 0];
}
- linkSourceDoc?: Doc;
dropDocCreator: (annotationOn: Doc | undefined) => Doc;
dropDocument?: Doc;
offset: number[];
@@ -201,24 +206,26 @@ export namespace DragManager {
dropEvent?.(); // glr: optional additional function to be called - in this case with presentation trails
if (docDragData && !docDragData.droppedDocuments.length) {
docDragData.dropAction = dragData.userDropAction || dragData.dropAction;
- docDragData.droppedDocuments = await Promise.all(
- dragData.draggedDocuments.map(async d =>
- !dragData.isDocDecorationMove && !dragData.userDropAction && ScriptCast(d.onDragStart)
- ? addAudioTag(ScriptCast(d.onDragStart).script.run({ this: d }).result)
- : docDragData.dropAction === 'alias'
- ? Doc.BestAlias(d)
- : docDragData.dropAction === 'proto'
- ? Doc.GetProto(d)
- : docDragData.dropAction === 'copy'
- ? (
- await Doc.MakeClone(d)
- ).clone
- : d
+ docDragData.droppedDocuments = (
+ await Promise.all(
+ dragData.draggedDocuments.map(async d =>
+ !dragData.isDocDecorationMove && !dragData.userDropAction && ScriptCast(d.onDragStart)
+ ? addAudioTag(ScriptCast(d.onDragStart).script.run({ this: d }).result)
+ : docDragData.dropAction === 'alias'
+ ? Doc.BestAlias(d)
+ : docDragData.dropAction === 'proto'
+ ? Doc.GetProto(d)
+ : docDragData.dropAction === 'copy'
+ ? (
+ await Doc.MakeClone(d)
+ ).clone
+ : d
+ )
)
- );
+ ).filter(d => d);
!['same', 'proto'].includes(docDragData.dropAction as any) &&
docDragData.droppedDocuments.forEach((drop: Doc, i: number) => {
- const dragProps = Cast(dragData.draggedDocuments[i].removeDropProperties, listSpec('string'), []);
+ const dragProps = StrListCast(dragData.draggedDocuments[i].removeDropProperties);
const remProps = (dragData?.removeDropProperties || []).concat(Array.from(dragProps));
remProps.map(prop => (drop[prop] = undefined));
});
@@ -256,8 +263,8 @@ export namespace DragManager {
}
// drags a column from a schema view
- export function StartColumnDrag(ele: HTMLElement, dragData: ColumnDragData, downX: number, downY: number, options?: DragOptions) {
- StartDrag([ele], dragData, downX, downY, options);
+ export function StartColumnDrag(ele: HTMLElement[], dragData: ColumnDragData, downX: number, downY: number, options?: DragOptions) {
+ StartDrag(ele, dragData, downX, downY, options);
}
export function SetSnapLines(horizLines: number[], vertLines: number[]) {
@@ -590,3 +597,8 @@ export namespace DragManager {
endDrag?.();
}
}
+
+ScriptingGlobals.add(function toggleRaiseOnDrag(readOnly?: boolean) {
+ if (readOnly) return DragManager.GetRaiseWhenDragged() ? Colors.MEDIUM_BLUE : 'transparent';
+ DragManager.SetRaiseWhenDragged(!DragManager.GetRaiseWhenDragged());
+});
diff --git a/src/client/util/DropConverter.ts b/src/client/util/DropConverter.ts
index 7c209d1e0..2e1d6ba23 100644
--- a/src/client/util/DropConverter.ts
+++ b/src/client/util/DropConverter.ts
@@ -33,15 +33,7 @@ function makeTemplate(doc: Doc, first: boolean = true, rename: Opt<string> = und
let any = false;
docs.forEach(d => {
if (!StrCast(d.title).startsWith('-')) {
- const params = StrCast(d.title)
- .match(/\(([a-zA-Z0-9._\-]*)\)/)?.[1]
- .replace('()', '');
- if (params) {
- any = makeTemplate(d, false) || any;
- d.PARAMS = params;
- } else {
- any = Doc.MakeMetadataFieldTemplate(d, Doc.GetProto(layoutDoc)) || any;
- }
+ any = Doc.MakeMetadataFieldTemplate(d, Doc.GetProto(layoutDoc)) || any;
} else if (d.type === DocumentType.COL || d.data instanceof RichTextField) {
any = makeTemplate(d, false) || any;
}
diff --git a/src/client/util/LinkFollower.ts b/src/client/util/LinkFollower.ts
index eacbcc0e3..d4d7c66f5 100644
--- a/src/client/util/LinkFollower.ts
+++ b/src/client/util/LinkFollower.ts
@@ -1,16 +1,15 @@
-import { action, runInAction } from 'mobx';
-import { Doc, DocListCast, Opt } from '../../fields/Doc';
-import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../fields/Types';
+import { action, observable, runInAction } from 'mobx';
+import { Doc, DocListCast, Field, FieldResult, Opt } from '../../fields/Doc';
+import { ScriptField } from '../../fields/ScriptField';
+import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../fields/Types';
import { DocumentType } from '../documents/DocumentTypes';
-import { DocumentDecorations } from '../views/DocumentDecorations';
-import { DocFocusOptions, DocumentViewSharedProps, OpenWhere } from '../views/nodes/DocumentView';
+import { DocFocusOptions, OpenWhere } from '../views/nodes/DocumentView';
import { PresBox } from '../views/nodes/trails';
import { DocumentManager } from './DocumentManager';
import { LinkManager } from './LinkManager';
+import { ScriptingGlobals } from './ScriptingGlobals';
import { SelectionManager } from './SelectionManager';
import { UndoManager } from './UndoManager';
-
-type CreateViewFunc = (doc: Doc, followLinkLocation: string, finished?: () => void) => void;
/*
* link doc:
* - anchor1: doc
@@ -24,18 +23,19 @@ type CreateViewFunc = (doc: Doc, followLinkLocation: string, finished?: () => vo
* - user defined kvps
*/
export class LinkFollower {
+ @observable public static IsFollowing = false;
// follows a link - if the target is on screen, it highlights/pans to it.
// if the target isn't onscreen, then it will open up the target in the lightbox, or in place
// depending on the followLinkLocation property of the source (or the link itself as a fallback);
- public static FollowLink = (linkDoc: Opt<Doc>, sourceDoc: Doc, docViewProps: DocumentViewSharedProps, altKey: boolean) => {
+ public static FollowLink = (linkDoc: Opt<Doc>, sourceDoc: Doc, altKey: boolean) => {
const batch = UndoManager.StartBatch('follow link click');
- runInAction(() => (DocumentDecorations.Instance.overrideBounds = true)); // turn off decoration bounds while following links since animations may occur, and DocDecorations is based on screenToLocal which is not always an observable value
+ runInAction(() => (LinkFollower.IsFollowing = true)); // turn off decoration bounds while following links since animations may occur, and DocDecorations is based on screenToLocal which is not always an observable value
LinkFollower.traverseLink(
linkDoc,
sourceDoc,
action(() => {
batch.end();
- Doc.AddUnHighlightWatcher(action(() => (DocumentDecorations.Instance.overrideBounds = false)));
+ Doc.AddUnHighlightWatcher(action(() => (LinkFollower.IsFollowing = false)));
}),
altKey ? true : undefined
);
@@ -120,3 +120,15 @@ export class LinkFollower {
});
}
}
+
+ScriptingGlobals.add(function followLink(doc: Doc, altKey: boolean) {
+ SelectionManager.DeselectAll();
+ LinkFollower.FollowLink(undefined, doc, altKey);
+});
+
+export function FollowLinkScript() {
+ return ScriptField.MakeScript('followLink(this,altKey)', { altKey: 'boolean' });
+}
+export function IsFollowLinkScript(field: FieldResult<Field>) {
+ return ScriptCast(field)?.script.originalScript.includes('followLink(');
+}
diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts
index d32298c83..f17a98616 100644
--- a/src/client/util/Scripting.ts
+++ b/src/client/util/Scripting.ts
@@ -7,7 +7,9 @@
import * as typescriptlib from '!!raw-loader!./type_decls.d';
import * as ts from 'typescript';
import { Doc, Field } from '../../fields/Doc';
+import { ToScriptString } from '../../fields/FieldSymbols';
import { ObjectField } from '../../fields/ObjectField';
+import { RefField } from '../../fields/RefField';
import { ScriptField } from '../../fields/ScriptField';
import { scriptingGlobals, ScriptingGlobals } from './ScriptingGlobals';
export { ts };
@@ -180,7 +182,11 @@ function forEachNode(node: ts.Node, onEnter: Traverser, onExit?: Traverser, inde
export function CompileScript(script: string, options: ScriptOptions = {}): CompileResult {
const captured = options.capturedVariables ?? {};
- const signature = Object.keys(captured).reduce((p, v) => p + `${v}=${captured[v] instanceof ObjectField ? 'XXX' : captured[v].toString()}`, '');
+ const signature = Object.keys(captured).reduce((p, v) => {
+ const formatCapture = (obj: any) => `${v}=${obj instanceof RefField ? 'XXX' : obj.toString()}`;
+ if (captured[v] instanceof Array) return p + (captured[v] as any).map(formatCapture);
+ return p + formatCapture(captured[v]);
+ }, '');
const found = ScriptField.GetScriptFieldCache(script + ':' + signature);
if (found) return found as CompiledScript;
const { requiredType = '', addReturn = false, params = {}, capturedVariables = {}, typecheck = true } = options;
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 0f4f77588..313c255a0 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -1,3 +1,4 @@
+import { ModalManager } from '@material-ui/core';
import { action, observable, ObservableMap } from 'mobx';
import { computedFn } from 'mobx-utils';
import { Doc, Opt } from '../../fields/Doc';
@@ -10,7 +11,8 @@ import { ScriptingGlobals } from './ScriptingGlobals';
export namespace SelectionManager {
class Manager {
@observable IsDragging: boolean = false;
- SelectedViews: ObservableMap<DocumentView, Doc> = new ObservableMap();
+ SelectedViewsMap: ObservableMap<DocumentView, Doc> = new ObservableMap();
+ @observable SelectedViews: DocumentView[] = [];
@observable SelectedSchemaDocument: Doc | undefined;
@action
@@ -20,7 +22,7 @@ export namespace SelectionManager {
@action
SelectView(docView: DocumentView, ctrlPressed: boolean): void {
// if doc is not in SelectedDocuments, add it
- if (!manager.SelectedViews.get(docView) && docView.props.Document.type !== DocumentType.MARKER) {
+ if (!manager.SelectedViewsMap.get(docView) && docView.props.Document.type !== DocumentType.MARKER) {
if (!ctrlPressed) {
if (LinkManager.currentLink && !LinkManager.Links(docView.rootDoc).includes(LinkManager.currentLink) && docView.rootDoc !== LinkManager.currentLink) {
LinkManager.currentLink = undefined;
@@ -28,33 +30,38 @@ export namespace SelectionManager {
this.DeselectAll();
}
- manager.SelectedViews.set(docView, docView.rootDoc);
+ manager.SelectedViews.push(docView);
+ manager.SelectedViewsMap.set(docView, docView.rootDoc);
docView.props.whenChildContentsActiveChanged(true);
- } else if (!ctrlPressed && (Array.from(manager.SelectedViews.entries()).length > 1 || manager.SelectedSchemaDocument)) {
- Array.from(manager.SelectedViews.keys()).map(dv => dv !== docView && dv.props.whenChildContentsActiveChanged(false));
+ } else if (!ctrlPressed && (Array.from(manager.SelectedViewsMap.entries()).length > 1 || manager.SelectedSchemaDocument)) {
+ Array.from(manager.SelectedViewsMap.keys()).map(dv => dv !== docView && dv.props.whenChildContentsActiveChanged(false));
manager.SelectedSchemaDocument = undefined;
- manager.SelectedViews.clear();
- manager.SelectedViews.set(docView, docView.rootDoc);
+ manager.SelectedViews.length = 0;
+ manager.SelectedViewsMap.clear();
+ manager.SelectedViews.push(docView);
+ manager.SelectedViewsMap.set(docView, docView.rootDoc);
}
}
@action
- DeselectView(docView: DocumentView): void {
- if (manager.SelectedViews.get(docView)) {
- manager.SelectedViews.delete(docView);
+ DeselectView(docView?: DocumentView): void {
+ if (docView && manager.SelectedViewsMap.get(docView)) {
+ manager.SelectedViewsMap.delete(docView);
+ manager.SelectedViews.splice(manager.SelectedViews.indexOf(docView), 1);
docView.props.whenChildContentsActiveChanged(false);
}
}
@action
DeselectAll(): void {
manager.SelectedSchemaDocument = undefined;
- Array.from(manager.SelectedViews.keys()).forEach(dv => dv.props.whenChildContentsActiveChanged(false));
- manager.SelectedViews.clear();
+ Array.from(manager.SelectedViewsMap.keys()).forEach(dv => dv.props.whenChildContentsActiveChanged(false));
+ manager.SelectedViewsMap.clear();
+ manager.SelectedViews.length = 0;
}
}
const manager = new Manager();
- export function DeselectView(docView: DocumentView): void {
+ export function DeselectView(docView?: DocumentView): void {
manager.DeselectView(docView);
}
export function SelectView(docView: DocumentView, ctrlPressed: boolean): void {
@@ -67,7 +74,7 @@ export namespace SelectionManager {
const IsSelectedCache = computedFn(function isSelected(doc: DocumentView) {
// wrapping get() in a computedFn only generates mobx() invalidations when the return value of the function for the specific get parameters has changed
- return manager.SelectedViews.get(doc) ? true : false;
+ return manager.SelectedViewsMap.get(doc) ? true : false;
});
// computed functions, such as used in IsSelected generate errors if they're called outside of a
// reaction context. Specifying the context with 'outsideReaction' allows an efficiency feature
@@ -76,7 +83,7 @@ export namespace SelectionManager {
return !doc
? false
: outsideReaction
- ? manager.SelectedViews.get(doc)
+ ? manager.SelectedViewsMap.get(doc)
? true
: false // get() accesses a hashtable -- setting anything in the hashtable generates a mobx invalidation for every get()
: IsSelectedCache(doc);
@@ -85,7 +92,7 @@ export namespace SelectionManager {
export function DeselectAll(except?: Doc): void {
let found: DocumentView | undefined = undefined;
if (except) {
- for (const view of Array.from(manager.SelectedViews.keys())) {
+ for (const view of Array.from(manager.SelectedViewsMap.keys())) {
if (view.props.Document === except) found = view;
}
}
@@ -95,13 +102,15 @@ export namespace SelectionManager {
}
export function Views(): Array<DocumentView> {
- return Array.from(manager.SelectedViews.keys()); //.filter(dv => manager.SelectedViews.get(dv)?._viewType !== CollectionViewType.Docking);
+ return manager.SelectedViews;
+ // Array.from(manager.SelectedViewsMap.keys()); //.filter(dv => manager.SelectedViews.get(dv)?._viewType !== CollectionViewType.Docking);
}
export function SelectedSchemaDoc(): Doc | undefined {
return manager.SelectedSchemaDocument;
}
export function Docs(): Doc[] {
- return Array.from(manager.SelectedViews.values()).filter(doc => doc?._viewType !== CollectionViewType.Docking);
+ return manager.SelectedViews.map(dv => dv.rootDoc).filter(doc => doc?._viewType !== CollectionViewType.Docking);
+ // Array.from(manager.SelectedViewsMap.values()).filter(doc => doc?._viewType !== CollectionViewType.Docking);
}
}
ScriptingGlobals.add(function SelectionManager_selectedDocType(type: string, expertMode: boolean, checkContext?: boolean) {
diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx
index 6c823e80a..396d754b6 100644
--- a/src/client/util/SettingsManager.tsx
+++ b/src/client/util/SettingsManager.tsx
@@ -184,10 +184,6 @@ export class SettingsManager extends React.Component<{}> {
<div className="preferences-check">Show full toolbar</div>
</div>
<div>
- <input type="checkbox" onChange={e => DragManager.SetRaiseWhenDragged(!DragManager.GetRaiseWhenDragged())} checked={DragManager.GetRaiseWhenDragged()} />
- <div className="preferences-check">Raise on drag</div>
- </div>
- <div>
<input type="checkbox" onChange={e => FontIconBox.SetShowLabels(!FontIconBox.GetShowLabels())} checked={FontIconBox.GetShowLabels()} />
<div className="preferences-check">Show button labels</div>
</div>