diff options
Diffstat (limited to 'src/client/views/nodes/button/FontIconBox.tsx')
-rw-r--r-- | src/client/views/nodes/button/FontIconBox.tsx | 295 |
1 files changed, 295 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..f98d01dfc --- /dev/null +++ b/src/client/views/nodes/button/FontIconBox.tsx @@ -0,0 +1,295 @@ +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { Tooltip } from '@material-ui/core'; +import { action, computed, observable } from 'mobx'; +import { observer } from 'mobx-react'; +import React from 'react'; +import { ColorState, SketchPicker } from 'react-color'; +import { Doc, StrListCast } from '../../../../fields/Doc'; +import { createSchema, makeInterface } from '../../../../fields/Schema'; +import { ScriptField } from '../../../../fields/ScriptField'; +import { BoolCast, Cast, StrCast } from '../../../../fields/Types'; +import { SelectionManager } from '../../../util/SelectionManager'; +import { ColorScheme } from '../../../util/SettingsManager'; +import { undoBatch, UndoManager } from '../../../util/UndoManager'; +import { ContextMenu } from '../../ContextMenu'; +import { DocComponent } from '../../DocComponent'; +import { StyleProp } from '../../StyleProvider'; +import { FieldView, FieldViewProps } from '../FieldView'; +import { FontIconBadge } from './FontIconBadge'; +import './FontIconBox.scss'; +const FontIconSchema = createSchema({ + icon: "string", +}); + +export enum ButtonType { + MenuButton = "menuBtn", + DropdownList = "drpdownList", + DropdownButton = "drpdownBtn", + ClickButton = "clickBtn", + DoubleButton = "dblBtn", + ToggleButton = "tglBtn", + ColorButton = "colorBtn" +} + +type FontIconDocument = makeInterface<[typeof FontIconSchema]>; +const FontIconDocument = makeInterface(FontIconSchema); +@observer +export class FontIconBox extends DocComponent<FieldViewProps, 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 color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color); + @observable private backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor); + @observable private icon = StrCast(this.dataDoc.icon, "user") as any; + @observable private dropdown: boolean = BoolCast(this.rootDoc.dropDownOpen); + @observable private dropdownDirection: string = StrCast(this.rootDoc.dropDownDirection); + @observable private buttonList: string[] = StrListCast(this.rootDoc.btnList); + @observable private activeFont: string = StrCast(Doc.UserDoc()._fontFamily); + @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 + **/ + + /** + * Dropdown button + */ + @computed get dropdownButton() { + const active: string = StrCast(this.rootDoc.dropDownOpen); + return ( + <div className={`menuButton ${this.type} ${active}`} + style={{ color: "black", borderBottomLeftRadius: this.dropdown ? 0 : undefined }} + onClick={action(() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen)}> + <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={this.color} /> + {!this.label || !Doc.UserDoc()._showLabel ? (null) : <div className="fontIconBox-label" style={{ color: this.color, backgroundColor: this.backgroundColor }}> {this.label} </div>} + <div + className="menuButton-dropdown" + style={{ borderBottomRightRadius: this.dropdown ? 0 : undefined }}> + <FontAwesomeIcon icon={'caret-down'} color={"black"} size="sm" /> + </div> + {this.rootDoc.dropDownOpen ? + <div className="menuButton-dropdownBox" + style={{ left: 0 }}> + {/* DROPDOWN BOX CONTENTS */} + </div> : null} + </div> + ); + } + + @undoBatch setColor = action((color: ColorState, docColor?: string, userColor?: string) => { + console.log(docColor, userColor); + if (docColor) { + const numSelected = SelectionManager.Views().length; + const selectedDoc = numSelected > 0 ? SelectionManager.Views()[0].Document : undefined; + eval(docColor); + } + else if (userColor) { + const userDoc = Doc.UserDoc(); + eval(userColor); + } + }); + + + + /** + * Default + */ + @computed get defaultButton() { + 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: this.color, backgroundColor: this.backgroundColor }}> {this.label} </div>} + <FontIconBadge collection={Cast(this.rootDoc.watchedDocuments, Doc, null)} /> + </div> + </div> + ) + } + + + render() { + // Variables called through eval (from button) + const canUndo: boolean = UndoManager.CanUndo(); + const canRedo: boolean = UndoManager.CanRedo(); + const numSelected = SelectionManager.Views().length; + const selectedDoc = numSelected > 0 ? SelectionManager.Views()[0].Document : undefined; + const userDoc = Doc.UserDoc(); + + // Toggle and canClick properties as determined from the variable passed into the button doc + // const toggle = this.rootDoc.toggle ? ScriptCast(this.rootDoc.toggle) : undefined; + const canClick: boolean = this.rootDoc.canClick ? eval(StrCast(this.rootDoc.canClick)) : false; + // if (toggle) { + // console.log(StrCast(this.rootDoc.title), toggle); + // toggle.script.run(); + // } + const dark: boolean = Doc.UserDoc().colorScheme === ColorScheme.Dark; + + const active: string = StrCast(this.rootDoc.dropDownOpen); + const label = !this.label || !Doc.UserDoc()._showLabel ? (null) : + <div className="fontIconBox-label" style={{ color: this.color, backgroundColor: this.backgroundColor }}> + {this.label} + </div>; + const menuLabel = !this.label || !Doc.UserDoc()._showMenuLabel ? (null) : + <div className="fontIconBox-label" style={{ color: this.color, backgroundColor: this.backgroundColor }}> + {this.label} + </div>; + const dropdownCaret = <div + className="menuButton-dropDown" + style={{ borderBottomRightRadius: this.dropdown ? 0 : undefined }}> + <FontAwesomeIcon icon={'caret-down'} color={"black"} size="sm" /> + </div>; + const colorBox = (func: (color: ColorState) => void) => <SketchPicker onChange={func} color={StrCast(this.backgroundColor)} + presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', + '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', + '#FFFFFF', '#f1efeb', 'transparent']} />; + const items = this.buttonList.map((value) => { + return <div className="list-item" + style={{ fontFamily: value }} + onClick={() => Doc.UserDoc()._fontFamily = value}> + {value} + </div>; + }); + + /** + * Menu Panel Button: menuBtn + * Dropdown Button: dropDownBtn + * doubleBtn + **/ + + // CODEDUMP: glr + // const presSize = type === ButtonType.MenuButton ? 30 : 25; + // const presTrailsIcon = <img src={`/assets/${"presTrails.png"}`} + // style={{ width: presSize, height: presSize, filter: `invert(${this.color === "white" ? "100%" : "0%"})`, marginBottom: "5px" }} />; + + // TODO:glr Add label of button type + let button = ( + <> + {this.defaultButton} + </> + ); + + switch (this.type) { + case ButtonType.DropdownButton: + button = ( + <> + {this.dropdownButton} + </> + ); + break; + case ButtonType.DropdownList: + button = ( + <div className={`menuButton ${this.type} ${active}`} + style={{ backgroundColor: this.rootDoc.dropDownOpen ? "#aeddf880" : undefined, color: this.rootDoc.dropDownOpen ? "#1c5c96" : "black", borderBottomLeftRadius: this.dropdown ? 0 : undefined }} + onClick={() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen}> + {/* {toggle} */} + {label} + {dropdownCaret} + {this.rootDoc.dropDownOpen ? + <> + <div className="menuButton-dropdownList" + style={{ left: 0 }}> + {items} + </div> + <div className="dropbox-background" onClick={(e) => { e.stopPropagation(); this.rootDoc.dropDownOpen = false; }} /> + </> + : null} + </div> + ); + break; + case ButtonType.ColorButton: + button = ( + <div className={`menuButton ${this.type} ${active}`} + style={{ opacity: selectedDoc ? 1 : 0.5, color: dark ? "white" : "black", borderBottomLeftRadius: this.dropdown ? 0 : undefined }} + onClick={() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen} + onPointerDown={e => e.stopPropagation()}> + <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={dark ? "white" : "black"} /> + {label} + {dropdownCaret} + {this.rootDoc.dropDownOpen ? + <> + <div className="menuButton-dropdownBox" + onPointerDown={e => e.stopPropagation()} + onClick={e => e.stopPropagation()} + style={{ left: 0 }}> + {colorBox((color) => this.setColor(color, StrCast(this.rootDoc.docColor), StrCast(this.rootDoc.userColor)))} + </div> + <div className="dropbox-background" onClick={(e) => { e.stopPropagation(); this.rootDoc.dropDownOpen = false; }} /> + </> + : null} + </div> + ); + break; + // case ButtonType.ToggleButton: + // button = ( + // <div className={`menuButton ${this.type}`} style={{ opacity: canClick ? 1 : 0.4, backgroundColor: toggle ? this.backgroundColor : undefined }}> + // <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={toggle ? this.color : this.backgroundColor} /> + // {label} + // </div> + // ); + // break; + case ButtonType.ClickButton: + button = ( + <div className={`menuButton ${this.type}`} style={{ color: this.color, backgroundColor: this.backgroundColor, opacity: canClick ? 1 : 0.4 }}> + <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={this.color} /> + {label} + </div> + ); + break; + case ButtonType.DoubleButton: + button = ( + <div className={`menuButton ${this.type}`} style={{ color: this.color, backgroundColor: this.backgroundColor }}> + <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={this.color} /> + {label} + </div> + ); + break; + case ButtonType.MenuButton: + button = ( + <div className={`menuButton ${this.type}`} style={{ color: dark ? "white" : "black", backgroundColor: dark ? "black" : "lightgrey" }}> + <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={dark ? "white" : "black"} /> + {menuLabel} + </div > + // <div className={`menuButton ${type}`} style={{ color, backgroundColor }}> + // <FontAwesomeIcon className={`fontIconBox-icon-${type}`} icon={icon} color={color} /> + // {label} + // </div> + ); + break; + default: + break; + } + + return !this.layoutDoc.toolTip ? button : + <Tooltip title={<div className="dash-tooltip">{StrCast(this.layoutDoc.toolTip)}</div>}> + {button} + </Tooltip>; + } +} |