aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/button/FontIconBox.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/button/FontIconBox.tsx')
-rw-r--r--src/client/views/nodes/button/FontIconBox.tsx751
1 files changed, 76 insertions, 675 deletions
diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx
index d181de8d0..e31407f4b 100644
--- a/src/client/views/nodes/button/FontIconBox.tsx
+++ b/src/client/views/nodes/button/FontIconBox.tsx
@@ -1,39 +1,23 @@
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Tooltip } from '@material-ui/core';
-import { ColorPicker, Dropdown, DropdownType, IconButton, IListItemProps, Size, Toggle, ToggleType, Type } from 'browndash-components';
-import { action, computed, observable, runInAction } from 'mobx';
+import { Button, ColorPicker, Dropdown, DropdownType, EditableText, IconButton, IListItemProps, NumberDropdown, NumberDropdownType, Size, Toggle, ToggleType, Type } from 'browndash-components';
+import { action, computed, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { ColorState, SketchPicker } from 'react-color';
-import * as fa from 'react-icons/fa';
import { Doc, StrListCast } from '../../../../fields/Doc';
-import { Height, Width } from '../../../../fields/DocSymbols';
-import { InkTool } from '../../../../fields/InkField';
import { ScriptField } from '../../../../fields/ScriptField';
import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
-import { WebField } from '../../../../fields/URLField';
-import { GestureUtils } from '../../../../pen-gestures/GestureUtils';
-import { aggregateBounds, Utils } from '../../../../Utils';
import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
-import { LinkManager } from '../../../util/LinkManager';
-import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
import { SelectionManager } from '../../../util/SelectionManager';
-import { undoable, undoBatch, UndoManager } from '../../../util/UndoManager';
-import { CollectionFreeFormView } from '../../collections/collectionFreeForm';
+import { undoable, UndoManager } from '../../../util/UndoManager';
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, ActiveIsInkMask, SetActiveFillColor, SetActiveInkColor, SetActiveInkWidth, SetActiveIsInkMask } from '../../InkingStroke';
-import { InkTranscription } from '../../InkTranscription';
import { StyleProp } from '../../StyleProvider';
import { FieldView, FieldViewProps } from '.././FieldView';
-import { CollectionFreeFormDocumentView } from '../CollectionFreeFormDocumentView';
import { OpenWhere } from '../DocumentView';
import { RichTextMenu } from '../formattedText/RichTextMenu';
-import { WebBox } from '../WebBox';
import './FontIconBox.scss';
export enum ButtonType {
@@ -136,116 +120,35 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
/**
* Number button
*/
- @computed get numberSliderButton() {
+ @computed get numberDropdown() {
+ let type: NumberDropdownType;
+ switch(this.type) {
+ case ButtonType.NumberDropdownButton:
+ type = 'dropdown'
+ break;
+ case ButtonType.NumberInlineButton:
+ type = 'input'
+ break;
+ case ButtonType.NumberSliderButton:
+ default:
+ type = 'slider'
+ break;
+ }
const numScript = (value?: number) => ScriptCast(this.rootDoc.script).script.run({ self: this.rootDoc, value, _readOnly_: value === undefined });
+ const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
// Script for checking the outcome of the toggle
- const checkResult = Number(numScript().result ?? 0).toPrecision(NumCast(this.dataDoc.numPrecision, 3));
+ const checkResult = Number(Number(numScript().result ?? 0).toPrecision(NumCast(this.dataDoc.numPrecision, 3)));
const label = !FontIconBox.GetShowLabels() ? null : <div className="fontIconBox-label">{this.label}</div>;
- const dropdown = (
- <div className="menuButton-dropdownBox" onPointerDown={e => e.stopPropagation()}>
- <input
- className="menu-slider"
- type="range"
- step="1"
- min={NumCast(this.rootDoc.numBtnMin, 0)}
- max={NumCast(this.rootDoc.numBtnMax, 100)}
- //readOnly={true}
- value={checkResult}
- onPointerDown={() => (this._batch = UndoManager.StartBatch('num slider changing'))}
- onPointerUp={() => this._batch?.end()}
- onChange={undoable(e => {
- e.stopPropagation();
- numScript(Number(e.target.value));
- }, 'set num value')}
- />
- </div>
- );
- return (
- <div
- className="menuButton numBtn slider"
- onPointerDown={e => e.stopPropagation()}
- onClick={action(() => {
- this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen;
- this.noTooltip = this.rootDoc.dropDownOpen;
- Doc.UnBrushAllDocs();
- })}>
- {checkResult}
- {label}
- {this.rootDoc.dropDownOpen ? dropdown : null}
- </div>
- );
- }
- /**
- * Number button
- */
- @computed get numberDropdownButton() {
- const numScript = (value?: number) => ScriptCast(this.rootDoc.script)?.script.run({ self: this.rootDoc, value, _readOnly_: value === undefined });
-
- const checkResult = Number(numScript().result ?? 0).toPrecision(NumCast(this.dataDoc.numPrecision, 3));
-
- const items: number[] = [];
- for (let i = 0; i < 100; i += 2) items.push(i);
-
- const list = items.map(value => {
- return (
- <div
- className="list-item"
- key={`${value}`}
- style={{
- backgroundColor: value.toString() === checkResult ? Colors.LIGHT_BLUE : undefined,
- }}
- onClick={undoable(value => numScript(value), `${this.rootDoc.title} button set from list`)}>
- {value}
- </div>
- );
- });
- return (
- <div className="menuButton numBtn list">
- <div className="button" onClick={undoable(e => numScript(Number(checkResult) - 1), `${this.rootDoc.title} decrement value`)}>
- <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;
- this.noTooltip = this.rootDoc.dropDownOpen;
- Doc.UnBrushAllDocs();
- })}>
- <input style={{ width: 30 }} className="button-input" type="number" value={checkResult} readOnly={true} onChange={undoable(e => numScript(Number(e.target.value)), `${this.rootDoc.title} button set value`)} />
- </div>
- <div className={`button`} onClick={undoable(e => numScript(Number(checkResult) + 1), `${this.rootDoc.title} increment value`)}>
- <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={action(e => {
- e.stopPropagation();
- this.rootDoc.dropDownOpen = false;
- this.noTooltip = false;
- Doc.UnBrushAllDocs();
- })}
- />
- </div>
- ) : null}
- </div>
- );
- }
- /**
- * Number button
- */
- @computed get numberInlineButton() {
- return <div />;
+ return <NumberDropdown
+ color={color}
+ numberDropdownType={type}
+ showPlusMinus={false}
+ min={NumCast(this.rootDoc.numBtnMin, 0)}
+ max={NumCast(this.rootDoc.numBtnMax, 100)}
+ number={checkResult}
+ setNumber={undoable(value => numScript(value), `${this.rootDoc.title} button set from list`)}
+ />
}
/**
@@ -296,18 +199,22 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
try {
if (script?.script.originalScript.startsWith('setView')) {
const selected = SelectionManager.Docs().lastElement();
+ console.log('selected')
if (selected) {
if (StrCast(selected.type) === DocumentType.COL) {
text = StrCast(selected._type_collection);
} else {
+ console.log("doc selected", selected.title)
dropdown = false;
text = selected.type === DocumentType.RTF ? 'Text' : StrCast(selected.type);
icon = Doc.toIcon(selected);
+ return <div>Hi!</div>
}
} else {
dropdown = false;
icon = 'globe-asia';
text = 'User Default';
+ return <div>Hi!</div>
}
noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Stacking, CollectionViewType.NoteTaking];
} else text = StrCast((RichTextMenu.Instance?.TextView?.EditorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily);
@@ -323,79 +230,32 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
.map(value => (
{
text: value,
+ val: value,
style: { fontFamily: value },
onClick: undoable(() => script.script.run({ self: this.rootDoc, value }), value)
// shortcut: '#',
}
));
- const label =
- !this.label || !FontIconBox.GetShowLabels() ? null : (
- <div className="fontIconBox-label" style={{ bottom: 0, position: 'absolute', color: color, backgroundColor: backgroundColor }}>
- {this.label}
- </div>
- );
return (
- <Dropdown selected={{text: text}} color={Colors.WHITE} type={Type.PRIM} dropdownType={DropdownType.SELECT} items={list}/>
+ <Dropdown
+ selectedVal={text}
+ setSelectedVal={undoable((val) => script.script.run({ self: this.rootDoc, val }), `dropdown select ${this.label}`)}
+ color={Colors.WHITE}
+ type={Type.PRIM}
+ dropdownType={DropdownType.SELECT}
+ items={list}
+ tooltip={this.label}
+ />
)
-
- return (
- <div
- className={`menuButton ${this.type} ${active}`}
- style={{ backgroundColor: this.rootDoc.dropDownOpen ? Colors.MEDIUM_BLUE : backgroundColor, color: color, display: dropdown ? undefined : 'flex' }}
- onClick={
- dropdown
- ? action(() => {
- this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen;
- this.noTooltip = this.rootDoc.dropDownOpen;
- Doc.UnBrushAllDocs();
- })
- : undefined
- }>
- {dropdown ? 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={action(e => {
- e.stopPropagation();
- this.rootDoc.dropDownOpen = false;
- this.noTooltip = false;
- Doc.UnBrushAllDocs();
- })}
- />
- </div>
- ) : null}
- </div>
- );
}
- @observable colorPickerClosed: boolean = true;
+
@computed get colorScript() {
return ScriptCast(this.rootDoc.script);
}
- colorPicker = (curColor: string) => {
- const change = (value: ColorState, ev: MouseEvent) => {
- ev.preventDefault();
- ev.stopPropagation();
- const s = this.colorScript;
- s && undoBatch(() => s.script.run({ self: this.rootDoc, 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 <SketchPicker onChange={change as any /* SketchPicker passes the mouse event to the callback, but the type system doesn't know that */} color={curColor} presetColors={presets} />;
- };
/**
* Color button
*/
@@ -405,61 +265,20 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
const curColor = this.colorScript?.script.run({ self: this.rootDoc, value: undefined, _readOnly_: true }).result ?? 'transparent';
const tooltip: string = StrCast(this.rootDoc.toolTip);
- const label =
- !this.label || !FontIconBox.GetShowLabels() ? null : (
- <div className="fontIconBox-label" style={{ color, backgroundColor }}>
- {this.label}
- </div>
- );
-
return (
<ColorPicker
- onChange={(e) => {
- this.colorPickerClosed = !this.colorPickerClosed;
- setTimeout(() => Doc.UnBrushAllDocs());
- e.stopPropagation();
+ setSelectedColor={(value) => {
+ const s = this.colorScript;
+ s && undoable(() => s.script.run({ self: this.rootDoc, value: value, _readOnly_: false }).result, `Set ${tooltip} to ${value}`)();
}}
- color={color}
+ selectedColor={curColor}
type={Type.PRIM}
+ color={color}
icon={this.Icon(color)!}
tooltip={tooltip}
+ label={this.label}
/>
)
-
- return (
- <div
- className={`menuButton ${this.type + (FontIconBox.GetShowLabels() ? 'Label' : '')} ${this.colorPickerClosed}`}
- style={{ color: color, borderBottomLeftRadius: this.dropdown ? 0 : undefined }}
- onClick={action(e => {
- this.colorPickerClosed = !this.colorPickerClosed;
- this.noTooltip = !this.colorPickerClosed;
- setTimeout(() => Doc.UnBrushAllDocs());
- e.stopPropagation();
- })}
- onPointerDown={e => e.stopPropagation()}>
- {this.Icon(color)}
- <div className="colorButton-color" style={{ backgroundColor: curColor }} />
- {label}
- {/* {dropdownCaret} */}
- {this.colorPickerClosed ? null : (
- <div>
- <div className="menuButton-dropdownBox" onPointerDown={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onClick={e => e.stopPropagation()}>
- {this.colorPicker(curColor)}
- </div>
- <div
- className="dropbox-background"
- onPointerDown={action(e => {
- e.preventDefault();
- e.stopPropagation();
- this.colorPickerClosed = true;
- this.noTooltip = false;
- Doc.UnBrushAllDocs();
- })}
- />
- </div>
- )}
- </div>
- );
}
@computed get toggleButton() {
@@ -498,6 +317,11 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
const checkResult = script?.script.run({ value: '', _readOnly_: true }).result;
const setValue = (value: string, shiftDown?: boolean): boolean => script?.script.run({ value, _readOnly_: false }).result;
+
+ return <EditableText
+ editing={false} onEdit={() => {}} setEditing={(editing: boolean) => {}}
+ />
+
return (
<div className="menuButton editableText">
<FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={'lock'} />
@@ -514,78 +338,39 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
const tooltip: string = StrCast(this.rootDoc.toolTip);
- const label = (noBackground: boolean = false) =>
- !this.label || !FontIconBox.GetShowLabels() ? null : (
- <div className="fontIconBox-label" style={{ color, backgroundColor: noBackground ? 'transparent' : backgroundColor }}>
- {this.label}
- </div>
- );
// TODO:glr Add label of button type
let button: JSX.Element = this.defaultButton;
-
// prettier-ignore
switch (this.type) {
- case ButtonType.EditableText: return this.editableText;
+ case ButtonType.EditableText:
+ button = this.editableText;
+ break;
case ButtonType.DropdownList:
- let 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._type_collection);
- } 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, CollectionViewType.NoteTaking];
- } else text = StrCast((RichTextMenu.Instance?.TextView?.EditorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily);
- } catch (e) {
- console.log(e);
- }
- // Get items to place into the list
- const list: IListItemProps[] = this.buttonList
- .filter(value => !Doc.noviceMode || !noviceList.length || noviceList.includes(value))
- .map(value => (
- {
- text: value,
- style: { fontFamily: value },
- onClick: undoable(() => script.script.run({ self: this.rootDoc, value }), value)
- // shortcut: '#',
- }
- ));
- button = <Dropdown selected={{text: text}} color={Colors.WHITE} type={Type.PRIM} dropdownType={DropdownType.SELECT} items={list}/>
+ button = this.dropdownListButton;
+ break;
+ case ButtonType.ColorButton:
+ button = this.colorButton;
+ break;
+ case ButtonType.NumberDropdownButton:
+ case ButtonType.NumberInlineButton:
+ case ButtonType.NumberSliderButton:
+ button = this.numberDropdown;
+ break;
+ case ButtonType.DropdownButton:
+ button = this.dropdownButton;
break;
- case ButtonType.ColorButton: button = this.colorButton; break;
- case ButtonType.NumberDropdownButton: button = this.numberDropdownButton; break;
- case ButtonType.NumberInlineButton: button = this.numberInlineButton; break;
- case ButtonType.NumberSliderButton: button = this.numberSliderButton; break;
- case ButtonType.DropdownButton: button = this.dropdownButton; break;
case ButtonType.ToggleButton: button = this.toggleButton; break;
case ButtonType.TextButton:
- // Script for checking the outcome of the toggle
- script = ScriptCast(this.rootDoc.script);
- const checkResult = script?.script.run({ _readOnly_: true }).result;
- button = (
- <div className={`menuButton ${this.type}`} style={{ color, backgroundColor:checkResult ?? backgroundColor, opacity: 1, gridAutoColumns: `${NumCast(this.rootDoc._height)} auto` }}>
- {this.Icon(color)}
- {StrCast(this.rootDoc.buttonText) ? <div className="button-text">{StrCast(this.rootDoc.buttonText)}</div> : null}
- {label()}
- </div>
+ // Script for checking the outcome of the toggle
+ const script = ScriptCast(this.rootDoc.script);
+ const checkResult = script?.script.run({ _readOnly_: true }).result;
+ button = (
+ <Button tooltip={tooltip} color={checkResult ?? backgroundColor} icon={this.Icon(color)!} text={StrCast(this.rootDoc.buttonText)} label={this.label}/>
);
break;
case ButtonType.ClickButton:
- case ButtonType.ToolButton: button = (
+ case ButtonType.ToolButton:
+ button = (
<IconButton tooltip={tooltip} color={color} icon={this.Icon(color)!} label={this.label}/>
);
break;
@@ -598,387 +383,3 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
return button;
}
}
-
-// toggle: Set overlay status of selected document
-ScriptingGlobals.add(function setView(view: string) {
- const selected = SelectionManager.Docs().lastElement();
- selected ? (selected._type_collection = view) : console.log('[FontIconBox.tsx] changeView failed');
-});
-
-// toggle: Set overlay status of selected document
-ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: boolean) {
- const selectedViews = SelectionManager.Views();
- if (Doc.ActiveTool !== InkTool.None) {
- if (checkResult) {
- return ActiveFillColor();
- }
- SetActiveFillColor(color ?? 'transparent');
- } else if (selectedViews.length) {
- if (checkResult) {
- const selView = selectedViews.lastElement();
- const fieldKey = selView.rootDoc.type === DocumentType.INK ? 'fillColor' : 'backgroundColor';
- const layoutFrameNumber = Cast(selView.props.docViewPath().lastElement()?.rootDoc?._currentFrame, 'number'); // frame number that container is at which determines layout frame values
- const contentFrameNumber = Cast(selView.rootDoc?._currentFrame, 'number', layoutFrameNumber ?? null); // frame number that content is at which determines what content is displayed
- return CollectionFreeFormDocumentView.getStringValues(selView?.rootDoc, contentFrameNumber)[fieldKey] ?? 'transparent';
- }
- selectedViews.forEach(dv => {
- const fieldKey = dv.rootDoc.type === DocumentType.INK ? 'fillColor' : 'backgroundColor';
- const layoutFrameNumber = Cast(dv.props.docViewPath().lastElement()?.rootDoc?._currentFrame, 'number'); // frame number that container is at which determines layout frame values
- const contentFrameNumber = Cast(dv.rootDoc?._currentFrame, 'number', layoutFrameNumber ?? null); // frame number that content is at which determines what content is displayed
- if (contentFrameNumber !== undefined) {
- CollectionFreeFormDocumentView.setStringValues(contentFrameNumber, dv.rootDoc, { fieldKey: color });
- } else {
- dv.rootDoc['_' + fieldKey] = color;
- }
- });
- } else {
- const selected = SelectionManager.Docs().length ? SelectionManager.Docs() : LinkManager.currentLink ? [LinkManager.currentLink] : [];
- if (checkResult) {
- return selected.lastElement()?._backgroundColor ?? 'transparent';
- }
- selected.forEach(doc => (doc._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().layout_showTitle = color === 'transparent' ? undefined : StrCast(Doc.UserDoc().layout_showTitle, 'author_date');
-});
-
-// toggle: Set overlay status of selected document
-ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) {
- const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
- if (checkResult) {
- if (NumCast(selected?.Document.z) >= 1) return Colors.MEDIUM_BLUE;
- return 'transparent';
- }
- selected ? selected.props.CollectionFreeFormDocumentView?.().float() : console.log('[FontIconBox.tsx] toggleOverlay failed');
-});
-
-ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll', checkResult?: boolean) {
- const selected = SelectionManager.Docs().lastElement();
- // prettier-ignore
- const map: Map<'flashcards' | 'grid' | 'snaplines' | 'clusters' | 'arrange'| 'viewAll', { waitForRender?: boolean, checkResult: (doc:Doc) => any; setDoc: (doc:Doc) => void;}> = new Map([
- ['grid', {
- checkResult: (doc:Doc) => doc._freeform_backgroundGrid,
- setDoc: (doc:Doc) => doc._freeform_backgroundGrid = !doc._freeform_backgroundGrid,
- }],
- ['snaplines', {
- checkResult: (doc:Doc) => doc._freeform_snapLines,
- setDoc: (doc:Doc) => doc._freeform_snapLines = !doc._freeform_snapLines,
- }],
- ['viewAll', {
- checkResult: (doc:Doc) => doc._freeform_fitContentsToBox,
- setDoc: (doc:Doc) => doc._freeform_fitContentsToBox = !doc._freeform_fitContentsToBox,
- }],
- ['clusters', {
- waitForRender: true, // flags that undo batch should terminate after a re-render giving the script the chance to fire
- checkResult: (doc:Doc) => doc._freeform_useClusters,
- setDoc: (doc:Doc) => doc._freeform_useClusters = !doc._freeform_useClusters,
- }],
- ['arrange', {
- waitForRender: true, // flags that undo batch should terminate after a re-render giving the script the chance to fire
- checkResult: (doc:Doc) => doc._autoArrange,
- setDoc: (doc:Doc) => doc._autoArrange = !doc._autoArrange,
- }],
- ['flashcards', {
- checkResult: (doc:Doc) => Doc.UserDoc().defaultToFlashcards,
- setDoc: (doc:Doc) => Doc.UserDoc().defaultToFlashcards = !Doc.UserDoc().defaultToFlashcards,
- }],
- ]);
-
- if (checkResult) {
- return map.get(attr)?.checkResult(selected) ? Colors.MEDIUM_BLUE : 'transparent';
- }
- const batch = map.get(attr)?.waitForRender ? UndoManager.StartBatch('set freeform attribute') : { end: () => {} };
- SelectionManager.Docs().map(dv => map.get(attr)?.setDoc(dv));
- setTimeout(() => batch.end(), 100);
-});
-ScriptingGlobals.add(function setFontAttr(attr: 'font' | 'fontColor' | 'highlight' | 'fontSize', value: any, checkResult?: boolean) {
- const editorView = RichTextMenu.Instance?.TextView?.EditorView;
- const selected = SelectionManager.Docs().lastElement();
- // prettier-ignore
- const map: Map<'font'|'fontColor'|'highlight'|'fontSize', { checkResult: () => any; setDoc: () => void;}> = new Map([
- ['font', {
- checkResult: () => RichTextMenu.Instance?.fontFamily,
- setDoc: () => value && RichTextMenu.Instance.setFontFamily(value),
- }],
- ['highlight', {
- checkResult: () =>(selected ?? Doc.UserDoc())._fontHighlight,
- setDoc: () => value && RichTextMenu.Instance.setHighlight(value),
- }],
- ['fontColor', {
- checkResult: () => RichTextMenu.Instance?.fontColor,
- setDoc: () => value && RichTextMenu.Instance.setColor(value),
- }],
- ['fontSize', {
- checkResult: () => RichTextMenu.Instance?.fontSize.replace('px', ''),
- setDoc: () => {
- if (typeof value === 'number') value = value.toString();
- if (value && Number(value).toString() === value) value += 'px';
- RichTextMenu.Instance.setFontSize(value);
- },
- }],
- ]);
-
- if (checkResult) {
- return map.get(attr)?.checkResult();
- }
- map.get(attr)?.setDoc?.();
-});
-
-type attrname = 'noAutoLink' | 'dictation' | 'bold' | 'italics' | 'underline' | 'left' | 'center' | 'right' | 'bullet' | 'decimal';
-type attrfuncs = [attrname, { checkResult: () => boolean; toggle: () => any }];
-ScriptingGlobals.add(function toggleCharStyle(charStyle: attrname, checkResult?: boolean) {
- const textView = RichTextMenu.Instance?.TextView;
- const editorView = textView?.EditorView;
- // prettier-ignore
- const alignments:attrfuncs[] = (['left','right','center'] as ("left"|"center"|"right")[]).map((where) =>
- [ where, { checkResult: () =>(editorView ? (RichTextMenu.Instance.textAlign ===where): (Doc.UserDoc().textAlign ===where) ? true:false),
- toggle: () => (editorView?.state ? RichTextMenu.Instance.align(editorView, editorView.dispatch, where):(Doc.UserDoc().textAlign = where))}]);
- // prettier-ignore
- const listings:attrfuncs[] = (['bullet','decimal'] as attrname[]).map(list =>
- [ list, { checkResult: () => (editorView ? RichTextMenu.Instance.getActiveListStyle() === list:false),
- toggle: () => editorView?.state && RichTextMenu.Instance.changeListType(list) }]);
- // prettier-ignore
- const attrs:attrfuncs[] = [
- ['dictation', { checkResult: () => textView?._recording ? true:false,
- toggle: () => textView && runInAction(() => (textView._recording = !textView._recording)) }],
- ['noAutoLink',{ checkResult: () => (editorView ? RichTextMenu.Instance.noAutoLink : false),
- toggle: () => editorView && RichTextMenu.Instance?.toggleNoAutoLinkAnchor()}],
- ['bold', { checkResult: () => (editorView ? RichTextMenu.Instance.bold : (Doc.UserDoc().fontWeight === 'bold') ? true:false),
- toggle: editorView ? RichTextMenu.Instance.toggleBold : () => (Doc.UserDoc().fontWeight = Doc.UserDoc().fontWeight === 'bold' ? undefined : 'bold')}],
- ['italics', { checkResult: () => (editorView ? RichTextMenu.Instance.italics : (Doc.UserDoc().fontStyle === 'italics') ? true:false),
- toggle: editorView ? RichTextMenu.Instance.toggleItalics : () => (Doc.UserDoc().fontStyle = Doc.UserDoc().fontStyle === 'italics' ? undefined : 'italics')}],
- ['underline', { checkResult: () => (editorView ? RichTextMenu.Instance.underline : (Doc.UserDoc().textDecoration === 'underline') ? true:false),
- toggle: editorView ? RichTextMenu.Instance.toggleUnderline : () => (Doc.UserDoc().textDecoration = Doc.UserDoc().textDecoration === 'underline' ? undefined : 'underline') }]]
-
- const map = new Map(attrs.concat(alignments).concat(listings));
- if (checkResult) return map.get(charStyle)?.checkResult() ? Colors.MEDIUM_BLUE : 'transparent';
- map.get(charStyle)?.toggle();
-});
-
-export function checkInksToGroup() {
- // console.log("getting here to inks group");
- if (Doc.ActiveTool === 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 (Doc.ActiveTool === 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[Width]();
- const height = d[Height]();
- 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[Height]();
- newCollection.width = newCollection[Width]();
- }
-
- // 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);
- });
- }
- CollectionFreeFormView.collectionsWithUnprocessedInk.clear();
-}
-
-function setActiveTool(tool: InkTool | GestureUtils.Gestures, keepPrim: boolean, checkResult?: boolean) {
- InkTranscription.Instance?.createInkGroup();
- if (checkResult) {
- return (Doc.ActiveTool === tool && !GestureOverlay.Instance?.InkShape) || GestureOverlay.Instance?.InkShape === tool
- ? GestureOverlay.Instance?.KeepPrimitiveMode || ![GestureUtils.Gestures.Circle, GestureUtils.Gestures.Line, GestureUtils.Gestures.Rectangle].includes(tool as GestureUtils.Gestures)
- ? Colors.MEDIUM_BLUE
- : Colors.MEDIUM_BLUE_ALT
- : 'transparent';
- }
- runInAction(() => {
- if (GestureOverlay.Instance) {
- GestureOverlay.Instance.KeepPrimitiveMode = keepPrim;
- }
- if (Object.values(GestureUtils.Gestures).includes(tool as any)) {
- if (GestureOverlay.Instance.InkShape === tool && !keepPrim) {
- Doc.ActiveTool = InkTool.None;
- GestureOverlay.Instance.InkShape = undefined;
- } else {
- Doc.ActiveTool = InkTool.Pen;
- GestureOverlay.Instance.InkShape = tool as GestureUtils.Gestures;
- }
- } else if (tool) {
- // pen or eraser
- if (Doc.ActiveTool === tool && !GestureOverlay.Instance.InkShape && !keepPrim) {
- Doc.ActiveTool = InkTool.None;
- } else {
- Doc.ActiveTool = tool as any;
- GestureOverlay.Instance.InkShape = undefined;
- }
- } else {
- Doc.ActiveTool = InkTool.None;
- }
- });
-}
-
-ScriptingGlobals.add(setActiveTool, 'sets the active ink tool mode');
-
-// toggle: Set overlay status of selected document
-ScriptingGlobals.add(function setInkProperty(option: 'inkMask' | 'fillColor' | 'strokeWidth' | 'strokeColor', value: any, checkResult?: boolean) {
- const selected = SelectionManager.Docs().lastElement();
- // prettier-ignore
- const map: Map<'inkMask' | 'fillColor' | 'strokeWidth' | 'strokeColor', { checkResult: () => any; setInk: (doc: Doc) => void; setMode: () => void }> = new Map([
- ['inkMask', {
- checkResult: () => ((selected?.type === DocumentType.INK ? BoolCast(selected.stroke_isInkMask) : ActiveIsInkMask()) ? Colors.MEDIUM_BLUE : 'transparent'),
- setInk: (doc: Doc) => (doc.stroke_isInkMask = !doc.stroke_isInkMask),
- setMode: () => selected?.type !== DocumentType.INK && SetActiveIsInkMask(!ActiveIsInkMask()),
- }],
- ['fillColor', {
- checkResult: () => (selected?.type === DocumentType.INK ? StrCast(selected.fillColor) : ActiveFillColor() ?? "transparent"),
- setInk: (doc: Doc) => (doc.fillColor = StrCast(value)),
- setMode: () => SetActiveFillColor(StrCast(value)),
- }],
- [ 'strokeWidth', {
- checkResult: () => (selected?.type === DocumentType.INK ? NumCast(selected.stroke_width) : ActiveInkWidth()),
- setInk: (doc: Doc) => (doc.stroke_width = NumCast(value)),
- setMode: () => SetActiveInkWidth(value.toString()),
- }],
- ['strokeColor', {
- checkResult: () => (selected?.type === DocumentType.INK ? StrCast(selected.color) : ActiveInkColor()),
- setInk: (doc: Doc) => (doc.color = String(value)),
- setMode: () => SetActiveInkColor(StrCast(value)),
- }],
- ]);
-
- if (checkResult) {
- return map.get(option)?.checkResult();
- }
- map.get(option)?.setMode();
- SelectionManager.Docs()
- .filter(doc => doc.type === DocumentType.INK)
- .map(doc => map.get(option)?.setInk(doc));
-});
-
-/** 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?.setData?.(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.schema_previewWidth) > 0;
- if (result) return Colors.MEDIUM_BLUE;
- else return 'transparent';
- } else if (selected) {
- if (NumCast(selected.schema_previewWidth) > 0) {
- selected.schema_previewWidth = 0;
- } else {
- selected.schema_previewWidth = 200;
- }
- }
-});
-ScriptingGlobals.add(function toggleSingleLineSchema(checkResult?: boolean) {
- const selected = SelectionManager.Docs().lastElement();
- if (checkResult && selected) {
- return NumCast(selected._schema_singleLine) > 0 ? Colors.MEDIUM_BLUE : 'transparent';
- }
- if (selected) {
- selected._schema_singleLine = !selected._schema_singleLine;
- }
-});
-
-/** STACK
- * groupBy
- */
-ScriptingGlobals.add(function setGroupBy(key: string, checkResult?: boolean) {
- SelectionManager.Docs().map(doc => (doc._text_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;
-});