import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Tooltip } from '@material-ui/core'; import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; import { Doc, Opt } from "../../fields/Doc"; import { Id } from "../../fields/FieldSymbols"; import { InkField } from '../../fields/InkField'; import { RichTextField } from '../../fields/RichTextField'; import { BoolCast, StrCast } from "../../fields/Types"; import { ImageField } from "../../fields/URLField"; import { DocUtils } from '../documents/Documents'; import { DocumentType } from '../documents/DocumentTypes'; import { SelectionManager } from '../util/SelectionManager'; import { undoBatch } from '../util/UndoManager'; import { CollectionViewType } from './collections/CollectionView'; import { Colors } from "./global/globalEnums"; import { InkingStroke } from './InkingStroke'; import { DocumentView } from './nodes/DocumentView'; import { VideoBox } from "./nodes/VideoBox"; import { pasteImageBitmap } from "./nodes/WebBoxRenderer"; import './PropertiesButtons.scss'; import React = require("react"); const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; enum UtilityButtonState { Default, OpenRight, OpenExternally } @observer export class PropertiesButtons extends React.Component<{}, {}> { @observable public static Instance: PropertiesButtons; @computed get selectedDoc() { return SelectionManager.SelectedSchemaDoc() || SelectionManager.Views().lastElement()?.rootDoc; } @computed get selectedTabView() { return !SelectionManager.SelectedSchemaDoc() && SelectionManager.Views().lastElement()?.topMost; } propertyToggleBtn = (label: string, property: string, tooltip: (on?: any) => string, icon: (on: boolean) => string, onClick?: (dv: Opt, doc: Doc, property: string) => void, useUserDoc?: boolean) => { const targetDoc = useUserDoc ? Doc.UserDoc() : this.selectedDoc; const onPropToggle = (dv: Opt, doc: Doc, prop: string) => (dv?.layoutDoc || doc)[prop] = (dv?.layoutDoc || doc)[prop] ? false : true; return !targetDoc ? (null) : {tooltip(targetDoc?.[property])} } placement="top">
e.stopPropagation()} onClick={undoBatch(() => { if (SelectionManager.Views().length > 1) { SelectionManager.Views().forEach(dv => (onClick ?? onPropToggle)(dv, dv.rootDoc, property)); } else if (targetDoc) (onClick ?? onPropToggle)(undefined, targetDoc, property); })} >
{label}
; } @computed get lockButton() { return this.propertyToggleBtn("No\xA0Drag", "_lockedPosition", on => `${on ? "Unlock" : "Lock"} position to prevent dragging`, on => "thumbtack"); } @computed get dictationButton() { return this.propertyToggleBtn("Dictate", "_showAudio", on => `${on ? "Hide" : "Show"} dictation/recording controls`, on => "microphone"); } @computed get maskButton() { return this.propertyToggleBtn("Mask", "isInkMask", on => on ? "Make plain ink" : "Make highlight mask", on => "paint-brush", (dv, doc) => InkingStroke.toggleMask(dv?.layoutDoc || doc)); } @computed get clustersButton() { return this.propertyToggleBtn("Clusters", "_useClusters", on => `${on ? "Hide" : "Show"} clusters`, on => "braille"); } @computed get panButton() { return this.propertyToggleBtn("Lock\xA0View", "_lockedTransform", on => `${on ? "Unlock" : "Lock"} panning of view`, on => "lock"); } @computed get fitContentButton() { return this.propertyToggleBtn("View All", "_fitContentsToBox", on => `${on ? "Don't" : "Do"} fit content to container visible area`, on => "eye"); } @computed get fitWidthButton() { return this.propertyToggleBtn("Fit\xA0Width", "_fitWidth", on => `${on ? "Don't" : "Do"} fit content to width of container`, on => "arrows-alt-h"); } @computed get captionButton() { return this.propertyToggleBtn("Caption", "_showCaption", on => `${on ? "Hide" : "Show"} caption footer`, on => "closed-captioning", (dv, doc) => (dv?.rootDoc || doc)._showCaption = (dv?.rootDoc || doc)._showCaption === undefined ? "caption" : undefined); } @computed get chromeButton() { return this.propertyToggleBtn("Controls", "_chromeHidden", on => `${on ? "Show" : "Hide"} editing UI`, on => "edit", (dv, doc) => (dv?.rootDoc || doc)._chromeHidden = !(dv?.rootDoc || doc)._chromeHidden); } @computed get titleButton() { return this.propertyToggleBtn("Title", "_showTitle", on => "Switch between title styles", on => "text-width", (dv, doc) => (dv?.rootDoc || doc)._showTitle = !(dv?.rootDoc || doc)._showTitle ? "title" : (dv?.rootDoc || doc)._showTitle === "title" ? "title:hover" : undefined); } @computed get autoHeightButton() { return this.propertyToggleBtn("Auto\xA0Size", "_autoHeight", on => `Automatical vertical sizing to show all content`, on => "arrows-alt-v"); } @computed get gridButton() { return this.propertyToggleBtn("Grid", "_backgroundGridShow", on => `Display background grid in collection`, on => "border-all"); } @computed get groupButton() { return this.propertyToggleBtn("Group", "isGroup", on => `Display collection as a Group`, on => "object-group", (dv, doc) => { doc.isGroup = !doc.isGroup; doc.forceActive = doc.isGroup; }); } @computed get freezeThumb() { return this.propertyToggleBtn("Freeze\Thumb", "_thumb-frozen", on => `${on ? "Freeze" : "Unfreeze"} thumbnail`, on => "arrows-alt-h", (dv, doc) => { if (doc["thumb-frozen"]) doc["thumb-frozen"] = undefined; else { document.body.focus(); // so that we can access the clipboard without an error setTimeout(() => pasteImageBitmap((data_url: any, error: any) => { error && console.log(error); data_url && VideoBox.convertDataUri(data_url, doc[Id] + "-thumb-frozen", true).then( returnedfilename => doc["thumb-frozen"] = new ImageField(returnedfilename)); })); } }); } @computed get snapButton() { return this.propertyToggleBtn("Snap\xA0Lines", "showSnapLines", on => `Display snapping lines when objects are dragged`, on => "border-all", undefined, true); } @computed get onClickButton() { return !this.selectedDoc ? (null) : Choose onClick behavior} placement="top">
e.stopPropagation()} >
onclick
; } @computed get perspectiveButton() { return !this.selectedDoc ? (null) : Choose view perspective} placement="top">
e.stopPropagation()} >
Perspective
; } @undoBatch handlePerspectiveChange = (e: any) => { this.selectedDoc && (this.selectedDoc._viewType = e.target.value); SelectionManager.Views().filter(dv => dv.docView).map(dv => dv.docView!).forEach(docView => docView.layoutDoc._viewType = e.target.value); } @undoBatch @action handleOptionChange = (onClick: string) => { this.selectedDoc && (this.selectedDoc.onClickBehavior = onClick); SelectionManager.Views().filter(dv => dv.docView).map(dv => dv.docView!).forEach(docView => { docView.noOnClick(); switch (onClick) { case "enterPortal": docView.makeIntoPortal(); break; case "toggleDetail": docView.setToggleDetail(); break; case "linkInPlace": docView.toggleFollowLink("inPlace", true, false); break; case "linkOnRight": docView.toggleFollowLink("add:right", false, false); break; } }); } @undoBatch editOnClickScript = () => { if (SelectionManager.Views().length) SelectionManager.Views().forEach(dv => DocUtils.makeCustomViewClicked(dv.rootDoc, undefined, "onClick")); else this.selectedDoc && DocUtils.makeCustomViewClicked(this.selectedDoc, undefined, "onClick"); } @computed get onClickFlyout() { const buttonList = [ ["nothing", "Select Document"], ["enterPortal", "Enter Portal"], ["toggleDetail", "Toggle Detail"], ["linkInPlace", "Follow Link"], ["linkOnRight", "Open Link on Right"] ]; const currentSelection = this.selectedDoc.onClickBehavior; // Get items to place into the list const list = buttonList.map((value) => { const click = () => { this.handleOptionChange(value[0]); }; return
{value[1]}
; }); return
{list}
{Doc.noviceMode ? (null) :
Edit onClick Script
}
; } @computed get onPerspectiveFlyout() { const excludedViewTypes = [CollectionViewType.Invalid, CollectionViewType.Docking, CollectionViewType.Pile, CollectionViewType.StackedTimeline, CollectionViewType.Linear]; const makeLabel = (value: string, label: string) =>
; return
{Object.values(CollectionViewType).filter(type => !excludedViewTypes.includes(type)).map(type => makeLabel(type, type))}
; } render() { const layoutField = this.selectedDoc?.[Doc.LayoutFieldKey(this.selectedDoc)]; const isText = layoutField instanceof RichTextField; const isInk = layoutField instanceof InkField; const isMap = this.selectedDoc?.type === DocumentType.MAP; const isCollection = this.selectedDoc?.type === DocumentType.COL; const isStacking = this.selectedDoc?._viewType === CollectionViewType.Stacking; const isFreeForm = this.selectedDoc?._viewType === CollectionViewType.Freeform; const isTree = this.selectedDoc?._viewType === CollectionViewType.Tree; const isTabView = this.selectedTabView; const toggle = (ele: JSX.Element | null, style?: React.CSSProperties) =>
{ele}
; const isNovice = Doc.noviceMode; return !this.selectedDoc ? (null) :
{toggle(this.titleButton)} {toggle(this.captionButton)} {toggle(this.lockButton)} {toggle(this.dictationButton, { display: isNovice ? "none" : "" })} {toggle(this.onClickButton)} {toggle(this.fitWidthButton)} {toggle(this.freezeThumb)} {toggle(this.fitContentButton, { display: !isFreeForm && !isMap ? "none" : "" })} {toggle(this.autoHeightButton, { display: !isText && !isStacking && !isTree ? "none" : "" })} {toggle(this.maskButton, { display: !isInk ? "none" : "" })} {toggle(this.chromeButton, { display: !isCollection || isNovice ? "none" : "" })} {toggle(this.gridButton, { display: !isCollection ? "none" : "" })} {toggle(this.groupButton, { display: isTabView || !isCollection ? "none" : "" })} {toggle(this.snapButton, { display: !isCollection ? "none" : "" })} {toggle(this.clustersButton, { display: !isFreeForm ? "none" : "" })} {toggle(this.panButton, { display: !isFreeForm ? "none" : "" })} {toggle(this.perspectiveButton, { display: !isCollection || isNovice ? "none" : "" })}
; } }