import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@material-ui/core'; import { action, computed, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { ColorState, SketchPicker } from 'react-color'; import { Doc, HeightSym, StrListCast, WidthSym } from '../../../../fields/Doc'; import { InkTool } from '../../../../fields/InkField'; import { createSchema } from '../../../../fields/Schema'; import { ScriptField } from '../../../../fields/ScriptField'; import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types'; import { WebField } from '../../../../fields/URLField'; import { aggregateBounds, Utils } from '../../../../Utils'; import { DocumentType } from '../../../documents/DocumentTypes'; import { CurrentUserUtils } from '../../../util/CurrentUserUtils'; import { ScriptingGlobals } from "../../../util/ScriptingGlobals"; import { SelectionManager } from '../../../util/SelectionManager'; import { undoBatch, UndoManager } from '../../../util/UndoManager'; import { CollectionFreeFormView } from '../../collections/collectionFreeForm'; import { CollectionViewType } from '../../collections/CollectionView'; import { ContextMenu } from '../../ContextMenu'; import { DocComponent } from '../../DocComponent'; import { EditableView } from '../../EditableView'; import { GestureOverlay } from '../../GestureOverlay'; import { Colors } from '../../global/globalEnums'; import { ActiveFillColor, ActiveInkColor, ActiveInkWidth, SetActiveFillColor, SetActiveInkColor, SetActiveInkWidth } from '../../InkingStroke'; import { InkTranscription } from '../../InkTranscription'; import { StyleProp } from '../../StyleProvider'; import { FieldView, FieldViewProps } from '.././FieldView'; import { RichTextMenu } from '../formattedText/RichTextMenu'; import { WebBox } from '../WebBox'; import { FontIconBadge } from './FontIconBadge'; import './FontIconBox.scss'; const FontIconSchema = createSchema({ icon: "string", }); export enum ButtonType { TextButton = "textBtn", MenuButton = "menuBtn", DropdownList = "drpdownList", DropdownButton = "drpdownBtn", ClickButton = "clickBtn", DoubleButton = "dblBtn", ToggleButton = "tglBtn", ColorButton = "colorBtn", ToolButton = "toolBtn", NumberButton = "numBtn", EditableText = "editableText" } export enum NumButtonType { Slider = "slider", DropdownOptions = "list", Inline = "inline" } export interface ButtonProps extends FieldViewProps { type?: ButtonType; } @observer export class FontIconBox extends DocComponent() { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(FontIconBox, fieldKey); } showTemplate = (): void => { const dragFactory = Cast(this.layoutDoc.dragFactory, Doc, null); dragFactory && this.props.addDocTab(dragFactory, "add:right"); } dragAsTemplate = (): void => { this.layoutDoc.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)'); }; useAsPrototype = (): void => { this.layoutDoc.onDragStart = ScriptField.MakeFunction('makeDelegate(this.dragFactory, true)'); }; specificContextMenu = (): void => { if (!Doc.UserDoc().noviceMode) { const cm = ContextMenu.Instance; cm.addItem({ description: "Show Template", event: this.showTemplate, icon: "tag" }); cm.addItem({ description: "Use as Render Template", event: this.dragAsTemplate, icon: "tag" }); cm.addItem({ description: "Use as Prototype", event: this.useAsPrototype, icon: "tag" }); } } // Determining UI Specs @observable private label = StrCast(this.rootDoc.label, StrCast(this.rootDoc.title)); @observable private icon = StrCast(this.dataDoc.icon, "user") as any; @observable private dropdown: boolean = BoolCast(this.rootDoc.dropDownOpen); @observable private buttonList: string[] = StrListCast(this.rootDoc.btnList); @observable private type = StrCast(this.rootDoc.btnType); /** * Types of buttons in dash: * - Main menu button (LHS) * - Tool button * - Expandable button (CollectionLinearView) * - Button inside of CollectionLinearView vs. outside of CollectionLinearView * - Action button * - Dropdown button * - Color button * - Dropdown list * - Number button **/ _batch: UndoManager.Batch | undefined = undefined; /** * Number button */ @computed get numberButton() { const numBtnType: string = StrCast(this.rootDoc.numBtnType); const numScript = ScriptCast(this.rootDoc.script); const setValue = (value: number) => numScript?.script.run({ value, _readOnly_: false }); // Script for checking the outcome of the toggle const checkResult: number = numScript?.script.run({ value: 0, _readOnly_: true }).result || 0; if (numBtnType === NumButtonType.Slider) { const dropdown =
e.stopPropagation()} > this._batch = UndoManager.StartBatch("presDuration")} onPointerUp={() => this._batch?.end()} onChange={e => { e.stopPropagation(); setValue(Number(e.target.value)); }} />
; return (
this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen)} > {checkResult} {this.rootDoc.dropDownOpen ? dropdown : null}
); } else if (numBtnType === NumButtonType.DropdownOptions) { const items: number[] = []; for (let i = 0; i < 100; i++) { if (i % 2 === 0) { items.push(i); } } const list = items.map((value) => { return
setValue(value)}> {value}
; }); return (
setValue(Number(checkResult) - 1))}>
{ e.stopPropagation(); e.preventDefault(); }} onClick={action(() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen)} > setValue(Number(e.target.value)))} />
setValue(Number(checkResult) + 1))}>
{this.rootDoc.dropDownOpen ?
{list}
{ e.stopPropagation(); this.rootDoc.dropDownOpen = false; }} />
: null}
); } else { return (
); } } /** * Dropdown button */ @computed get dropdownButton() { const active: string = StrCast(this.rootDoc.dropDownOpen); const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color); const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor); return (
this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen)}> {!this.label || !Doc.UserDoc()._showLabel ? (null) :
{this.label}
}
{this.rootDoc.dropDownOpen ?
{/* DROPDOWN BOX CONTENTS */}
: null}
); } /** * Dropdown list */ @computed get dropdownListButton() { const active: string = StrCast(this.rootDoc.dropDownOpen); const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color); const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor); const script = ScriptCast(this.rootDoc.script); let noviceList: string[] = []; let text: string | undefined; let dropdown = true; let icon: IconProp = "caret-down"; try { if (script.script.originalScript.startsWith('setView')) { const selected = SelectionManager.Docs().lastElement(); if (selected) { if (StrCast(selected.type) === DocumentType.COL) { text = StrCast(selected._viewType); } else { dropdown = false; text = selected.type === DocumentType.RTF ? "Text" : StrCast(selected.type); icon = Doc.toIcon(selected); } } else { dropdown = false; icon = "globe-asia"; text = "User Default"; } noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Stacking]; } else if (script.script.originalScript.startsWith('setFont')) { const editorView = RichTextMenu.Instance?.TextView?.EditorView; text = StrCast((editorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily); noviceList = ["Roboto", "Times New Roman", "Arial", "Georgia", "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"]; } } catch (e) { console.log(e); } // Get items to place into the list const list = this.buttonList.map((value) => { if (Doc.UserDoc().noviceMode && !noviceList.includes(value)) { return; } return
script.script.run({ value }).result}> {value[0].toUpperCase() + value.slice(1)}
; }); const label = !this.label || !Doc.UserDoc()._showLabel ? (null) :
{this.label}
; return (
this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen : undefined}> {dropdown ? (null) : }
{text && text[0].toUpperCase() + text.slice(1)}
{label} {!dropdown ? (null) :
} {this.rootDoc.dropDownOpen ?
{list}
{ e.stopPropagation(); this.rootDoc.dropDownOpen = false; }} />
: null}
); } @observable colorPickerClosed: boolean = true; @computed get colorScript() { return ScriptCast(this.rootDoc.script); } colorPicker = (curColor: string) => { const change = (value: ColorState) => { const s = this.colorScript; s && undoBatch(() => s.script.run({ value: Utils.colorString(value), _readOnly_: false }).result)(); }; const presets = ['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', '#FFFFFF', '#f1efeb', "transparent"]; return ; } /** * Color button */ @computed get colorButton() { const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color); const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor); const curColor = this.colorScript?.script.run({ value: undefined, _readOnly_: true }).result ?? "transparent"; const label = !this.label || !Doc.UserDoc()._showLabel ? (null) :
{this.label}
; const dropdownCaret =
; setTimeout(() => this.colorPicker(curColor)); // cause an update to the color picker rendered in MainView return (
this.colorPickerClosed = !this.colorPickerClosed)} onPointerDown={e => e.stopPropagation()}>
{label} {/* {dropdownCaret} */} {this.colorPickerClosed ? (null) :
e.stopPropagation()} onClick={e => e.stopPropagation()}> {this.colorPicker(curColor)}
{ e.stopPropagation(); this.colorPickerClosed = true; })} />
}
); } @computed get toggleButton() { // Determine the type of toggle button const switchToggle: boolean = BoolCast(this.rootDoc.switchToggle); const buttonText: string = StrCast(this.rootDoc.buttonText); // Colors const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color); const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor); // Button label const label = !this.label || !Doc.UserDoc()._showLabel ? (null) :
{this.label}
; if (switchToggle) { return (
{buttonText ? buttonText : null}
); } else { return (
{label}
); } } /** * Default */ @computed get defaultButton() { const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color); const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor); const active: string = StrCast(this.rootDoc.dropDownOpen); return (
{!this.label || !Doc.UserDoc()._showLabel ? (null) :
{this.label}
}
); } @computed get editableText() { // Script for running the toggle const script = ScriptCast(this.rootDoc.script); // Function to run the script const checkResult = script?.script.run({ value: "", _readOnly_: true }).result; const setValue = (value: string, shiftDown?: boolean): boolean => script?.script.run({ value, _readOnly_: false }).result; return (
script?.script.run({ value: "", _readOnly_: true }).result} SetValue={setValue} contents={checkResult} />
); } render() { const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color); const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor); const label = !this.label || !Doc.UserDoc()._showLabel ? (null) :
{this.label}
; const menuLabel = !this.label || !Doc.UserDoc()._showMenuLabel ? (null) :
{this.label}
; const buttonText = StrCast(this.rootDoc.buttonText); // TODO:glr Add label of button type let button = this.defaultButton; switch (this.type) { case ButtonType.TextButton: button = (
{buttonText ?
{buttonText}
: null} {label}
); // button = break; case ButtonType.EditableText: button = this.editableText; break; case ButtonType.NumberButton: button = this.numberButton; break; case ButtonType.DropdownButton: button = this.dropdownButton; break; case ButtonType.DropdownList: button = this.dropdownListButton; break; case ButtonType.ColorButton: button = this.colorButton; break; case ButtonType.ToolButton: button = (
{label}
); break; case ButtonType.ToggleButton: button = this.toggleButton; // button = break; case ButtonType.ClickButton: button = (
{label}
); break; case ButtonType.MenuButton: const trailsIcon = ; button = (
{this.icon === "pres-trail" ? trailsIcon : } {menuLabel}
); break; default: break; } return !this.layoutDoc.toolTip || this.type === ButtonType.DropdownList || this.type === ButtonType.ColorButton || this.type === ButtonType.NumberButton || this.type === ButtonType.EditableText ? button : {StrCast(this.layoutDoc.toolTip)}
}> {button} ; } } // toggle: Set overlay status of selected document ScriptingGlobals.add(function setView(view: string) { const selected = SelectionManager.Docs().lastElement(); selected ? selected._viewType = view : console.log("[FontIconBox.tsx] changeView failed"); }); // toggle: Set overlay status of selected document ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: boolean) { const selected = SelectionManager.Docs().lastElement(); if (checkResult) { return selected?._backgroundColor ?? "transparent"; } if (selected) selected._backgroundColor = color; }); // toggle: Set overlay status of selected document ScriptingGlobals.add(function setHeaderColor(color?: string, checkResult?: boolean) { if (checkResult) { return Doc.SharingDoc().userColor; } Doc.SharingDoc().userColor = undefined; Doc.GetProto(Doc.SharingDoc()).userColor = color; Doc.UserDoc().showTitle = color === "transparent" ? undefined : StrCast(Doc.UserDoc().showTitle, "creationDate"); }); // toggle: Set overlay status of selected document ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) { const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined; if (checkResult && selected) { if (NumCast(selected.Document.z) >= 1) return Colors.MEDIUM_BLUE; return "transparent"; } selected ? selected.props.CollectionFreeFormDocumentView?.().float() : console.log("[FontIconBox.tsx] toggleOverlay failed"); }); /** TEXT * setFont * setFontSize * toggleBold * toggleUnderline * toggleItalic * setAlignment * toggleBold * toggleItalic * toggleUnderline **/ // toggle: Set overlay status of selected document ScriptingGlobals.add(function setFont(font: string, checkResult?: boolean) { SelectionManager.Docs().map(doc => doc._fontFamily = font); const editorView = RichTextMenu.Instance.TextView?.EditorView; if (checkResult) { return StrCast((editorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily); } if (editorView) RichTextMenu.Instance.setFontFamily(font); else Doc.UserDoc().fontFamily = font; }); ScriptingGlobals.add(function getActiveTextInfo(info: "family" | "size" | "color" | "highlight") { const editorView = RichTextMenu.Instance.TextView?.EditorView; const style = editorView?.state && RichTextMenu.Instance.getActiveFontStylesOnSelection(); switch (info) { case "family": return style?.activeFamilies[0]; case "size": return style?.activeSizes[0]; case "color": return style?.activeColors[0]; case "highlight": return style?.activeHighlights[0]; } }); ScriptingGlobals.add(function setAlignment(align: "left" | "right" | "center", checkResult?: boolean) { const editorView = RichTextMenu.Instance?.TextView?.EditorView; if (checkResult) { return (editorView ? RichTextMenu.Instance.textAlign : Doc.UserDoc().textAlign) === align ? Colors.MEDIUM_BLUE : "transparent"; } if (editorView?.state) RichTextMenu.Instance.align(editorView, editorView.dispatch, align); else Doc.UserDoc().textAlign = align; }); ScriptingGlobals.add(function setBulletList(mapStyle: "bullet" | "decimal", checkResult?: boolean) { const editorView = RichTextMenu.Instance?.TextView?.EditorView; if (checkResult) { const active = editorView?.state && RichTextMenu.Instance.getActiveListStyle(); if (active === mapStyle) return Colors.MEDIUM_BLUE; return "transparent"; } if (editorView) { const active = editorView?.state && RichTextMenu.Instance.getActiveListStyle(); editorView?.state && RichTextMenu.Instance.changeListType( editorView.state.schema.nodes.ordered_list.create({ mapStyle: active === mapStyle ? "" : mapStyle })); } }); // toggle: Set overlay status of selected document ScriptingGlobals.add(function setFontColor(color?: string, checkResult?: boolean) { const editorView = RichTextMenu.Instance?.TextView?.EditorView; if (checkResult) { return editorView ? RichTextMenu.Instance.fontColor : Doc.UserDoc().fontColor; } if (editorView) color && RichTextMenu.Instance.setColor(color, editorView, editorView?.dispatch); else Doc.UserDoc().fontColor = color; }); // toggle: Set overlay status of selected document ScriptingGlobals.add(function setFontHighlight(color?: string, checkResult?: boolean) { const selected = SelectionManager.Docs().lastElement(); const editorView = RichTextMenu.Instance.TextView?.EditorView; if (checkResult) { return (selected ?? Doc.UserDoc())._fontHighlight; } if (selected) { selected._fontColor = color; if (color) { editorView?.state && RichTextMenu.Instance.setHighlight(color, editorView, editorView?.dispatch); } } Doc.UserDoc()._fontHighlight = color; }); // toggle: Set overlay status of selected document ScriptingGlobals.add(function setFontSize(size: string | number, checkResult?: boolean) { const editorView = RichTextMenu.Instance?.TextView?.EditorView; if (checkResult) { return (editorView ? RichTextMenu.Instance.fontSize : StrCast(Doc.UserDoc().fontSize, "10px")).replace("px", ""); } if (typeof size === "number") size = size.toString(); if (size && Number(size).toString() === size) size += "px"; if (editorView) RichTextMenu.Instance.setFontSize(size); else Doc.UserDoc()._fontSize = size; }); ScriptingGlobals.add(function toggleBold(checkResult?: boolean) { const editorView = RichTextMenu.Instance?.TextView?.EditorView; if (checkResult) { return (editorView ? RichTextMenu.Instance.bold : Doc.UserDoc().fontWeight === "bold") ? Colors.MEDIUM_BLUE : "transparent"; } if (editorView) RichTextMenu.Instance?.toggleBold(); else Doc.UserDoc().fontWeight = Doc.UserDoc().fontWeight === "bold" ? undefined : "bold"; }); ScriptingGlobals.add(function toggleUnderline(checkResult?: boolean) { const editorView = RichTextMenu.Instance?.TextView?.EditorView; if (checkResult) { return (editorView ? RichTextMenu.Instance.underline : Doc.UserDoc().textDecoration === "underline") ? Colors.MEDIUM_BLUE : "transparent"; } if (editorView) RichTextMenu.Instance?.toggleUnderline(); else Doc.UserDoc().textDecoration = Doc.UserDoc().textDecoration === "underline" ? undefined : "underline"; }); ScriptingGlobals.add(function toggleItalic(checkResult?: boolean) { const editorView = RichTextMenu.Instance?.TextView?.EditorView; if (checkResult) { return (editorView ? RichTextMenu.Instance.italics : Doc.UserDoc().fontStyle === "italics") ? Colors.MEDIUM_BLUE : "transparent"; } if (editorView) RichTextMenu.Instance?.toggleItalics(); else Doc.UserDoc().fontStyle = Doc.UserDoc().fontStyle === "italics" ? undefined : "italics"; }); export function checkInksToGroup() { // console.log("getting here to inks group"); if (CurrentUserUtils.SelectedTool === InkTool.Write) { CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => { // TODO: nda - will probably want to go through ffView unprocessed docs and then see if any of the inksToGroup docs are in it and only use those // find all inkDocs in ffView.unprocessedDocs that are within 200 pixels of each other const inksToGroup = ffView.unprocessedDocs.filter(inkDoc => { // console.log(inkDoc.x, inkDoc.y); }); }); } } export function createInkGroup(inksToGroup?: Doc[], isSubGroup?: boolean) { // TODO nda - if document being added to is a inkGrouping then we can just add to that group if (CurrentUserUtils.SelectedTool === InkTool.Write) { CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => { // TODO: nda - will probably want to go through ffView unprocessed docs and then see if any of the inksToGroup docs are in it and only use those const selected = ffView.unprocessedDocs; // loop through selected an get the bound const bounds: { x: number, y: number, width?: number, height?: number }[] = [] selected.map(action(d => { const x = NumCast(d.x); const y = NumCast(d.y); const width = d[WidthSym](); const height = d[HeightSym](); bounds.push({ x, y, width, height }); })) const aggregBounds = aggregateBounds(bounds, 0, 0); const marqViewRef = ffView._marqueeViewRef.current; // set the vals for bounds in marqueeView if (marqViewRef) { marqViewRef._downX = aggregBounds.x; marqViewRef._downY = aggregBounds.y; marqViewRef._lastX = aggregBounds.r; marqViewRef._lastY = aggregBounds.b; } selected.map(action(d => { const dx = NumCast(d.x); const dy = NumCast(d.y); delete d.x; delete d.y; delete d.activeFrame; delete d._timecodeToShow; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection delete d._timecodeToHide; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection // calculate pos based on bounds if (marqViewRef?.Bounds) { d.x = dx - marqViewRef.Bounds.left - marqViewRef.Bounds.width / 2; d.y = dy - marqViewRef.Bounds.top - marqViewRef.Bounds.height / 2; } return d; })); ffView.props.removeDocument?.(selected); // TODO: nda - this is the code to actually get a new grouped collection const newCollection = marqViewRef?.getCollection(selected, undefined, [], true); if (newCollection) { newCollection.height = newCollection[HeightSym](); newCollection.width = newCollection[WidthSym](); } // nda - bug: when deleting a stroke before leaving writing mode, delete the stroke from unprocessed ink docs newCollection && ffView.props.addDocument?.(newCollection); // TODO: nda - will probably need to go through and only remove the unprocessed selected docs ffView.unprocessedDocs = []; InkTranscription.Instance.transcribeInk(newCollection, selected, false, ffView); }); } CollectionFreeFormView.collectionsWithUnprocessedInk.clear(); } /** INK * setActiveInkTool * setStrokeWidth * setStrokeColor **/ ScriptingGlobals.add(function setActiveInkTool(tool: string, checkResult?: boolean) { createInkGroup(); if (checkResult) { return ((Doc.UserDoc().activeInkTool === tool && !GestureOverlay.Instance?.InkShape) || GestureOverlay.Instance?.InkShape === tool) ? Colors.MEDIUM_BLUE : "transparent"; } if (["circle", "square", "line"].includes(tool)) { if (GestureOverlay.Instance.InkShape === tool) { Doc.UserDoc().activeInkTool = InkTool.None; GestureOverlay.Instance.InkShape = InkTool.None; } else { Doc.UserDoc().activeInkTool = InkTool.Pen; GestureOverlay.Instance.InkShape = tool; } } else if (tool) { // pen or eraser if (Doc.UserDoc().activeInkTool === tool && !GestureOverlay.Instance.InkShape) { Doc.UserDoc().activeInkTool = InkTool.None; } else if (tool == "write") { // console.log("write mode selected - create groupDoc here!", tool) Doc.UserDoc().activeInkTool = tool; GestureOverlay.Instance.InkShape = ""; } else { Doc.UserDoc().activeInkTool = tool; GestureOverlay.Instance.InkShape = ""; } } else { Doc.UserDoc().activeInkTool = InkTool.None; } }); // toggle: Set overlay status of selected document ScriptingGlobals.add(function setFillColor(color?: string, checkResult?: boolean) { const selected = SelectionManager.Docs().lastElement(); if (checkResult) { if (selected?.type === DocumentType.INK) { return StrCast(selected.fillColor); } return ActiveFillColor(); } SetActiveFillColor(StrCast(color)); SelectionManager.Docs().filter(doc => doc.type === DocumentType.INK).map(doc => doc.fillColor = color); }); ScriptingGlobals.add(function setStrokeWidth(width: number, checkResult?: boolean) { if (checkResult) { const selected = SelectionManager.Docs().lastElement(); if (selected?.type === DocumentType.INK) { return NumCast(selected.strokeWidth); } return ActiveInkWidth(); } SetActiveInkWidth(width.toString()); SelectionManager.Docs().filter(doc => doc.type === DocumentType.INK).map(doc => doc.strokeWidth = Number(width)); }); // toggle: Set overlay status of selected document ScriptingGlobals.add(function setStrokeColor(color?: string, checkResult?: boolean) { if (checkResult) { const selected = SelectionManager.Docs().lastElement(); if (selected?.type === DocumentType.INK) { return StrCast(selected.color); } return ActiveInkColor(); } SetActiveInkColor(StrCast(color)); SelectionManager.Docs().filter(doc => doc.type === DocumentType.INK).map(doc => doc.color = String(color)); }); /** WEB * webSetURL **/ ScriptingGlobals.add(function webSetURL(url: string, checkResult?: boolean) { const selected = SelectionManager.Views().lastElement(); if (selected?.rootDoc.type === DocumentType.WEB) { if (checkResult) { return StrCast(selected.rootDoc.data, Cast(selected.rootDoc.data, WebField, null)?.url?.href); } (selected.ComponentView as WebBox).submitURL(url); //selected.rootDoc.data = new WebField(url); } }); ScriptingGlobals.add(function webForward(checkResult?: boolean) { const selected = (SelectionManager.Views().lastElement()?.ComponentView as WebBox); if (checkResult) { return selected?.forward(checkResult) ? undefined : "lightGray"; } selected?.forward(); }); ScriptingGlobals.add(function webBack(checkResult?: boolean) { const selected = (SelectionManager.Views().lastElement()?.ComponentView as WebBox); if (checkResult) { return selected?.back(checkResult) ? undefined : "lightGray"; } selected?.back(); }); /** Schema * toggleSchemaPreview **/ ScriptingGlobals.add(function toggleSchemaPreview(checkResult?: boolean) { const selected = SelectionManager.Docs().lastElement(); if (checkResult && selected) { const result: boolean = NumCast(selected.schemaPreviewWidth) > 0; if (result) return Colors.MEDIUM_BLUE; else return "transparent"; } else if (selected) { if (NumCast(selected.schemaPreviewWidth) > 0) { selected.schemaPreviewWidth = 200; } else { selected.schemaPreviewWidth = 0; } } }); /** STACK * groupBy */ ScriptingGlobals.add(function setGroupBy(key: string, checkResult?: boolean) { SelectionManager.Docs().map(doc => doc._fontFamily = key); const editorView = RichTextMenu.Instance.TextView?.EditorView; if (checkResult) { return StrCast((editorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily); } if (editorView) RichTextMenu.Instance.setFontFamily(key); else Doc.UserDoc().fontFamily = key; });