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.tsx300
1 files changed, 118 insertions, 182 deletions
diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx
index 93761633c..b3a3c3ae4 100644
--- a/src/client/views/nodes/button/FontIconBox.tsx
+++ b/src/client/views/nodes/button/FontIconBox.tsx
@@ -1,4 +1,5 @@
import { IconProp } from '@fortawesome/fontawesome-svg-core';
+import { faAlignRight } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip } from '@material-ui/core';
import { action, computed, observable, runInAction } from 'mobx';
@@ -11,7 +12,7 @@ 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, StopEvent, Utils } from '../../../../Utils';
+import { aggregateBounds, Utils } from '../../../../Utils';
import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
import { LinkManager } from '../../../util/LinkManager';
import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
@@ -27,6 +28,7 @@ import { ActiveFillColor, ActiveInkColor, ActiveInkWidth, ActiveIsInkMask, SetAc
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';
@@ -133,10 +135,10 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
@computed get numberButton() {
const numBtnType: string = StrCast(this.rootDoc.numBtnType);
const numScript = ScriptCast(this.rootDoc.script);
- const setValue = (value: number) => UndoManager.RunInBatch(() => numScript?.script.run({ value, _readOnly_: false }), 'set num value');
+ const setValue = (value: number) => UndoManager.RunInBatch(() => numScript?.script.run({ self: this.rootDoc, value, _readOnly_: false }), 'set num value');
// Script for checking the outcome of the toggle
- const checkResult = Number(numScript?.script.run({ value: 0, _readOnly_: true }).result ?? 0).toPrecision(NumCast(this.dataDoc.numPrecision, 3));
+ const checkResult = Number(numScript?.script.run({ self: this.rootDoc, value: 0, _readOnly_: true }).result ?? 0).toPrecision(NumCast(this.dataDoc.numPrecision, 3));
const label = !FontIconBox.GetShowLabels() ? null : <div className="fontIconBox-label">{this.label}</div>;
@@ -149,7 +151,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
min={NumCast(this.rootDoc.numBtnMin, 0)}
max={NumCast(this.rootDoc.numBtnMax, 100)}
value={checkResult}
- className={'menu-slider'}
+ className="menu-slider"
onPointerDown={() => (this._batch = UndoManager.StartBatch('presDuration'))}
onPointerUp={() => this._batch?.end()}
onChange={e => {
@@ -283,27 +285,23 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
text = 'User Default';
}
noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Stacking, CollectionViewType.NoteTaking];
- } 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'];
- }
+ } 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 = this.buttonList
- .filter(value => !Doc.noviceMode || noviceList.includes(value))
+ .filter(value => !Doc.noviceMode || !noviceList.length || noviceList.includes(value))
.map(value => (
<div
className="list-item"
key={`${value}`}
style={{
- fontFamily: script.script.originalScript.startsWith('setFont') ? value : undefined,
+ fontFamily: script.script.originalScript.startsWith('{ return setFont') ? value : undefined,
backgroundColor: value === text ? Colors.LIGHT_BLUE : undefined,
}}
- onClick={undoBatch(() => script.script.run({ value }))}>
+ onClick={undoBatch(() => script.script.run({ self: this.rootDoc, value }))}>
{value[0].toUpperCase() + value.slice(1)}
</div>
));
@@ -356,7 +354,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
ev.preventDefault();
ev.stopPropagation();
const s = this.colorScript;
- s && undoBatch(() => s.script.run({ value: Utils.colorString(value), _readOnly_: false }).result)();
+ 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} />;
@@ -367,7 +365,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
@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 curColor = this.colorScript?.script.run({ self: this.rootDoc, value: undefined, _readOnly_: true }).result ?? 'transparent';
const label =
!this.label || !FontIconBox.GetShowLabels() ? null : (
@@ -376,13 +374,6 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
</div>
);
- // dropdown caret seems superfluous since clicking the color button does the same thing
- // const dropdownCaret = <div
- // className="menuButton-dropDown"
- // style={{ borderBottomRightRadius: this.dropdown ? 0 : undefined }}>
- // <FontAwesomeIcon icon={'caret-down'} color={color} size="sm" />
- // </div>;
- //setTimeout(() => this.colorPicker(curColor)); // cause an update to the color picker rendered in MainView
return (
<div
className={`menuButton ${this.type + (FontIconBox.GetShowLabels() ? 'Label' : '')} ${this.colorPickerClosed}`}
@@ -551,11 +542,30 @@ ScriptingGlobals.add(function setView(view: string) {
// toggle: Set overlay status of selected document
ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: boolean) {
- const selected = SelectionManager.Views().lastElement()?.props.Document ?? LinkManager.currentLink;
- if (checkResult) {
- return selected?._backgroundColor ?? 'transparent';
+ const selectedViews = SelectionManager.Views();
+ if (selectedViews.length) {
+ if (checkResult) {
+ const selView = selectedViews.lastElement();
+ const layoutFrameNumber = Cast(selView.props.ContainingCollectionDoc?._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).backgroundColor ?? 'transparent';
+ }
+ selectedViews.forEach(dv => {
+ const layoutFrameNumber = Cast(dv.props.ContainingCollectionDoc?._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, { backgroundColor: color });
+ } else {
+ dv.rootDoc._backgroundColor = 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));
}
- if (selected) selected._backgroundColor = color;
});
// toggle: Set overlay status of selected document
@@ -578,121 +588,70 @@ ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) {
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) {
- if (checkResult) return RichTextMenu.Instance?.fontFamily;
- font && RichTextMenu.Instance.setFontFamily(font);
-});
-
-ScriptingGlobals.add(function getActiveTextInfo(info: 'family' | 'size' | 'color' | 'highlight') {
- const editorView = RichTextMenu.Instance.TextView?.EditorView;
- const style = editorView?.state && RichTextMenu.Instance.getActiveFontStylesOnSelection();
- // prettier-ignore
- 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) {
+ScriptingGlobals.add(function setFontAttr(attr: 'font' | 'fontColor' | 'highlight' | 'fontSize', value: any, 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';
- }
- editorView?.state && RichTextMenu.Instance.changeListType(mapStyle);
-});
-
-// toggle: Set overlay status of selected document
-ScriptingGlobals.add(function setFontColor(color?: string, checkResult?: boolean) {
- if (checkResult) return RichTextMenu.Instance.fontColor;
- color && RichTextMenu.Instance.setColor(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;
+ // prettier-ignore
+ const map: Map<'font'|'fontColor'|'highlight'|'fontSize', { checkResult: () => any; setDoc: () => void; setMode?: () => void }> = new Map([
+ ['font', {
+ checkResult: () => RichTextMenu.Instance?.fontFamily,
+ setDoc: () => value && RichTextMenu.Instance.setFontFamily(value),
+ setMode: () => Doc.UserDoc().textAlign = 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 (selected ?? Doc.UserDoc())._fontHighlight;
+ return map.get(attr)?.checkResult();
}
- color && RichTextMenu.Instance.setHighlight(color);
+ if (editorView?.state) map.get(attr)?.setDoc();
+ else map.get(attr)?.setMode?.();
});
-// toggle: Set overlay status of selected document
-ScriptingGlobals.add(function setFontSize(size: string | number, checkResult?: boolean) {
- if (checkResult) {
- return RichTextMenu.Instance?.fontSize.replace('px', '');
- }
- if (typeof size === 'number') size = size.toString();
- if (size && Number(size).toString() === size) size += 'px';
- RichTextMenu.Instance.setFontSize(size);
-});
-ScriptingGlobals.add(function toggleNoAutoLinkAnchor(checkResult?: boolean) {
- const editorView = RichTextMenu.Instance?.TextView?.EditorView;
- if (checkResult) {
- return (editorView ? RichTextMenu.Instance.noAutoLink : false) ? Colors.MEDIUM_BLUE : 'transparent';
- }
- if (editorView) RichTextMenu.Instance?.toggleNoAutoLinkAnchor();
-});
-ScriptingGlobals.add(function toggleDictation(checkResult?: boolean) {
+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;
- if (checkResult) {
- return textView?._recording ? Colors.MEDIUM_BLUE : 'transparent';
- }
- if (textView) runInAction(() => (textView._recording = !textView._recording));
-});
-
-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';
+ 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() {
@@ -812,62 +771,39 @@ function setActiveTool(tool: InkTool | GestureUtils.Gestures, keepPrim: boolean,
ScriptingGlobals.add(setActiveTool, 'sets the active ink tool mode');
// toggle: Set overlay status of selected document
-ScriptingGlobals.add(function setIsInkMask(checkResult?: boolean) {
- const selected = SelectionManager.Docs().lastElement();
- if (checkResult) {
- if (selected?.type === DocumentType.INK) {
- return BoolCast(selected.isInkMask) ? Colors.MEDIUM_BLUE : 'transparent';
- }
- return ActiveIsInkMask() ? Colors.MEDIUM_BLUE : 'transparent';
- }
- SetActiveIsInkMask(!ActiveIsInkMask());
- SelectionManager.Docs()
- .filter(doc => doc.type === DocumentType.INK)
- .map(doc => (doc.isInkMask = !doc.isInkMask));
-});
-
-// toggle: Set overlay status of selected document
-ScriptingGlobals.add(function setFillColor(color?: string, checkResult?: boolean) {
+ScriptingGlobals.add(function setInkProperty(option: 'inkMask' | 'fillColor' | 'strokeWidth' | 'strokeColor', value: any, 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)));
-});
+ // 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.isInkMask) : ActiveIsInkMask()) ? Colors.MEDIUM_BLUE : 'transparent'),
+ setInk: (doc: Doc) => (doc.isInkMask = !doc.isInkMask),
+ setMode: () => selected?.type !== DocumentType.INK && SetActiveIsInkMask(!ActiveIsInkMask()),
+ }],
+ ['fillColor', {
+ checkResult: () => (selected?.type === DocumentType.INK ? StrCast(selected.fillColor) : ActiveFillColor() ? Colors.MEDIUM_BLUE : 'transparent'),
+ setInk: (doc: Doc) => (doc.fillColor = StrCast(value)),
+ setMode: () => SetActiveFillColor(StrCast(value)),
+ }],
+ [ 'strokeWidth', {
+ checkResult: () => (selected?.type === DocumentType.INK ? NumCast(selected.strokeWidth) : ActiveInkWidth()),
+ setInk: (doc: Doc) => (doc.strokeWidth = NumCast(value)),
+ setMode: () => SetActiveInkWidth(value.toString()),
+ }],
+ ['strokeColor', {
+ checkResult: () => (selected?.type === DocumentType.INK ? NumCast(selected.color) : ActiveInkColor()),
+ setInk: (doc: Doc) => (doc.color = String(value)),
+ setMode: () => SetActiveInkColor(StrCast(value)),
+ }],
+ ]);
-// 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();
+ return map.get(option)?.checkResult();
}
- SetActiveInkColor(StrCast(color));
+ map.get(option)?.setMode();
SelectionManager.Docs()
.filter(doc => doc.type === DocumentType.INK)
- .map(doc => (doc.color = String(color)));
+ .map(doc => map.get(option)?.setInk(doc));
});
/** WEB