diff options
Diffstat (limited to 'src/client/views/nodes/button/FontIconBox.tsx')
-rw-r--r-- | src/client/views/nodes/button/FontIconBox.tsx | 925 |
1 files changed, 925 insertions, 0 deletions
diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx new file mode 100644 index 000000000..b1d74261b --- /dev/null +++ b/src/client/views/nodes/button/FontIconBox.tsx @@ -0,0 +1,925 @@ +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, StrListCast } from '../../../../fields/Doc'; +import { InkTool } from '../../../../fields/InkField'; +import { createSchema, makeInterface } from '../../../../fields/Schema'; +import { ScriptField } from '../../../../fields/ScriptField'; +import { BoolCast, Cast, NumCast, StrCast } from '../../../../fields/Types'; +import { WebField } from '../../../../fields/URLField'; +import { DocumentType } from '../../../documents/DocumentTypes'; +import { Scripting } from "../../../util/Scripting"; +import { SelectionManager } from '../../../util/SelectionManager'; +import { ColorScheme } from '../../../util/SettingsManager'; +import { UndoManager, undoBatch } from '../../../util/UndoManager'; +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 { SetActiveInkColor, ActiveFillColor, SetActiveFillColor, ActiveInkWidth, ActiveInkColor, SetActiveInkWidth } from '../../InkingStroke'; +import { StyleProp } from '../../StyleProvider'; +import { FieldView, FieldViewProps } from '.././FieldView'; +import { RichTextMenu } from '../formattedText/RichTextMenu'; +import { TextButton } from './textButton'; +import { ToggleButton } from './toggleButton'; +import { IButtonProps } from './ButtonInterface'; +import { FontIconBadge } from './FontIconBadge'; +import './FontIconBox.scss'; +import { undo } from 'prosemirror-history'; +import { WebBox } from '../WebBox'; +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; +} + +type FontIconDocument = makeInterface<[typeof FontIconSchema]>; +const FontIconDocument = makeInterface(FontIconSchema); +@observer +export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(FontIconDocument) { + 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 setValue = (value: number) => { + // Script for running the toggle + const script: string = StrCast(this.rootDoc.script) + "(" + value + ")"; + ScriptField.MakeScript(script)?.script.run(); + }; + + // Script for checking the outcome of the toggle + const checkScript: string = StrCast(this.rootDoc.script) + "(0, true)"; + const checkResult: number = ScriptField.MakeScript(checkScript)?.script.run().result; + + + if (numBtnType === NumButtonType.Slider) { + const dropdown = + <div + className="menuButton-dropdownBox" + onPointerDown={e => e.stopPropagation()} + > + <input type="range" step="1" min={NumCast(this.rootDoc.numBtnMin, 0)} max={NumCast(this.rootDoc.numBtnMax, 100)} value={checkResult} + className={"menu-slider"} id="slider" + onPointerDown={() => this._batch = UndoManager.StartBatch("presDuration")} + onPointerUp={() => this._batch?.end()} + onChange={e => { e.stopPropagation(); setValue(Number(e.target.value)); }} + /> + </div>; + return ( + <div + className={`menuButton ${this.type} ${numBtnType}`} + onClick={action(() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen)} + > + {checkResult} + {this.rootDoc.dropDownOpen ? dropdown : null} + </div> + ); + } 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 <div className="list-item" key={`${value}`} + style={{ + backgroundColor: value === checkResult ? Colors.LIGHT_BLUE : undefined + }} + onClick={() => setValue(value)}> + {value} + </div>; + }); + return ( + <div + className={`menuButton ${this.type} ${numBtnType}`} + > + <div className={`button`} onClick={action((e) => setValue(checkResult - 1))}> + <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={"minus"} /> + </div> + <div + className={`button ${'number'}`} + onPointerDown={(e) => { + e.stopPropagation(); + e.preventDefault(); + }} + onClick={action(() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen)} + > + <input + style={{ width: 30 }} + className="button-input" + type="number" + value={checkResult} + onChange={action((e) => setValue(Number(e.target.value)))} + /> + </div> + <div className={`button`} onClick={action((e) => setValue(checkResult + 1))}> + <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={"plus"} /> + </div> + + {this.rootDoc.dropDownOpen ? + <div> + <div className="menuButton-dropdownList" + style={{ left: "25%" }}> + {list} + </div> + <div className="dropbox-background" onClick={(e) => { e.stopPropagation(); this.rootDoc.dropDownOpen = false; }} /> + </div> : null} + + </div> + ); + } else { + return ( + <div> + + </div> + ); + } + + + } + + /** + * 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 ( + <div className={`menuButton ${this.type} ${active}`} + style={{ color: color, backgroundColor: backgroundColor, borderBottomLeftRadius: this.dropdown ? 0 : undefined }} + onClick={action(() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen)}> + <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} /> + {!this.label || !Doc.UserDoc()._showLabel ? (null) : <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor }}> {this.label} </div>} + <div + className="menuButton-dropdown" + style={{ borderBottomRightRadius: this.dropdown ? 0 : undefined }}> + <FontAwesomeIcon icon={'caret-down'} color={color} size="sm" /> + </div> + {this.rootDoc.dropDownOpen ? + <div className="menuButton-dropdownBox"> + {/* DROPDOWN BOX CONTENTS */} + </div> : null} + </div> + ); + } + + /** + * 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: string = StrCast(this.rootDoc.script); + + let noviceList: string[] = []; + let text: string | undefined; + let dropdown = true; + let icon: IconProp = "caret-down"; + let noneSelected: boolean = false; + + if (script === '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 === 'setFont') { + const selected = SelectionManager.Docs().lastElement(); + text = StrCast((selected?.type === DocumentType.RTF ? selected : Doc.UserDoc())._fontFamily); + noviceList = ["Roboto", "Times New Roman", "Arial", "Georgia", + "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"]; + } + + // Get items to place into the list + const list = this.buttonList.map((value) => { + if (Doc.UserDoc().noviceMode && !noviceList.includes(value)) { + return; + } + const click = () => { + const s = ScriptField.MakeScript(script + '("' + value + '")'); + if (s) { + s.script.run().result; + } + }; + return <div className="list-item" key={`${value}`} + style={{ + fontFamily: script === 'setFont' ? value : undefined, + backgroundColor: value === text ? Colors.LIGHT_BLUE : undefined + }} + onClick={click}> + {value[0].toUpperCase() + value.slice(1)} + </div>; + }); + + const label = !this.label || !Doc.UserDoc()._showLabel ? (null) : + <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor, position: "absolute" }}> + {this.label} + </div>; + + return ( + <div className={`menuButton ${this.type} ${active}`} + style={{ backgroundColor: this.rootDoc.dropDownOpen ? Colors.MEDIUM_BLUE : backgroundColor, color: color, display: dropdown ? undefined : "flex" }} + onClick={dropdown ? () => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen : undefined}> + {dropdown || noneSelected ? (null) : <FontAwesomeIcon style={{ marginLeft: 5 }} className={`fontIconBox-icon-${this.type}`} icon={icon} color={color} />} + <div className="menuButton-dropdown-header"> + {text && text[0].toUpperCase() + text.slice(1)} + </div> + {label} + {!dropdown ? (null) : <div className="menuButton-dropDown"> + <FontAwesomeIcon icon={icon} color={color} size="sm" /> + </div>} + {this.rootDoc.dropDownOpen ? + <div> + <div className="menuButton-dropdownList" + style={{ left: 0 }}> + {list} + </div> + <div className="dropbox-background" onClick={(e) => { e.stopPropagation(); this.rootDoc.dropDownOpen = false; }} /> + </div> + : null} + </div> + ); + } + + /** + * Color button + */ + @computed get colorButton() { + 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: string = StrCast(this.rootDoc.script); + const scriptCheck: string = script + "(undefined, true)"; + const boolResult = ScriptField.MakeScript(scriptCheck)?.script.run().result; + + let stroke: boolean = false; + let strokeIcon: any; + // if (script === "setStrokeColor") { + // stroke = true; + // const checkWidth = ScriptField.MakeScript("setStrokeWidth(0, true)")?.script.run().result; + // const width = 20 + (checkWidth / 100) * 70; + // const height = 20 + (checkWidth / 100) * 70; + // strokeIcon = (<div style={{ borderRadius: "100%", width: width + '%', height: height + '%', backgroundColor: boolResult ? boolResult : "#FFFFFF" }} />); + // } + + const colorOptions: string[] = ['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', + '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', + '#FFFFFF', '#f1efeb', "transparent"]; + + const colorBox = (func: (color: ColorState) => void) => <SketchPicker + disableAlpha={!stroke} + onChange={func} color={boolResult ? boolResult : "#FFFFFF"} + presetColors={colorOptions} />; + const label = !this.label || !Doc.UserDoc()._showLabel ? (null) : + <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor, position: "absolute" }}> + {this.label} + </div>; + + const dropdownCaret = <div + className="menuButton-dropDown" + style={{ borderBottomRightRadius: this.dropdown ? 0 : undefined }}> + <FontAwesomeIcon icon={'caret-down'} color={color} size="sm" /> + </div>; + + const click = (value: ColorState) => { + const hex: string = value.hex; + const s = ScriptField.MakeScript(script + '("' + hex + '", false)'); + if (s) { + undoBatch(() => s.script.run().result)(); + } + }; + return ( + <div className={`menuButton ${this.type} ${active}`} + style={{ color: color, borderBottomLeftRadius: this.dropdown ? 0 : undefined }} + onClick={() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen} + onPointerDown={e => e.stopPropagation()}> + {stroke ? strokeIcon : <><FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} /> + <div className="colorButton-color" + style={{ backgroundColor: boolResult ? boolResult : "#FFFFFF" }} + ></div></>} + {label} + {/* {dropdownCaret} */} + {this.rootDoc.dropDownOpen ? + <div> + <div className="menuButton-dropdownBox" + onPointerDown={e => e.stopPropagation()} + onClick={e => e.stopPropagation()}> + {colorBox(click)} + </div> + <div className="dropbox-background" onClick={(e) => { e.stopPropagation(); this.rootDoc.dropDownOpen = false; }} /> + </div> + : null} + </div> + ); + } + + @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) : + <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor, position: "absolute" }}> + {this.label} + </div>; + + if (switchToggle) { + return ( + <div className={`menuButton ${this.type} ${'switch'}`}> + {buttonText ? buttonText : null} + <label className="switch"> + <input type="checkbox" + checked={backgroundColor === Colors.MEDIUM_BLUE} + /> + <span className="slider round"></span> + </label> + </div> + ); + } else { + return ( + <div className={`menuButton ${this.type}`} + style={{ opacity: 1, backgroundColor: backgroundColor, color: color }}> + <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} /> + {label} + </div> + ); + } + } + + + + /** + * 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 ( + <div className={`menuButton ${this.type}`} onContextMenu={this.specificContextMenu} + style={{ backgroundColor: "transparent", borderBottomLeftRadius: this.dropdown ? 0 : undefined }}> + <div className="menuButton-wrap"> + <FontAwesomeIcon className={`menuButton-icon-${this.type}`} icon={this.icon} color={"black"} size={"sm"} /> + {!this.label || !Doc.UserDoc()._showLabel ? (null) : <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor }}> {this.label} </div>} + </div> + </div> + ); + } + + @computed get editableText() { + // Script for running the toggle + const script: string = StrCast(this.rootDoc.script); + + // Script for checking the outcome of the toggle + const checkScript: string = StrCast(this.rootDoc.script) + "('', true)"; + + // Function to run the script + const checkResult = ScriptField.MakeScript(checkScript)?.script.run().result; + + const setValue = (value: string, shiftDown?: boolean): boolean => { + ScriptField.MakeScript(script + "('" + value + "')")?.script.run(); + return true; + }; + return ( + <div className="menuButton editableText"> + <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={"lock"} /> + <div style={{ width: "calc(100% - .875em)", paddingLeft: "4px" }}> + <EditableView GetValue={() => checkResult} SetValue={setValue} contents={checkResult} /> + </div> + </div> + ); + } + + + render() { + const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color); + const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor); + const dark: boolean = Doc.UserDoc().colorScheme === ColorScheme.Dark; + + const label = !this.label || !Doc.UserDoc()._showLabel ? (null) : + <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor, position: "absolute" }}> + {this.label} + </div>; + + const menuLabel = !this.label || !Doc.UserDoc()._showMenuLabel ? (null) : + <div className="fontIconBox-label" style={{ color: color, backgroundColor: "transparent" }}> + {this.label} + </div>; + + const buttonProps: IButtonProps = { + type: this.type, + rootDoc: this.rootDoc, + label: label, + backgroundColor: backgroundColor, + icon: this.icon, + color: color + } + + const buttonText = StrCast(this.rootDoc.buttonText); + + // TODO:glr Add label of button type + let button = this.defaultButton; + + switch (this.type) { + case ButtonType.TextButton: + button = ( + <div className={`menuButton ${this.type}`} style={{ color: color, backgroundColor: backgroundColor, opacity: 1, gridAutoColumns: `${NumCast(this.rootDoc._height)} auto` }}> + <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} /> + {buttonText ? + <div className="button-text"> + {buttonText} + </div> + : null} + {label} + </div> + ); + // button = <TextButton {...buttonProps}></TextButton> + break; + case ButtonType.EditableText: + console.log("Editable text"); + 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 = ( + <div className={`menuButton ${this.type}`} style={{ opacity: 1, backgroundColor: backgroundColor, color: color }}> + <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} /> + {label} + </div> + ); + break; + case ButtonType.ToggleButton: + button = this.toggleButton; + // button = <ToggleButton {...buttonProps}></ToggleButton> + break; + case ButtonType.ClickButton: + button = ( + <div className={`menuButton ${this.type}`} style={{ color: color, backgroundColor: backgroundColor, opacity: 1 }}> + <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} /> + {label} + </div> + ); + break; + case ButtonType.MenuButton: + const trailsIcon = <img src={`/assets/${"presTrails.png"}`} + style={{ width: 30, height: 30, filter: `invert(${color === Colors.DARK_GRAY ? "0%" : "100%"})` }} />; + button = ( + <div className={`menuButton ${this.type}`} style={{ color: color, backgroundColor: backgroundColor }}> + {this.icon === "pres-trail" ? trailsIcon : <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />} + {menuLabel} + <FontIconBadge collection={Cast(this.rootDoc.watchedDocuments, Doc, null)} /> + </div > + ); + break; + default: + break; + } + + return !this.layoutDoc.toolTip || this.type === ButtonType.DropdownList || this.type === ButtonType.ColorButton || this.type === ButtonType.NumberButton || this.type === ButtonType.EditableText ? button : + <Tooltip title={<div className="dash-tooltip">{StrCast(this.layoutDoc.toolTip)}</div>}> + {button} + </Tooltip>; + } +} + + +// toggle: Set overlay status of selected document +Scripting.addGlobal(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 +Scripting.addGlobal(function setBackgroundColor(color?: string, checkResult?: boolean) { + const selected = SelectionManager.Docs().lastElement(); + if (checkResult) { + if (selected) { + console.log("[Background] (selected): " + StrCast(selected._backgroundColor)); + return selected._backgroundColor; + } else { + return "#FFFFFF"; + } + } + if (selected?.type === DocumentType.INK) selected.fillColor = color; + if (selected) selected._backgroundColor = color; + Doc.UserDoc()._fontColor = color; +}); + +// toggle: Set overlay status of selected document +Scripting.addGlobal(function setHeaderColor(color?: string, checkResult?: boolean) { + 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 +Scripting.addGlobal(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; + else 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 +Scripting.addGlobal(function setFont(font: string, checkResult?: boolean) { + SelectionManager.Docs().map(doc => doc._fontFamily = font); + const editorView = RichTextMenu.Instance.TextView?.EditorView; + editorView?.state && RichTextMenu.Instance.setFontFamily(font, editorView); + Doc.UserDoc()._fontFamily = font; + return Doc.UserDoc()._fontFamily; +}); + +Scripting.addGlobal(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?.activeColors[0]; + case "size": return style?.activeSizes[0]; + case "color": return style?.activeColors[0]; + case "highlight": return style?.activeHighlights[0]; + } +}); + +Scripting.addGlobal(function setAlignment(align: "left" | "right" | "center", checkResult?: boolean) { + const editorView = RichTextMenu.Instance?.TextView?.EditorView; + if (checkResult) { + let active: string; + if (editorView) { + active = editorView?.state && RichTextMenu.Instance.getActiveAlignment(); + } else { + active = StrCast(Doc.UserDoc().textAlign); + } + if (active === align) return Colors.MEDIUM_BLUE; + else return "transparent"; + } + SelectionManager.Docs().map(doc => doc.textAlign = align); + switch (align) { + case "left": + editorView?.state && RichTextMenu.Instance.alignLeft(editorView, editorView.dispatch); + break; + case "center": + editorView?.state && RichTextMenu.Instance.alignCenter(editorView, editorView.dispatch); + break; + case "right": + editorView?.state && RichTextMenu.Instance.alignRight(editorView, editorView.dispatch); + break; + default: + break; + } + Doc.UserDoc().textAlign = align; +}); + +Scripting.addGlobal(function setBulletList(mapStyle: "bullet" | "decimal", checkResult?: boolean) { + const editorView = RichTextMenu.Instance?.TextView?.EditorView; + if (checkResult) { + const active = editorView?.state && RichTextMenu.Instance.getActiveListStyle(); + console.log(active, mapStyle); + if (active === mapStyle) return Colors.MEDIUM_BLUE; + else return "transparent"; + } + if (editorView) { + const active = editorView?.state && RichTextMenu.Instance.getActiveListStyle(); + if (active === mapStyle) { + console.log("set bullet list"); + editorView?.state && RichTextMenu.Instance.changeListType(editorView.state.schema.nodes.ordered_list.create({ mapStyle: "" })); + } else { + editorView?.state && RichTextMenu.Instance.changeListType(editorView.state.schema.nodes.ordered_list.create({ mapStyle: mapStyle })); + } + } +}); + +// toggle: Set overlay status of selected document +Scripting.addGlobal(function setFontColor(color?: string, checkResult?: boolean) { + const selected = SelectionManager.Docs().lastElement(); + const editorView = RichTextMenu.Instance.TextView?.EditorView; + + if (checkResult) { + if (selected) { + console.log("[Font color] (selected): " + StrCast(selected._fontColor)); + return selected._fontColor; + } else { + console.log("[Font color] (global): " + StrCast(Doc.UserDoc()._fontColor)); + return Doc.UserDoc()._fontColor; + } + } + + if (selected) { + selected._fontColor = color; + if (color) { + editorView?.state && RichTextMenu.Instance.setColor(color, editorView, editorView?.dispatch); + } + } + Doc.UserDoc()._fontColor = color; +}); + +// toggle: Set overlay status of selected document +Scripting.addGlobal(function setFontHighlight(color?: string, checkResult?: boolean) { + const selected = SelectionManager.Docs().lastElement(); + const editorView = RichTextMenu.Instance.TextView?.EditorView; + + if (checkResult) { + if (selected) { + return selected._fontHighlight; + } else { + return 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 +Scripting.addGlobal(function setFontSize(size: string, checkResult?: boolean) { + if (checkResult) { + const size: number = parseInt(StrCast(Doc.UserDoc()._fontSize), 10); + return size; + } + const editorView = RichTextMenu.Instance.TextView?.EditorView; + editorView?.state && RichTextMenu.Instance.setFontSize(Number(size), editorView); + Doc.UserDoc()._fontSize = size + "px"; +}); + +Scripting.addGlobal(function toggleBold(checkResult?: boolean) { + if (checkResult) { + if (Doc.UserDoc().bold) return Colors.MEDIUM_BLUE; + else return "transparent"; + } + const editorView = RichTextMenu.Instance.TextView?.EditorView; + if (editorView) { + console.log("editorView"); + editorView?.state && RichTextMenu.Instance.toggleBold(editorView, true); + } + SelectionManager.Docs().filter(doc => StrCast(doc.type) === DocumentType.RTF).map(doc => doc.bold = !doc.bold); + Doc.UserDoc().bold = !Doc.UserDoc().bold; + return Doc.UserDoc().bold; +}); + +Scripting.addGlobal(function toggleUnderline(checkResult?: boolean) { + if (checkResult) { + if (Doc.UserDoc().underline) return Colors.MEDIUM_BLUE; + else return "transparent"; + } + const editorView = RichTextMenu.Instance.TextView?.EditorView; + if (editorView) { + console.log("editorView"); + editorView?.state && RichTextMenu.Instance.toggleUnderline(editorView, true); + } + SelectionManager.Docs().filter(doc => StrCast(doc.type) === DocumentType.RTF).map(doc => doc.underline = !doc.underline); + Doc.UserDoc().underline = !Doc.UserDoc().underline; + return Doc.UserDoc().underline; +}); + +Scripting.addGlobal(function toggleItalic(checkResult?: boolean) { + if (checkResult) { + if (Doc.UserDoc().italic) return Colors.MEDIUM_BLUE; + else return "transparent"; + } + const editorView = RichTextMenu.Instance.TextView?.EditorView; + if (editorView) { + console.log("editorView"); + editorView?.state && RichTextMenu.Instance.toggleItalic(editorView, true); + } + SelectionManager.Docs().filter(doc => StrCast(doc.type) === DocumentType.RTF).map(doc => doc.italic = !doc.italic); + Doc.UserDoc().italic = !Doc.UserDoc().italic; + return Doc.UserDoc().italic; +}); + + + + +/** INK + * setActiveInkTool + * setStrokeWidth + * setStrokeColor + **/ + +Scripting.addGlobal(function setActiveInkTool(tool: string, checkResult?: boolean) { + if (checkResult) { + if (Doc.UserDoc().activeInkTool === tool && GestureOverlay.Instance.InkShape === "" || GestureOverlay.Instance.InkShape === tool) return Colors.MEDIUM_BLUE; + else return "transparent"; + } + if (tool === "circle") { + Doc.UserDoc().activeInkTool = "pen"; + GestureOverlay.Instance.InkShape = tool; + } else if (tool === "square") { + Doc.UserDoc().activeInkTool = "pen"; + GestureOverlay.Instance.InkShape = tool; + } else if (tool === "line") { + Doc.UserDoc().activeInkTool = "pen"; + GestureOverlay.Instance.InkShape = tool; + } else if (tool) { + if (Doc.UserDoc().activeInkTool === tool && GestureOverlay.Instance.InkShape === "" || GestureOverlay.Instance.InkShape === tool) { + GestureOverlay.Instance.InkShape = ""; + Doc.UserDoc().activeInkTool = InkTool.None; + } else { + Doc.UserDoc().activeInkTool = tool; + } + } else { + Doc.UserDoc().activeInkTool = InkTool.None; + } +}); + +// toggle: Set overlay status of selected document +Scripting.addGlobal(function setFillColor(color?: string, checkResult?: boolean) { + const selected = SelectionManager.Docs().lastElement(); + if (checkResult) { + if (selected?.type === DocumentType.INK) { + return StrCast(selected._backgroundColor); + } + return ActiveFillColor(); + } + SetActiveFillColor(StrCast(color)); + SelectionManager.Docs().filter(doc => doc.type === DocumentType.INK).map(doc => doc.fillColor = color); +}); + +Scripting.addGlobal(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 +Scripting.addGlobal(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 + **/ +Scripting.addGlobal(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); + } +}); +Scripting.addGlobal(function webForward() { + const selected = SelectionManager.Views().lastElement(); + if (selected?.rootDoc.type === DocumentType.WEB) { + (selected.ComponentView as WebBox).forward(); + } +}); +Scripting.addGlobal(function webBack() { + const selected = SelectionManager.Views().lastElement(); + if (selected?.rootDoc.type === DocumentType.WEB) { + (selected.ComponentView as WebBox).back(); + } +}); + + +/** Schema + * toggleSchemaPreview + **/ +Scripting.addGlobal(function toggleSchemaPreview(checkResult?: boolean) { + const selected = SelectionManager.Docs().lastElement(); + console.log(selected && selected.title); + 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; + } + } +});
\ No newline at end of file |