From ded69655dabf97c76f97271e7da8e77e3f33ec25 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 15 Mar 2021 03:36:35 -0400
Subject: getting webBox's to work like PdfBox's - text selection & marquee.

---
 src/client/views/PropertiesButtons.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'src/client/views/PropertiesButtons.tsx')

diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index bf72dbdba..46d5b2f71 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -153,7 +153,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
                             e.preventDefault();
                             let googleDoc = await Cast(dataDoc.googleDoc, Doc);
                             if (!googleDoc) {
-                                const options = { _width: 600, _nativeWidth: 960, _nativeHeight: 800, isAnnotating: false, useCors: false };
+                                const options = { _width: 600, _nativeWidth: 960, _nativeHeight: 800, useCors: false };
                                 googleDoc = Docs.Create.WebDocument(googleDocUrl, options);
                                 dataDoc.googleDoc = googleDoc;
                             }
-- 
cgit v1.2.3-70-g09d2


From 82f319ddf3e70095b04473ecce8790f4524e8939 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 16 Mar 2021 12:03:20 -0400
Subject: cleaned up propertiesbuttons a bit.  added lockTransform button. 
 changed chromeStatus disabled to be undefined.

---
 src/client/documents/Documents.ts                  |   2 +-
 src/client/util/CurrentUserUtils.ts                |  37 ++-
 src/client/views/InkingStroke.tsx                  |   2 -
 src/client/views/PropertiesButtons.tsx             | 300 ++++++---------------
 src/client/views/TemplateMenu.tsx                  |   4 +-
 .../collections/CollectionMasonryViewFieldRow.tsx  |   4 +-
 .../views/collections/CollectionPileView.tsx       |   2 +-
 src/client/views/collections/SchemaTable.tsx       |   2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |   5 -
 src/client/views/nodes/DocumentView.tsx            |   4 +-
 src/client/views/nodes/PresBox.tsx                 |   2 +-
 .../views/nodes/formattedText/FormattedTextBox.tsx |   2 +-
 12 files changed, 107 insertions(+), 259 deletions(-)

(limited to 'src/client/views/PropertiesButtons.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 6e892cb6e..71fc5c40d 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -822,7 +822,7 @@ export namespace Docs {
             const webProto = Prototypes.get(DocumentType.WEB);
             webProto.scrollHeight = 100000;  // backward compatibility -- can be removed after db is reset
             webProto._fitWidth = true;  // backward compatibility -- can be removed after db is reset
-            return InstanceFromProto(webProto, url ? new WebField(new URL(url)) : undefined, { _chromeStatus: url ? "disabled" : "enabled", _lockedTransform: true, ...options });
+            return InstanceFromProto(webProto, url ? new WebField(new URL(url)) : undefined, { _chromeStatus: url ? undefined : "enabled", _lockedTransform: true, ...options });
         }
 
         export function HtmlDocument(html: string, options: DocumentOptions = {}) {
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 9dda90353..6566f5f78 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -81,7 +81,7 @@ export class CurrentUserUtils {
                     Docs.Create.MulticolumnDocument([], { title: "data", _height: 200, system: true }),
                     Docs.Create.TextDocument("", { title: "text", _height: 100, system: true })
                 ],
-                { _width: 400, _height: 300, title: "slideView", _chromeStatus: "disabled", _xMargin: 3, _yMargin: 3, system: true }
+                { _width: 400, _height: 300, title: "slideView", _xMargin: 3, _yMargin: 3, system: true }
             );
             slideTemplate.isTemplateDoc = makeTemplate(slideTemplate);
             doc["template-button-slides"] = CurrentUserUtils.ficon({
@@ -193,7 +193,7 @@ export class CurrentUserUtils {
             };
             details.text = new RichTextField(JSON.stringify(detailedTemplate), buxtonFieldKeys.join(" "));
 
-            const shared = { _chromeStatus: "disabled", _autoHeight: true, _xMargin: 0 };
+            const shared = { _autoHeight: true, _xMargin: 0 };
             const detailViewOpts = { title: "detailView", _width: 300, _fontFamily: "Arial", _fontSize: "12px" };
             const descriptionWrapperOpts = { title: "descriptions", _height: 300, _columnWidth: -1, treeViewHideTitle: true, _pivotField: "title", system: true };
 
@@ -228,7 +228,7 @@ export class CurrentUserUtils {
                 title: "Advanced Item Prototypes", _xMargin: 0, _showTitle: "title",
                 hidden: ComputedField.MakeFunction("IsNoviceMode()") as any,
                 _stayInCollection: true, _hideContextMenu: true,
-                _autoHeight: true, _width: 500, _height: 300, _fitWidth: true, _columnWidth: 35, ignoreClick: true, _lockedPosition: true, _chromeStatus: "disabled",
+                _autoHeight: true, _width: 500, _height: 300, _fitWidth: true, _columnWidth: 35, ignoreClick: true, _lockedPosition: true,
                 dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }), system: true
             }));
         } else {
@@ -499,7 +499,7 @@ export class CurrentUserUtils {
         if (dragCreatorSet === undefined) {
             doc.myItemCreators = new PrefetchProxy(Docs.Create.MasonryDocument(creatorBtns, {
                 title: "Basic Item Creators", _showTitle: "title", _xMargin: 0, _stayInCollection: true, _hideContextMenu: true,
-                _autoHeight: true, _width: 500, _height: 300, _fitWidth: true, _columnWidth: 35, ignoreClick: true, _lockedPosition: true, _chromeStatus: "disabled",
+                _autoHeight: true, _width: 500, _height: 300, _fitWidth: true, _columnWidth: 35, ignoreClick: true, _lockedPosition: true,
                 dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }), system: true
             }));
         } else {
@@ -528,7 +528,7 @@ export class CurrentUserUtils {
         if (doc.mySearchPanelDoc === undefined) {
             doc.mySearchPanelDoc = new PrefetchProxy(Docs.Create.SearchDocument({
                 _width: 500, _height: 300, backgroundColor: "dimGray", ignoreClick: true, _searchDoc: true,
-                childDropAction: "alias", _lockedPosition: true, _viewType: CollectionViewType.Schema, _chromeStatus: "disabled", title: "sidebar search stack", system: true
+                childDropAction: "alias", _lockedPosition: true, _viewType: CollectionViewType.Schema, title: "sidebar search stack", system: true
             })) as any as Doc;
         }
     }
@@ -563,7 +563,7 @@ export class CurrentUserUtils {
                 backgroundColor: "black", ignoreClick: true,
                 _gridGap: 0,
                 _yMargin: 0,
-                _yPadding: 0, _xMargin: 0, _autoHeight: false, _width: 60, _columnWidth: 60, _lockedPosition: true, _chromeStatus: "disabled", system: true
+                _yPadding: 0, _xMargin: 0, _autoHeight: false, _width: 60, _columnWidth: 60, _lockedPosition: true, system: true
             }));
         }
         // this resets all sidebar buttons to being deactivated
@@ -596,7 +596,7 @@ export class CurrentUserUtils {
     // Sets up mobileMenu stacking document
     static setupMobileMenu() {
         const menu = new PrefetchProxy(Docs.Create.StackingDocument(this.setupMobileButtons(), {
-            _width: 980, ignoreClick: true, _lockedPosition: false, _chromeStatus: "disabled", title: "home", _yMargin: 100, system: true
+            _width: 980, ignoreClick: true, _lockedPosition: false, title: "home", _yMargin: 100, system: true
         }));
         return menu;
     }
@@ -627,26 +627,26 @@ export class CurrentUserUtils {
     static mobileButton = (opts: DocumentOptions, docs: Doc[]) => Docs.Create.MulticolumnDocument(docs, {
         ...opts,
         dropAction: undefined, removeDropProperties: new List<string>(["dropAction"]), _nativeWidth: 900, _nativeHeight: 250, _width: 900, _height: 250, _yMargin: 15,
-        borderRounding: "5px", boxShadow: "0 0", _chromeStatus: "disabled", system: true
+        borderRounding: "5px", boxShadow: "0 0", system: true
     }) as any as Doc
 
     // sets up the text container for the information contained within the mobile button
     static mobileTextContainer = (opts: DocumentOptions, docs: Doc[]) => Docs.Create.MultirowDocument(docs, {
         ...opts,
         dropAction: undefined, removeDropProperties: new List<string>(["dropAction"]), _nativeWidth: 450, _nativeHeight: 250, _width: 450, _height: 250, _yMargin: 25,
-        backgroundColor: "rgba(0,0,0,0)", borderRounding: "0", boxShadow: "0 0", _chromeStatus: "disabled", ignoreClick: true, system: true
+        backgroundColor: "rgba(0,0,0,0)", borderRounding: "0", boxShadow: "0 0", ignoreClick: true, system: true
     }) as any as Doc
 
     // Sets up the title of the button
     static mobileButtonText = (opts: DocumentOptions, buttonTitle: string) => Docs.Create.TextDocument(buttonTitle, {
         ...opts,
-        dropAction: undefined, title: buttonTitle, _fontSize: "37px", _xMargin: 0, _yMargin: 0, ignoreClick: true, _chromeStatus: "disabled", backgroundColor: "rgba(0,0,0,0)", system: true
+        dropAction: undefined, title: buttonTitle, _fontSize: "37px", _xMargin: 0, _yMargin: 0, ignoreClick: true, backgroundColor: "rgba(0,0,0,0)", system: true
     }) as any as Doc
 
     // Sets up the description of the button
     static mobileButtonInfo = (opts: DocumentOptions, buttonInfo: string) => Docs.Create.TextDocument(buttonInfo, {
         ...opts,
-        dropAction: undefined, title: "info", _fontSize: "25px", _xMargin: 0, _yMargin: 0, ignoreClick: true, _chromeStatus: "disabled", backgroundColor: "rgba(0,0,0,0)", _dimMagnitude: 2, system: true
+        dropAction: undefined, title: "info", _fontSize: "25px", _xMargin: 0, _yMargin: 0, ignoreClick: true, backgroundColor: "rgba(0,0,0,0)", _dimMagnitude: 2, system: true
     }) as any as Doc
 
 
@@ -671,11 +671,11 @@ export class CurrentUserUtils {
     static setupThumbDoc(userDoc: Doc) {
         if (!userDoc.thumbDoc) {
             const thumbDoc = Docs.Create.LinearDocument(CurrentUserUtils.setupThumbButtons(userDoc), {
-                _width: 100, _height: 50, ignoreClick: true, _lockedPosition: true, _chromeStatus: "disabled", title: "buttons",
+                _width: 100, _height: 50, ignoreClick: true, _lockedPosition: true, title: "buttons",
                 _autoHeight: true, _yMargin: 5, linearViewIsExpanded: true, backgroundColor: "white", system: true
             });
             thumbDoc.inkToTextDoc = Docs.Create.LinearDocument([], {
-                _width: 300, _height: 25, _autoHeight: true, _chromeStatus: "disabled", linearViewIsExpanded: true, flexDirection: "column", system: true
+                _width: 300, _height: 25, _autoHeight: true, linearViewIsExpanded: true, flexDirection: "column", system: true
             });
             userDoc.thumbDoc = thumbDoc;
         }
@@ -695,7 +695,7 @@ export class CurrentUserUtils {
             title: "Mobile Upload Collection", backgroundColor: "white", _lockedPosition: true, system: true
         });
         return Docs.Create.StackingDocument([webDoc, uploadDoc], {
-            _width: screen.width, _lockedPosition: true, _chromeStatus: "disabled", title: "Upload", _autoHeight: true, _yMargin: 80, backgroundColor: "lightgray", system: true
+            _width: screen.width, _lockedPosition: true, title: "Upload", _autoHeight: true, _yMargin: 80, backgroundColor: "lightgray", system: true
         });
     }
 
@@ -715,7 +715,7 @@ export class CurrentUserUtils {
         if (doc.myCreators === undefined) {
             doc.myCreators = new PrefetchProxy(Docs.Create.StackingDocument([creatorBtns, templateBtns], {
                 title: "all Creators", _yMargin: 0, _autoHeight: true, _xMargin: 0, _fitWidth: true,
-                _width: 500, _height: 300, ignoreClick: true, _lockedPosition: true, _chromeStatus: "disabled", system: true
+                _width: 500, _height: 300, ignoreClick: true, _lockedPosition: true, system: true
             }));
         }
         // setup a color picker
@@ -728,7 +728,7 @@ export class CurrentUserUtils {
 
         if (doc.myTools === undefined) {
             const toolsStack = new PrefetchProxy(Docs.Create.StackingDocument([doc.myCreators as Doc, doc.myColorPicker as Doc], {
-                title: "My Tools", _width: 500, _yMargin: 20, ignoreClick: true, _lockedPosition: true, _chromeStatus: "disabled", _forceActive: true, system: true, _stayInCollection: true, _hideContextMenu: true,
+                title: "My Tools", _width: 500, _yMargin: 20, ignoreClick: true, _lockedPosition: true, _forceActive: true, system: true, _stayInCollection: true, _hideContextMenu: true,
             })) as any as Doc;
 
             doc.myTools = toolsStack;
@@ -831,7 +831,6 @@ export class CurrentUserUtils {
     static setupSidebarContainer(doc: Doc) {
         if (doc.sidebar === undefined) {
             const sidebarContainer = new Doc();
-            sidebarContainer._chromeStatus = "disabled";
             sidebarContainer.system = true;
             doc.sidebar = new PrefetchProxy(sidebarContainer);
         }
@@ -853,7 +852,7 @@ export class CurrentUserUtils {
     static blist = (opts: DocumentOptions, docs: Doc[]) => new PrefetchProxy(Docs.Create.LinearDocument(docs, {
         ...opts, _gridGap: 5, _xMargin: 5, _yMargin: 5, _height: 42, _width: 100, boxShadow: "0 0", _forceActive: true,
         dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }),
-        backgroundColor: "black", treeViewPreventOpen: true, _lockedPosition: true, _chromeStatus: "disabled", linearViewIsExpanded: true, system: true
+        backgroundColor: "black", treeViewPreventOpen: true, _lockedPosition: true, linearViewIsExpanded: true, system: true
     })) as any as Doc
 
     static ficon = (opts: DocumentOptions) => new PrefetchProxy(Docs.Create.FontIconDocument({
@@ -923,7 +922,7 @@ export class CurrentUserUtils {
         if (doc.myImportDocs === undefined) {
             doc.myImportDocs = new PrefetchProxy(Docs.Create.StackingDocument([], {
                 title: "My ImportDocuments", _forceActive: true, ignoreClick: true, _showTitle: "title", _stayInCollection: true, _hideContextMenu: true, childLimitHeight: 0,
-                childDropAction: "alias", _autoHeight: true, _yMargin: 50, _gridGap: 15, _lockedPosition: true, _chromeStatus: "disabled", system: true
+                childDropAction: "alias", _autoHeight: true, _yMargin: 50, _gridGap: 15, _lockedPosition: true, system: true
             }));
         }
         if (doc.myImportPanel === undefined) {
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 46586bf1b..31279338f 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -28,8 +28,6 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
 
     public static LayoutString(fieldStr: string) { return FieldView.LayoutString(InkingStroke, fieldStr); }
 
-
-
     private analyzeStrokes = () => {
         const data: InkData = Cast(this.dataDoc[this.fieldKey], InkField)?.inkData ?? [];
         CognitiveServices.Inking.Appliers.ConcatenateHandwriting(this.dataDoc, ["inkAnalysis", "handwriting"], [data]);
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index 46d5b2f71..e93abb67a 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -3,10 +3,10 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { Tooltip } from '@material-ui/core';
 import { action, computed, observable, runInAction } from "mobx";
 import { observer } from "mobx-react";
-import { Doc } from "../../fields/Doc";
+import { Doc, Opt } from "../../fields/Doc";
 import { InkField } from '../../fields/InkField';
 import { RichTextField } from '../../fields/RichTextField';
-import { Cast, NumCast, StrCast } from "../../fields/Types";
+import { BoolCast, Cast, NumCast, StrCast } from "../../fields/Types";
 import { ImageField } from '../../fields/URLField';
 import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager';
 import { Pulls, Pushes } from '../apis/google_docs/GoogleApiClientUtils';
@@ -16,10 +16,11 @@ import { DocumentType } from '../documents/DocumentTypes';
 import { SelectionManager } from '../util/SelectionManager';
 import { undoBatch } from '../util/UndoManager';
 import { CollectionDockingView } from './collections/CollectionDockingView';
+import { CollectionViewType } from './collections/CollectionView';
+import { DocumentView } from './nodes/DocumentView';
 import { GoogleRef } from "./nodes/formattedText/FormattedTextBox";
 import './PropertiesButtons.scss';
 import React = require("react");
-import { CollectionViewType } from './collections/CollectionView';
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -40,26 +41,19 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     private _pushAnimating = false;
     private _pullColorAnimating = false;
 
+    public static hasPushedHack = false;
+    public static hasPulledHack = false;
+
+    @observable public static Instance: PropertiesButtons;
+    @observable private openHover = UtilityButtonState.Default;
     @observable private pushIcon: IconProp = "arrow-alt-circle-up";
     @observable private pullIcon: IconProp = "arrow-alt-circle-down";
     @observable private pullColor: string = "white";
     @observable public isAnimatingFetch = false;
     @observable public isAnimatingPulse = false;
 
-    @observable private openHover: UtilityButtonState = UtilityButtonState.Default;
-
-    @observable public static Instance: PropertiesButtons;
-    public static hasPushedHack = false;
-    public static hasPulledHack = false;
-
-
     @computed get selectedDoc() { return SelectionManager.SelectedSchemaDoc() || this.selectedDocumentView?.rootDoc; }
-    @computed get selectedDocumentView() {
-        if (SelectionManager.Views().length) {
-            return SelectionManager.Views()[0];
-        } else return undefined;
-    }
-
+    @computed get selectedDocumentView() { return SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined; }
     @computed get onClick() { return this.selectedDoc?.onClickBehavior ? this.selectedDoc?.onClickBehavior : "nothing"; }
 
     public startPullOutcome = action((success: boolean) => {
@@ -185,27 +179,62 @@ export class PropertiesButtons extends React.Component<{}, {}> {
         </Tooltip>;
     }
 
-    @action @undoBatch
-    onLock = () => {
-        SelectionManager.Views().forEach(dv => dv.docView?.toggleLockPosition());
+    @action
+    makeMask = (inkDoc: Doc) => {
+        inkDoc.isInkMask = !inkDoc.isInkMask;
+        inkDoc._backgroundColor = inkDoc.isInkMask ? "rgba(0,0,0,0.7)" : undefined;
+        inkDoc.mixBlendMode = inkDoc.isInkMask ? "hard-light" : undefined;
+        inkDoc.color = "#9b9b9bff";
+        inkDoc._stayInCollection = inkDoc.isInkMask ? true : undefined;
     }
-
-    @computed
-    get lockButton() {
+    propToggleBtn = (label: string, property: string, tooltip: (on?: any) => string, icon: (on: boolean) => string, onClick?: (dv: Opt<DocumentView>, doc: Doc, property: string) => void) => {
         const targetDoc = this.selectedDoc;
+        const onPropToggle = (dv: Opt<DocumentView>, doc: Doc, prop: string) => (dv?.layoutDoc || doc)[prop] = (dv?.layoutDoc || doc)[prop] ? undefined : true;
         return !targetDoc ? (null) : <Tooltip
-            title={<div className="dash-tooltip">{`${this.selectedDoc?._lockedPosition ? "Unlock" : "Lock"} Position`}</div>} placement="top">
+            title={<div className={`dash-tooltip`}>{tooltip(targetDoc?.[property])} </div>} placement="top">
             <div>
-                <div className={`propertiesButtons-linkButton-empty toggle-${targetDoc._lockedPosition ? "on" : "off"}`} onPointerDown={this.onLock} >
-                    <FontAwesomeIcon className="documentdecorations-icon" size="lg"
-                        color={this.selectedDoc?._lockedPosition ? "black" : "white"}
-                        icon={this.selectedDoc?._lockedPosition ? "unlock" : "lock"} />
+                <div className={`propertiesButtons-linkButton-empty toggle-${StrCast(targetDoc[property]).includes(":hover") ? "hover" : targetDoc[property] ? "on" : "off"}`}
+                    onPointerDown={undoBatch(() => {
+                        if (SelectionManager.Views().length) {
+                            SelectionManager.Views().forEach(dv => (onClick ?? onPropToggle)(dv, dv.rootDoc, property));
+                        } else if (targetDoc) (onClick ?? onPropToggle)(undefined, targetDoc, property);
+                    })} >
+                    <FontAwesomeIcon className="documentdecorations-icon" size="lg" icon={icon(BoolCast(targetDoc?.[property])) as any} />
                 </div>
-                <div className="propertiesButtons-title"
-                >Position </div>
+                <div className="propertiesButtons-title">{label}</div>
             </div>
         </Tooltip>;
     }
+    @computed get lockButton() {
+        return this.propToggleBtn("Position", "_lockedPosition", on => `${on ? "Unlock" : "Lock"} XY location on freeform view`, on => on ? "unlock" : "lock");
+    }
+    @computed get panButton() {
+        return this.propToggleBtn("Pan", "_lockedTransform", on => `${on ? "Unlock" : "Lock"} panning of view`, on => on ? "unlock" : "lock");
+    }
+    @computed get dictationButton() {
+        return this.propToggleBtn("Dictate", "_showAudio", on => `${on ? "Hide" : "Show"} dictation/recording controls`, () => "microphone");
+    }
+    @computed get maskButton() {
+        return this.propToggleBtn("Mask", "isInkMask", on => on ? "Make plain ink" : "Make highlight mask", () => "paint-brush", (dv, doc) => this.makeMask(dv?.layoutDoc || doc));
+    }
+    @computed get clustersButton() {
+        return this.propToggleBtn("Clusters", "_useClusters", on => `${on ? "Hide" : "Show"} clusters`, () => "braille");
+    }
+    @computed get fitContentButton() {
+        return this.propToggleBtn("Fit All", "_fitToBox", on => `${on ? "Don't" : ""} fit content to container visible area`, on => on ? "expand-arrows-alt" : "compress-arrows-alt");
+    }
+    @computed get fitWidthButton() {
+        return this.propToggleBtn("Fit Wid", "_fitWidth", on => `${on ? "Don't" : ""} fit content to width of container`, on => on ? "arrows-alt-h" : "arrows-alt-h");
+    }
+    @computed get captionButton() {
+        return this.propToggleBtn("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.propToggleBtn("Controls", "_chromeStatus", on => `${on === "enabled" ? "Hide" : "Show"} editing UI`, on => "edit", (dv, doc) => (dv?.rootDoc || doc)._chromeStatus = (dv?.rootDoc || doc)._chromeStatus === undefined ? "enabled" : undefined);
+    }
+    @computed get titleButton() {
+        return this.propToggleBtn("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 downloadButton() {
@@ -221,117 +250,35 @@ export class PropertiesButtons extends React.Component<{}, {}> {
         </Tooltip>;
     }
 
-    @undoBatch
-    setDictation = () => SelectionManager.Views().forEach(dv => dv.rootDoc._showAudio = !dv.rootDoc._showAudio)
-
-    @computed
-    get dictationButton() {
-        const targetDoc = this.selectedDoc;
-        return !targetDoc ? (null) : <Tooltip title={<div className="dash-tooltip">{"Show Dictation Controls"}</div>} placement="top">
-            <div>
-                <div className={`propertiesButtons-linkButton-empty toggle-${targetDoc._showAudio ? "on" : "off"}`} onPointerDown={this.setDictation}>
-                    <FontAwesomeIcon className="propertiesButtons-icon" icon="microphone" size="lg" />
-                </div>
-                <div className="propertiesButtons-title"> Dictate </div>
-            </div>
-        </Tooltip>;
-    }
-
-
-    @undoBatch
-    @action
-    setTitle = () => {
-        SelectionManager.Views().forEach(dv => dv.rootDoc._showTitle = !dv.rootDoc._showTitle ? "title" : dv.rootDoc._showTitle === "title" ? "title:hover" : undefined);
-    }
-
-    @computed
-    get titleButton() {
-        const targetDoc = this.selectedDoc;
-        return !targetDoc ? (null) : <Tooltip title={<div className="dash-tooltip">{"Show Title Header"}</div>} placement="top">
-            <div>
-                <div className={`propertiesButtons-linkButton-empty toggle-${targetDoc._showTitle === "title" ? "on" : StrCast(targetDoc._showTitle).includes(":hover") ? "hover" : "off"}`} onPointerDown={this.setTitle}>
-                    <FontAwesomeIcon className="propertiesButtons-icon" icon="text-width" size="lg" />
-                </div>
-                <div className="propertiesButtons-title"> Title </div>
-            </div>
-        </Tooltip>;
-    }
-
-    @undoBatch
-    @action
-    setCaption = () => {
-        SelectionManager.Views().forEach(dv => {
-            dv.rootDoc._showCaption = dv.rootDoc._showCaption === undefined ? "caption" : undefined;
-            console.log("caption = " + dv.rootDoc._showCaption);
-        });
-    }
-
-    @computed
-    get captionButton() {
-        const targetDoc = this.selectedDoc;
-        return !targetDoc ? (null) : <Tooltip title={<div className="dash-tooltip">{"Show Caption Footer"}</div>} placement="top">
-            <div>
-                <div className={`propertiesButtons-linkButton-empty toggle-${targetDoc._showCaption ? "on" : "off"}`} onPointerDown={this.setCaption}>
-                    <FontAwesomeIcon className="propertiesButtons-icon" icon="closed-captioning" size="lg" />
-                </div>
-                <div className="propertiesButtons-title"> Caption </div>
-            </div>
-        </Tooltip>;
-    }
-
-    @undoBatch
-    @action
-    setChrome = () => {
-        SelectionManager.Views().forEach(dv => dv.rootDoc._chromeStatus = dv.rootDoc._chromeStatus === "disabled" ? "enabled" : "disabled");
-    }
-
     @computed
-    get chromeButton() {
-        const targetDoc = this.selectedDoc;
-        return !targetDoc ? (null) : <Tooltip title={<div className="dash-tooltip">{"Show Editing UI"}</div>} placement="top">
+    get onClickButton() {
+        return !this.selectedDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">Choose onClick behavior</div></>} placement="top">
             <div>
-                <div className={`propertiesButtons-linkButton-empty toggle-${targetDoc._chromeStatus === "enabled" ? "on" : "off"}`} onPointerDown={this.setChrome}>
-                    <FontAwesomeIcon className="propertiesButtons-icon" icon="edit" size="lg" />
+                <div className="propertiesButtons-linkFlyout">
+                    <Flyout anchorPoint={anchorPoints.LEFT_TOP}
+                        content={this.onClickFlyout}>
+                        <div className={"propertiesButtons-linkButton-empty"} onPointerDown={e => e.stopPropagation()} >
+                            {<FontAwesomeIcon className="documentdecorations-icon" icon="mouse-pointer" size="lg" />}
+                        </div>
+                    </Flyout>
                 </div>
-                <div className="propertiesButtons-title"> Controls </div>
+                <div className="propertiesButtons-title"> onclick </div>
             </div>
         </Tooltip>;
     }
 
-    @computed
-    get onClickButton() {
-        if (this.selectedDoc) {
-            return <Tooltip title={<><div className="dash-tooltip">Choose onClick behavior</div></>} placement="top">
-                <div>
-                    <div className="propertiesButtons-linkFlyout">
-                        <Flyout anchorPoint={anchorPoints.LEFT_TOP}
-                            content={this.onClickFlyout}>
-                            <div className={"propertiesButtons-linkButton-empty"} onPointerDown={e => e.stopPropagation()} >
-                                {<FontAwesomeIcon className="documentdecorations-icon" icon="mouse-pointer" size="lg" />}
-                            </div>
-                        </Flyout>
-                    </div>
-                    <div className="propertiesButtons-title"> onclick </div>
-                </div>
-            </Tooltip>;
-        } else {
-            return null;
-        }
-    }
-
     @undoBatch
     @action
     handleOptionChange = (e: any) => {
-        const value = e.target.value;
         this.selectedDoc && (this.selectedDoc.onClickBehavior = e.target.value);
 
-        SelectionManager.Views().forEach(dv => {
-            dv.docView?.noOnClick();
-            switch (value) {
-                case "enterPortal": dv.docView?.makeIntoPortal(); break;
-                case "toggleDetail": dv.docView?.toggleDetail(); break;
-                case "linkInPlace": dv.docView?.toggleFollowLink("inPlace", true, false); break;
-                case "linkOnRight": dv.docView?.toggleFollowLink("add:right", false, false); break;
+        SelectionManager.Views().filter(dv => dv.docView).map(dv => dv.docView!).forEach(docView => {
+            docView.noOnClick();
+            switch (e.target.value) {
+                case "enterPortal": docView.makeIntoPortal(); break;
+                case "toggleDetail": docView.toggleDetail(); break;
+                case "linkInPlace": docView.toggleFollowLink("inPlace", true, false); break;
+                case "linkOnRight": docView.toggleFollowLink("add:right", false, false); break;
             }
         });
     }
@@ -407,98 +354,6 @@ export class PropertiesButtons extends React.Component<{}, {}> {
         </Tooltip>;
     }
 
-    @computed
-    get clustersButton() {
-        const targetDoc = this.selectedDoc;
-        return !targetDoc ? (null) : <Tooltip
-            title={<><div className="dash-tooltip">{this.selectedDoc?._useClusters ? "Stop Showing Clusters" : "Show Clusters"}</div></>} placement="top">
-            <div>
-                <div className={`propertiesButtons-linkButton-empty toggle-${targetDoc._useClusters ? "on" : "off"}`} onPointerDown={this.changeClusters}>
-                    <FontAwesomeIcon className="documentdecorations-icon" icon="braille" size="lg" />
-                </div>
-                <div className="propertiesButtons-title" > clusters </div>
-            </div>
-        </Tooltip>;
-    }
-
-    @action @undoBatch
-    changeFitToBox = () => {
-        if (this.selectedDoc) {
-            if (SelectionManager.Views().length) SelectionManager.Views().forEach(dv => dv.rootDoc._fitToBox = !dv.rootDoc._fitToBox);
-            else this.selectedDoc._fitToBox = !this.selectedDoc._fitToBox;
-        }
-    }
-
-    @action @undoBatch
-    changeFitWidth = () => {
-        if (this.selectedDoc) {
-            if (SelectionManager.Views().length) SelectionManager.Views().forEach(dv => dv.rootDoc._fitWidth = !dv.rootDoc._fitWidth);
-            else this.selectedDoc._fitWidth = !this.selectedDoc._fitWidth;
-        }
-    }
-
-    @action @undoBatch
-    changeClusters = () => {
-        if (this.selectedDoc) {
-            if (SelectionManager.Views().length) SelectionManager.Views().forEach(dv => dv.rootDoc._useClusters = !dv.rootDoc._useClusters);
-            else this.selectedDoc._useClusters = !this.selectedDoc._useClusters;
-        }
-    }
-
-    @computed
-    get fitContentButton() {
-        const targetDoc = this.selectedDoc;
-        return !targetDoc ? (null) : <Tooltip
-            title={<><div className="dash-tooltip">{this.selectedDoc?._fitToBox ? "Stop Fitting Content" : "Fit Content"}</div></>} placement="top">
-            <div>
-                <div className={`propertiesButtons-linkButton-empty toggle-${targetDoc._fitToBox ? "on" : "off"}`} onPointerDown={this.changeFitToBox}>
-                    <FontAwesomeIcon className="documentdecorations-icon" icon="expand" size="lg" />
-                </div>
-                <div className="propertiesButtons-title"> {this.selectedDoc?._fitToBox ? "unfit" : "fit"} </div>
-            </div>
-        </Tooltip>;
-    }
-
-    @computed
-    get fitWidthButton() {
-        const targetDoc = this.selectedDoc;
-        return !targetDoc ? (null) : <Tooltip
-            title={<><div className="dash-tooltip">{this.selectedDoc?._fitWidth ? "Stop Fitting Width" : "Fit Width"}</div></>} placement="top">
-            <div>
-                <div className={`propertiesButtons-linkButton-empty toggle-${targetDoc._fitWidth ? "on" : "off"}`} onPointerDown={this.changeFitWidth}>
-                    <FontAwesomeIcon className="documentdecorations-icon" icon="arrows-alt-h" size="lg" />
-                </div>
-                <div className="propertiesButtons-title"> {this.selectedDoc?._fitWidth ? "unfit" : "fit"} </div>
-            </div>
-        </Tooltip>;
-    }
-
-    @undoBatch
-    @action
-    private makeMask = () => {
-        if (this.selectedDoc) {
-            this.selectedDoc._backgroundColor = "rgba(0,0,0,0.7)";
-            this.selectedDoc.mixBlendMode = "hard-light";
-            this.selectedDoc.color = "#9b9b9bff";
-            this.selectedDoc._stayInCollection = true;
-            this.selectedDoc.isInkMask = true;
-        }
-    }
-
-    @computed
-    get maskButton() {
-        const targetDoc = this.selectedDoc;
-        return !targetDoc ? (null) : <Tooltip
-            title={<><div className="dash-tooltip">Make Mask</div></>} placement="top">
-            <div>
-                <div className={"propertiesButtons-linkButton-empty"} onPointerDown={this.makeMask}>
-                    <FontAwesomeIcon className="documentdecorations-icon" color="white" icon="paint-brush" size="lg" />
-                </div>
-                <div className="propertiesButtons-title"> mask </div>
-            </div>
-        </Tooltip>;
-    }
-
     render() {
         if (!this.selectedDoc) return (null);
 
@@ -524,6 +379,9 @@ export class PropertiesButtons extends React.Component<{}, {}> {
             <div className="propertiesButtons-button">
                 {this.lockButton}
             </div>
+            <div className="propertiesButtons-button" style={{ display: isFreeForm ? "" : "none" }}>
+                {this.panButton}
+            </div>
             <div className="propertiesButtons-button">
                 {this.dictationButton}
             </div>
@@ -554,4 +412,4 @@ export class PropertiesButtons extends React.Component<{}, {}> {
             </div>
         </div>;
     }
-}
+}
\ No newline at end of file
diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx
index f39d5ee4c..162a2ebb8 100644
--- a/src/client/views/TemplateMenu.tsx
+++ b/src/client/views/TemplateMenu.tsx
@@ -81,7 +81,7 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
     @action
     toggleChrome = (): void => {
         this.props.docViews.map(dv => Doc.Layout(dv.layoutDoc)).forEach(layout =>
-            layout._chromeStatus = (layout._chromeStatus !== "disabled" ? "disabled" : StrCast(layout._replacedChrome, "enabled")));
+            layout._chromeStatus = (layout._chromeStatus !== undefined ? undefined : StrCast(layout._replacedChrome, "enabled")));
     }
 
     // todo: add brushes to brushMap to save with a style name
@@ -119,7 +119,7 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
             templateMenu.push(<TemplateToggle key={template} template={template} checked={checked} toggle={this.toggleTemplate} />));
         templateMenu.push(<OtherToggle key={"audio"} name={"Audio"} checked={firstDoc._showAudio ? true : false} toggle={this.toggleAudio} />);
         templateMenu.push(<OtherToggle key={"default"} name={"Default"} checked={templateName === "layout"} toggle={this.toggleDefault} />);
-        !Doc.UserDoc().noviceMode && templateMenu.push(<OtherToggle key={"chrome"} name={"Chrome"} checked={layout._chromeStatus !== "disabled"} toggle={this.toggleChrome} />);
+        !Doc.UserDoc().noviceMode && templateMenu.push(<OtherToggle key={"chrome"} name={"Chrome"} checked={layout._chromeStatus !== undefined} toggle={this.toggleChrome} />);
         addedTypes.concat(noteTypes).map(template => template.treeViewChecked = this.templateIsUsed(firstDoc, template));
         this._addedKeys && Array.from(this._addedKeys).filter(key => !noteTypes.some(nt => nt.title === key)).forEach(template => templateMenu.push(
             <OtherToggle key={template} name={template} checked={templateName === template} toggle={e => this.toggleLayout(e, template)} />));
diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
index 9b57d4c68..2013b3f43 100644
--- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
+++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
@@ -187,7 +187,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
     @action
     headerDown = (e: React.PointerEvent<HTMLDivElement>) => {
         if (e.button === 0 && !e.ctrlKey) {
-            setupMoveUpEvents(this, e, this.headerMove, emptyFunction, e => (this.props.parent.props.Document._chromeStatus === "disabled") && this.collapseSection(e));
+            setupMoveUpEvents(this, e, this.headerMove, emptyFunction, e => !this.props.parent.props.Document._chromeStatus && this.collapseSection(e));
             this._createAliasSelected = false;
         }
     }
@@ -286,7 +286,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
     }
 
     @computed get headingView() {
-        const noChrome = this.props.parent.props.Document._chromeStatus === "disabled";
+        const noChrome = !this.props.parent.props.Document._chromeStatus;
         const key = StrCast(this.props.parent.props.Document._pivotField);
         const evContents = this.heading ? this.heading : this.props.type && this.props.type === "number" ? "0" : `NO ${key.toUpperCase()} VALUE`;
         const editableHeaderView = <EditableView
diff --git a/src/client/views/collections/CollectionPileView.tsx b/src/client/views/collections/CollectionPileView.tsx
index f054e7b7f..22b5c2b2a 100644
--- a/src/client/views/collections/CollectionPileView.tsx
+++ b/src/client/views/collections/CollectionPileView.tsx
@@ -21,7 +21,7 @@ export class CollectionPileView extends CollectionSubView(doc => doc) {
             this.Document._pileLayoutEngine = "pass";
         }
         this._originalChrome = StrCast(this.layoutDoc._chromeStatus);
-        this.layoutDoc._chromeStatus = "disabled";
+        this.layoutDoc._chromeStatus = undefined;
     }
     componentWillUnmount() {
         this.layoutDoc._chromeStatus = this._originalChrome;
diff --git a/src/client/views/collections/SchemaTable.tsx b/src/client/views/collections/SchemaTable.tsx
index 53801eef1..d26f53e28 100644
--- a/src/client/views/collections/SchemaTable.tsx
+++ b/src/client/views/collections/SchemaTable.tsx
@@ -559,7 +559,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
             onPointerDown={this.props.onPointerDown} onClick={this.props.onClick} onWheel={e => this.props.active(true) && e.stopPropagation()}
             onDrop={e => this.props.onDrop(e, {})} onContextMenu={this.onContextMenu} >
             {this.reactTable}
-            {StrCast(this.props.Document._chromeStatus) !== "disabled" ? <div className="collectionSchemaView-addRow" onClick={() => this.createRow()}>+ new</div>
+            {this.props.Document._chromeStatus ? <div className="collectionSchemaView-addRow" onClick={() => this.createRow()}>+ new</div>
                 : undefined}
             {!this._showDoc ? (null) :
                 <div className="collectionSchemaView-documentPreview"
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index b5dca42a7..2e1f4db51 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1286,10 +1286,6 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
     @undoBatch
     toggleNativeDimensions = () => Doc.toggleNativeDimensions(this.layoutDoc, 1, this.nativeWidth, this.nativeHeight)
 
-    @undoBatch
-    @action
-    toggleLockTransform = () => this.layoutDoc._lockedTransform = this.layoutDoc._lockedTransform ? undefined : true
-
     onContextMenu = (e: React.MouseEvent) => {
         if (this.props.isAnnotationOverlay || this.props.Document.annotationOn || !ContextMenu.Instance) return;
 
@@ -1314,7 +1310,6 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
         const optionItems = options && "subitems" in options ? options.subitems : [];
         !this.props.isAnnotationOverlay && !Doc.UserDoc().noviceMode &&
             optionItems.push({ description: (this._showAnimTimeline ? "Close" : "Open") + " Animation Timeline", event: action(() => this._showAnimTimeline = !this._showAnimTimeline), icon: "eye" });
-        optionItems.push({ description: this.layoutDoc._lockedTransform ? "Unlock Transform" : "Lock Transform", event: this.toggleLockTransform, icon: this.layoutDoc._lockedTransform ? "unlock" : "lock" });
         this.props.renderDepth && optionItems.push({ description: "Use Background Color as Default", event: () => Cast(Doc.UserDoc().emptyCollection, Doc, null)._backgroundColor = StrCast(this.layoutDoc._backgroundColor), icon: "palette" });
         if (!Doc.UserDoc().noviceMode) {
             optionItems.push({ description: (!Doc.NativeWidth(this.layoutDoc) || !Doc.NativeHeight(this.layoutDoc) ? "Freeze" : "Unfreeze") + " Aspect", event: this.toggleNativeDimensions, icon: "snowflake" });
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index aec6cd03d..47a3c878f 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -594,7 +594,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
 
     @undoBatch deleteClicked = () => this.props.removeDocument?.(this.props.Document);
     @undoBatch toggleDetail = () => this.Document.onClick = ScriptField.MakeScript(`toggleDetail(self, "${this.Document.layoutKey}")`);
-    @undoBatch toggleLockPosition = () => this.Document._lockedPosition = this.Document._lockedPosition ? undefined : true;
 
     @undoBatch @action
     drop = async (e: Event, de: DragManager.DropEvent) => {
@@ -689,7 +688,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
             if (!this.Document.annotationOn) {
                 const options = cm.findByDescription("Options...");
                 const optionItems: ContextMenuProps[] = options && "subitems" in options ? options.subitems : [];
-                this.props.ContainingCollectionDoc?._viewType === CollectionViewType.Freeform && optionItems.push({ description: this.Document._lockedPosition ? "Unlock Position" : "Lock Position", event: this.toggleLockPosition, icon: BoolCast(this.Document._lockedPosition) ? "unlock" : "lock" });
                 !options && cm.addItem({ description: "Options...", subitems: optionItems, icon: "compass" });
 
                 onClicks.push({ description: this.Document.ignoreClick ? "Select" : "Do Nothing", event: () => this.Document.ignoreClick = !this.Document.ignoreClick, icon: this.Document.ignoreClick ? "unlock" : "lock" });
@@ -721,7 +719,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
             (this.rootDoc._viewType !== CollectionViewType.Docking || !Doc.UserDoc().noviceMode) && moreItems.push({ description: "Share", event: () => SharingManager.Instance.open(this.props.DocumentView()), icon: "users" });
             if (!Doc.UserDoc().noviceMode) {
                 moreItems.push({ description: "Make View of Metadata Field", event: () => Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.DataDoc), icon: "concierge-bell" });
-                moreItems.push({ description: `${this.Document._chromeStatus !== "disabled" ? "Hide" : "Show"} Chrome`, event: () => this.Document._chromeStatus = (this.Document._chromeStatus !== "disabled" ? "disabled" : "enabled"), icon: "project-diagram" });
+                moreItems.push({ description: `${this.Document._chromeStatus ? "Hide" : "Show"} Chrome`, event: () => this.Document._chromeStatus = (this.Document._chromeStatus ? undefined : "enabled"), icon: "project-diagram" });
 
                 if (Cast(Doc.GetProto(this.props.Document).data, listSpec(Doc))) {
                     moreItems.push({ description: "Export to Google Photos Album", event: () => GooglePhotos.Export.CollectionToAlbum({ collection: this.props.Document }).then(console.log), icon: "caret-square-right" });
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index 844afe1e2..682ec5356 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -2262,7 +2262,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         const mode = StrCast(this.rootDoc._viewType) as CollectionViewType;
         const isMini: boolean = this.toolbarWidth <= 100;
         return (
-            <div className="presBox-buttons" style={{ display: this.rootDoc._chromeStatus === "disabled" ? "none" : undefined }}>
+            <div className="presBox-buttons" style={{ display: !this.rootDoc._chromeStatus ? "none" : undefined }}>
                 {isMini ? (null) : <select className="presBox-viewPicker"
                     style={{ display: this.layoutDoc.presStatus === "edit" ? "block" : "none" }}
                     onPointerDown={e => e.stopPropagation()}
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index af34a53ec..5e94a7ae5 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1207,7 +1207,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
 
         // jump rich text menu to this textbox
         const bounds = this._ref.current?.getBoundingClientRect();
-        if (bounds && this.layoutDoc._chromeStatus !== "disabled" && RichTextMenu.Instance) {
+        if (bounds && this.layoutDoc._chromeStatus && RichTextMenu.Instance) {
             const x = Math.min(Math.max(bounds.left, 0), window.innerWidth - RichTextMenu.Instance.width);
             let y = Math.min(Math.max(0, bounds.top - RichTextMenu.Instance.height - 50), window.innerHeight - RichTextMenu.Instance.height);
             if (coords && coords.left > x && coords.left < x + RichTextMenu.Instance.width && coords.top > y && coords.top < y + RichTextMenu.Instance.height + 50) {
-- 
cgit v1.2.3-70-g09d2


From 04225e5248ac46c4f9fdc698ec1526b53fd02164 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 16 Mar 2021 20:59:48 -0400
Subject: more chromeStatus cleanup.  Big stripdown of propertiesButtons.

---
 src/client/views/InkingStroke.tsx                  |  15 +-
 src/client/views/PropertiesButtons.scss            |   1 +
 src/client/views/PropertiesButtons.tsx             | 393 ++++-----------------
 src/client/views/TemplateMenu.tsx                  |   9 +-
 .../collections/CollectionMasonryViewFieldRow.tsx  |   2 +-
 .../views/collections/CollectionStackingView.tsx   |   4 +-
 .../CollectionStackingViewFieldColumn.tsx          |   6 +-
 .../views/nodes/formattedText/FormattedTextBox.tsx |  15 +-
 8 files changed, 91 insertions(+), 354 deletions(-)

(limited to 'src/client/views/PropertiesButtons.tsx')

diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 31279338f..34cdb50e3 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -33,12 +33,13 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
         CognitiveServices.Inking.Appliers.ConcatenateHandwriting(this.dataDoc, ["inkAnalysis", "handwriting"], [data]);
     }
 
-    private makeMask = () => {
-        this.props.Document.mixBlendMode = "hard-light";
-        this.props.Document.color = "#9b9b9bff";
-        //this.props.Document._stayInCollection = true;
-        this.props.Document.isInkMask = true;
-    }
+    public static toggleMask = action((inkDoc: Doc) => {
+        inkDoc.isInkMask = !inkDoc.isInkMask;
+        inkDoc._backgroundColor = inkDoc.isInkMask ? "rgba(0,0,0,0.7)" : undefined;
+        inkDoc.mixBlendMode = inkDoc.isInkMask ? "hard-light" : undefined;
+        inkDoc.color = "#9b9b9bff";
+        inkDoc._stayInCollection = inkDoc.isInkMask ? true : undefined;
+    })
 
     public _prevX = 0;
     public _prevY = 0;
@@ -205,7 +206,7 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
                     const cm = ContextMenu.Instance;
                     if (cm) {
                         !Doc.UserDoc().noviceMode && cm.addItem({ description: "Recognize Writing", event: this.analyzeStrokes, icon: "paint-brush" });
-                        cm.addItem({ description: "Make Mask", event: this.makeMask, icon: "paint-brush" });
+                        cm.addItem({ description: "Toggle Mask", event: () => InkingStroke.toggleMask(this.rootDoc), icon: "paint-brush" });
                         cm.addItem({ description: "Edit Points", event: action(() => formatInstance._controlBtn = !formatInstance._controlBtn), icon: "paint-brush" });
                         //cm.addItem({ description: "Format Shape...", event: this.formatShape, icon: "paint-brush" });
                     }
diff --git a/src/client/views/PropertiesButtons.scss b/src/client/views/PropertiesButtons.scss
index ba212da7f..29d2bfcb7 100644
--- a/src/client/views/PropertiesButtons.scss
+++ b/src/client/views/PropertiesButtons.scss
@@ -63,6 +63,7 @@ $linkGap : 3px;
     display: flex;
     flex-direction: row;
     flex-wrap: wrap;
+    padding-bottom: 5.5px;
 }
 
 .onClickFlyout-editScript {
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index e93abb67a..15214b692 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -1,264 +1,92 @@
-import { IconProp } from '@fortawesome/fontawesome-svg-core';
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { Tooltip } from '@material-ui/core';
-import { action, computed, observable, runInAction } from "mobx";
+import { action, computed, observable } from "mobx";
 import { observer } from "mobx-react";
 import { Doc, Opt } from "../../fields/Doc";
 import { InkField } from '../../fields/InkField';
 import { RichTextField } from '../../fields/RichTextField';
-import { BoolCast, Cast, NumCast, StrCast } from "../../fields/Types";
-import { ImageField } from '../../fields/URLField';
-import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager';
-import { Pulls, Pushes } from '../apis/google_docs/GoogleApiClientUtils';
-import { GooglePhotos } from '../apis/google_docs/GooglePhotosClientUtils';
-import { Docs, DocUtils } from '../documents/Documents';
+import { BoolCast, StrCast } from "../../fields/Types";
+import { DocUtils } from '../documents/Documents';
 import { DocumentType } from '../documents/DocumentTypes';
 import { SelectionManager } from '../util/SelectionManager';
 import { undoBatch } from '../util/UndoManager';
-import { CollectionDockingView } from './collections/CollectionDockingView';
 import { CollectionViewType } from './collections/CollectionView';
+import { InkingStroke } from './InkingStroke';
 import { DocumentView } from './nodes/DocumentView';
-import { GoogleRef } from "./nodes/formattedText/FormattedTextBox";
 import './PropertiesButtons.scss';
 import React = require("react");
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
 
-
-const cloud: IconProp = "cloud-upload-alt";
-const fetch: IconProp = "sync-alt";
-
 enum UtilityButtonState {
     Default,
     OpenRight,
     OpenExternally
 }
-
 @observer
 export class PropertiesButtons extends React.Component<{}, {}> {
-    private _pullAnimating = false;
-    private _pushAnimating = false;
-    private _pullColorAnimating = false;
-
-    public static hasPushedHack = false;
-    public static hasPulledHack = false;
-
     @observable public static Instance: PropertiesButtons;
-    @observable private openHover = UtilityButtonState.Default;
-    @observable private pushIcon: IconProp = "arrow-alt-circle-up";
-    @observable private pullIcon: IconProp = "arrow-alt-circle-down";
-    @observable private pullColor: string = "white";
-    @observable public isAnimatingFetch = false;
-    @observable public isAnimatingPulse = false;
-
-    @computed get selectedDoc() { return SelectionManager.SelectedSchemaDoc() || this.selectedDocumentView?.rootDoc; }
-    @computed get selectedDocumentView() { return SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined; }
-    @computed get onClick() { return this.selectedDoc?.onClickBehavior ? this.selectedDoc?.onClickBehavior : "nothing"; }
-
-    public startPullOutcome = action((success: boolean) => {
-        if (!this._pullAnimating) {
-            this._pullAnimating = true;
-            this.pullIcon = success ? "check-circle" : "stop-circle";
-            setTimeout(() => runInAction(() => {
-                this.pullIcon = "arrow-alt-circle-down";
-                this._pullAnimating = false;
-            }), 1000);
-        }
-    });
-
-    public startPushOutcome = action((success: boolean) => {
-        this.isAnimatingPulse = false;
-        if (!this._pushAnimating) {
-            this._pushAnimating = true;
-            this.pushIcon = success ? "check-circle" : "stop-circle";
-            setTimeout(() => runInAction(() => {
-                this.pushIcon = "arrow-alt-circle-up";
-                this._pushAnimating = false;
-            }), 1000);
-        }
-    });
-
-    public setPullState = action((unchanged: boolean) => {
-        this.isAnimatingFetch = false;
-        if (!this._pullColorAnimating) {
-            this._pullColorAnimating = true;
-            this.pullColor = unchanged ? "lawngreen" : "red";
-            setTimeout(this.clearPullColor, 1000);
-        }
-    });
-
-    private clearPullColor = action(() => {
-        this.pullColor = "white";
-        this._pullColorAnimating = false;
-    });
-
-    @computed
-    get considerGoogleDocsPush() {
-        const targetDoc = this.selectedDoc;
-        const published = targetDoc && Doc.GetProto(targetDoc)[GoogleRef] !== undefined;
-        const animation = this.isAnimatingPulse ? "shadow-pulse 1s linear infinite" : "none";
-        return !targetDoc ? (null) : <Tooltip title={<div className="dash-tooltip">{`${published ? "Push" : "Publish"} to Google Docs`}</div>} placement="top">
-            <div>
-                <div
-                    className="propertiesButtons-linker"
-                    style={{ animation }}
-                    onClick={async () => {
-                        await GoogleAuthenticationManager.Instance.fetchOrGenerateAccessToken();
-                        !published && runInAction(() => this.isAnimatingPulse = true);
-                        PropertiesButtons.hasPushedHack = false;
-                        targetDoc[Pushes] = NumCast(targetDoc[Pushes]) + 1;
-                    }}>
-                    <FontAwesomeIcon className="documentdecorations-icon" icon={published ? (this.pushIcon as any) : cloud} size={published ? "lg" : "sm"} />
-                </div>
-                <div className="propertiesButtons-title">Google</div>
-            </div>
-        </Tooltip>;
-    }
-
-    @computed
-    get considerGoogleDocsPull() {
-        const targetDoc = this.selectedDoc;
-        const dataDoc = targetDoc && Doc.GetProto(targetDoc);
-        const animation = this.isAnimatingFetch ? "spin 0.5s linear infinite" : "none";
-
-        const title = (() => {
-            switch (this.openHover) {
-                default:
-                case UtilityButtonState.Default: return `${!dataDoc?.googleDocUnchanged ? "Pull from" : "Fetch"} Google Docs`;
-                case UtilityButtonState.OpenRight: return "Open in Right Split";
-                case UtilityButtonState.OpenExternally: return "Open in new Browser Tab";
-            }
-        })();
 
-        return !targetDoc || !dataDoc || !dataDoc[GoogleRef] ? (null) : <Tooltip
-            title={<><div className="dash-tooltip">{title}</div></>} placement="top">
-            <div>
-                <div className="propertiesButtons-linker"
-                    style={{ backgroundColor: this.pullColor }}
-                    onPointerEnter={action(e => {
-                        e.altKey && (this.openHover = UtilityButtonState.OpenExternally);
-                        e.shiftKey && (this.openHover = UtilityButtonState.OpenRight);
-                    })}
-                    onPointerLeave={action(() => this.openHover = UtilityButtonState.Default)}
-                    onClick={async e => {
-                        const googleDocUrl = `https://docs.google.com/document/d/${dataDoc[GoogleRef]}/edit`;
-                        if (e.shiftKey) {
-                            e.preventDefault();
-                            let googleDoc = await Cast(dataDoc.googleDoc, Doc);
-                            if (!googleDoc) {
-                                const options = { _width: 600, _nativeWidth: 960, _nativeHeight: 800, useCors: false };
-                                googleDoc = Docs.Create.WebDocument(googleDocUrl, options);
-                                dataDoc.googleDoc = googleDoc;
-                            }
-                            CollectionDockingView.AddSplit(googleDoc, "right");
-                        } else if (e.altKey) {
-                            e.preventDefault();
-                            window.open(googleDocUrl);
-                        } else {
-                            this.clearPullColor();
-                            PropertiesButtons.hasPulledHack = false;
-                            targetDoc[Pulls] = NumCast(targetDoc[Pulls]) + 1;
-                            dataDoc.googleDocUnchanged && runInAction(() => this.isAnimatingFetch = true);
-                        }
-                    }}>
-                    <FontAwesomeIcon className="documentdecorations-icon" size="lg" color="black"
-                        style={{ WebkitAnimation: animation, MozAnimation: animation }}
-                        icon={(() => {
-                            switch (this.openHover) {
-                                default:
-                                case UtilityButtonState.Default: return dataDoc.googleDocUnchanged === false ? (this.pullIcon as any) : fetch;
-                                case UtilityButtonState.OpenRight: return "arrow-alt-circle-right";
-                                case UtilityButtonState.OpenExternally: return "share";
-                            }
-                        })()}
-                    />
-                </div>
-                <div className="propertiesButtons-title" style={{ backgroundColor: "white", color: "black" }}>Fetch</div>
-            </div>
-        </Tooltip>;
-    }
+    @computed get selectedDoc() { return SelectionManager.SelectedSchemaDoc() || SelectionManager.Views().lastElement()?.rootDoc; }
 
-    @action
-    makeMask = (inkDoc: Doc) => {
-        inkDoc.isInkMask = !inkDoc.isInkMask;
-        inkDoc._backgroundColor = inkDoc.isInkMask ? "rgba(0,0,0,0.7)" : undefined;
-        inkDoc.mixBlendMode = inkDoc.isInkMask ? "hard-light" : undefined;
-        inkDoc.color = "#9b9b9bff";
-        inkDoc._stayInCollection = inkDoc.isInkMask ? true : undefined;
-    }
-    propToggleBtn = (label: string, property: string, tooltip: (on?: any) => string, icon: (on: boolean) => string, onClick?: (dv: Opt<DocumentView>, doc: Doc, property: string) => void) => {
+    propertyToggleBtn = (label: string, property: string, tooltip: (on?: any) => string, icon: (on: boolean) => string, onClick?: (dv: Opt<DocumentView>, doc: Doc, property: string) => void) => {
         const targetDoc = this.selectedDoc;
         const onPropToggle = (dv: Opt<DocumentView>, doc: Doc, prop: string) => (dv?.layoutDoc || doc)[prop] = (dv?.layoutDoc || doc)[prop] ? undefined : true;
-        return !targetDoc ? (null) : <Tooltip
-            title={<div className={`dash-tooltip`}>{tooltip(targetDoc?.[property])} </div>} placement="top">
-            <div>
-                <div className={`propertiesButtons-linkButton-empty toggle-${StrCast(targetDoc[property]).includes(":hover") ? "hover" : targetDoc[property] ? "on" : "off"}`}
-                    onPointerDown={undoBatch(() => {
-                        if (SelectionManager.Views().length) {
-                            SelectionManager.Views().forEach(dv => (onClick ?? onPropToggle)(dv, dv.rootDoc, property));
-                        } else if (targetDoc) (onClick ?? onPropToggle)(undefined, targetDoc, property);
-                    })} >
-                    <FontAwesomeIcon className="documentdecorations-icon" size="lg" icon={icon(BoolCast(targetDoc?.[property])) as any} />
+        return !targetDoc ? (null) :
+            <Tooltip title={<div className={`dash-tooltip`}>{tooltip(targetDoc?.[property])} </div>} placement="top">
+                <div>
+                    <div className={`propertiesButtons-linkButton-empty toggle-${StrCast(targetDoc[property]).includes(":hover") ? "hover" : targetDoc[property] ? "on" : "off"}`}
+                        onPointerDown={undoBatch(() => {
+                            if (SelectionManager.Views().length) {
+                                SelectionManager.Views().forEach(dv => (onClick ?? onPropToggle)(dv, dv.rootDoc, property));
+                            } else if (targetDoc) (onClick ?? onPropToggle)(undefined, targetDoc, property);
+                        })} >
+                        <FontAwesomeIcon className="documentdecorations-icon" size="lg" icon={icon(BoolCast(targetDoc?.[property])) as any} />
+                    </div>
+                    <div className="propertiesButtons-title">{label}</div>
                 </div>
-                <div className="propertiesButtons-title">{label}</div>
-            </div>
-        </Tooltip>;
+            </Tooltip>;
     }
     @computed get lockButton() {
-        return this.propToggleBtn("Position", "_lockedPosition", on => `${on ? "Unlock" : "Lock"} XY location on freeform view`, on => on ? "unlock" : "lock");
-    }
-    @computed get panButton() {
-        return this.propToggleBtn("Pan", "_lockedTransform", on => `${on ? "Unlock" : "Lock"} panning of view`, on => on ? "unlock" : "lock");
+        return this.propertyToggleBtn("No\xA0Drag", "_lockedPosition", on => `${on ? "Unlock" : "Lock"} position to prevent dragging`, on => "thumbtack");
     }
     @computed get dictationButton() {
-        return this.propToggleBtn("Dictate", "_showAudio", on => `${on ? "Hide" : "Show"} dictation/recording controls`, () => "microphone");
+        return this.propertyToggleBtn("Dictate", "_showAudio", on => `${on ? "Hide" : "Show"} dictation/recording controls`, on => "microphone");
     }
     @computed get maskButton() {
-        return this.propToggleBtn("Mask", "isInkMask", on => on ? "Make plain ink" : "Make highlight mask", () => "paint-brush", (dv, doc) => this.makeMask(dv?.layoutDoc || doc));
+        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.propToggleBtn("Clusters", "_useClusters", on => `${on ? "Hide" : "Show"} clusters`, () => "braille");
+        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.propToggleBtn("Fit All", "_fitToBox", on => `${on ? "Don't" : ""} fit content to container visible area`, on => on ? "expand-arrows-alt" : "compress-arrows-alt");
+        return this.propertyToggleBtn("View All", "_fitToBox", on => `${on ? "Don't" : ""} fit content to container visible area`, on => "eye");
     }
     @computed get fitWidthButton() {
-        return this.propToggleBtn("Fit Wid", "_fitWidth", on => `${on ? "Don't" : ""} fit content to width of container`, on => on ? "arrows-alt-h" : "arrows-alt-h");
+        return this.propertyToggleBtn("Fit\xA0Width", "_fitWidth", on => `${on ? "Don't" : ""} fit content to width of container`, on => "arrows-alt-h");
     }
     @computed get captionButton() {
-        return this.propToggleBtn("Caption", "_showCaption", on => `${on ? "Hide" : "Show"} caption footer`, on => "closed-captioning", (dv, doc) => (dv?.rootDoc || doc)._showCaption = (dv?.rootDoc || doc)._showCaption === undefined ? "caption" : undefined);
+        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.propToggleBtn("Controls", "_chromeStatus", on => `${on === "enabled" ? "Hide" : "Show"} editing UI`, on => "edit", (dv, doc) => (dv?.rootDoc || doc)._chromeStatus = (dv?.rootDoc || doc)._chromeStatus === undefined ? "enabled" : undefined);
+        return this.propertyToggleBtn("Controls", "_chromeStatus", on => `${on === "enabled" ? "Hide" : "Show"} editing UI`, on => "edit", (dv, doc) => (dv?.rootDoc || doc)._chromeStatus = (dv?.rootDoc || doc)._chromeStatus === undefined ? "enabled" : undefined);
     }
     @computed get titleButton() {
-        return this.propToggleBtn("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 downloadButton() {
-        const targetDoc = this.selectedDoc;
-        return !targetDoc ? (null) : <Tooltip
-            title={<div className="dash-tooltip">{"Download Document"}</div>} placement="top">
-            <div>
-                <div className={"propertiesButtons-linkButton-empty"} onPointerDown={() => this.selectedDoc && Doc.Zip(this.selectedDoc)}>
-                    <FontAwesomeIcon className="propertiesButtons-icon" icon="download" size="lg" />
-                </div>
-                <div className="propertiesButtons-title"> downld </div>
-            </div>
-        </Tooltip>;
+        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 onClickButton() {
-        return !this.selectedDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">Choose onClick behavior</div></>} placement="top">
+        return !this.selectedDoc ? (null) : <Tooltip title={<div className="dash-tooltip">Choose onClick behavior</div>} placement="top">
             <div>
                 <div className="propertiesButtons-linkFlyout">
-                    <Flyout anchorPoint={anchorPoints.LEFT_TOP}
-                        content={this.onClickFlyout}>
+                    <Flyout anchorPoint={anchorPoints.LEFT_TOP} content={this.onClickFlyout}>
                         <div className={"propertiesButtons-linkButton-empty"} onPointerDown={e => e.stopPropagation()} >
-                            {<FontAwesomeIcon className="documentdecorations-icon" icon="mouse-pointer" size="lg" />}
+                            <FontAwesomeIcon className="documentdecorations-icon" icon="mouse-pointer" size="lg" />
                         </div>
                     </Flyout>
                 </div>
@@ -271,7 +99,6 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     @action
     handleOptionChange = (e: any) => {
         this.selectedDoc && (this.selectedDoc.onClickBehavior = e.target.value);
-
         SelectionManager.Views().filter(dv => dv.docView).map(dv => dv.docView!).forEach(docView => {
             docView.noOnClick();
             switch (e.target.value) {
@@ -283,133 +110,53 @@ export class PropertiesButtons extends React.Component<{}, {}> {
         });
     }
 
-    @undoBatch @action
+    @undoBatch
     editOnClickScript = () => {
-        if (this.selectedDoc) {
-            if (SelectionManager.Views().length) SelectionManager.Views().forEach(dv => DocUtils.makeCustomViewClicked(dv.rootDoc, undefined, "onClick"));
-            else DocUtils.makeCustomViewClicked(this.selectedDoc, undefined, "onClick");
-        }
+        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() {
-        return <div><form>
-            <div className="radio">
-                <label>
-                    <input type="radio" value="nothing"
-                        checked={this.onClick === 'nothing'}
-                        onChange={this.handleOptionChange} />
-                    Select Document
-                </label>
-            </div>
-            <div className="radio">
-                <label>
-                    <input type="radio" value="enterPortal"
-                        checked={this.onClick === 'enterPortal'}
-                        onChange={this.handleOptionChange} />
-                    Enter Portal
-                </label>
-            </div>
-            <div className="radio">
-                <label>
-                    <input type="radio" value="toggleDetail"
-                        checked={this.onClick === 'toggleDetail'}
-                        onChange={this.handleOptionChange} />
-                    Toggle Detail
-                </label>
-            </div>
-            <div className="radio">
-                <label>
-                    <input type="radio" value="linkInPlace"
-                        checked={this.onClick === 'linkInPlace'}
-                        onChange={this.handleOptionChange} />
-                    Follow Link
-                </label>
-            </div>
-            <div className="radio">
-                <label>
-                    <input type="radio" value="linkOnRight"
-                        checked={this.onClick === 'linkOnRight'}
-                        onChange={this.handleOptionChange} />
-                    Open Link on Right
-                </label>
-            </div>
-        </form>
+        const makeLabel = (value: string, label: string) => <div className="radio">
+            <label>
+                <input type="radio" value={value} checked={(this.selectedDoc?.onClickBehavior ?? "nothing") === value} onChange={this.handleOptionChange} />
+                {label}
+            </label>
+        </div>;
+        return <div>
+            <form>
+                {makeLabel("nothing", "Select Document")}
+                {makeLabel("enterPortal", "Enter Portal")}
+                {makeLabel("toggleDetail", "Toggle Detail")}
+                {makeLabel("linkInPlace", "Follow Link")}
+                {makeLabel("linkOnRight", "Open Link on Right")}
+            </form>
             {Doc.UserDoc().noviceMode ? (null) : <div onPointerDown={this.editOnClickScript} className="onClickFlyout-editScript"> Edit onClick Script</div>}
         </div>;
     }
 
-    @computed
-    get googlePhotosButton() {
-        const targetDoc = this.selectedDoc;
-        return !targetDoc ? (null) : <Tooltip
-            title={<><div className="dash-tooltip">{"Export to Google Photos"}</div></>} placement="top">
-            <div>
-                <div className={"propertiesButtons-linkButton-empty"}
-                    onPointerDown={() => this.selectedDoc && GooglePhotos.Export.CollectionToAlbum({ collection: this.selectedDoc }).then(console.log)}>
-                    {<FontAwesomeIcon className="documentdecorations-icon" icon="cloud-upload-alt" size="lg" />}
-                </div>
-                <div className="propertiesButtons-title"> google </div>
-            </div>
-        </Tooltip>;
-    }
-
     render() {
-        if (!this.selectedDoc) return (null);
-
-        const layoutField = this.selectedDoc[Doc.LayoutFieldKey(this.selectedDoc)];
+        const layoutField = this.selectedDoc?.[Doc.LayoutFieldKey(this.selectedDoc)];
         const isText = layoutField instanceof RichTextField;
-        const isImage = layoutField instanceof ImageField;
         const isInk = layoutField instanceof InkField;
-        const isCollection = this.selectedDoc.type === DocumentType.COL;
-        const isFreeForm = this.selectedDoc._viewType === CollectionViewType.Freeform;
-        const considerPull = isText && this.considerGoogleDocsPull;
-        const considerPush = isText && this.considerGoogleDocsPush;
-
-        return <div className="propertiesButtons" style={{ paddingBottom: "5.5px" }}>
-            <div className="propertiesButtons-button">
-                {this.titleButton}
-            </div>
-            <div className="propertiesButtons-button">
-                {this.captionButton}
-            </div>
-            <div className="propertiesButtons-button" style={{ display: isCollection ? "" : "none" }}>
-                {this.chromeButton}
-            </div>
-            <div className="propertiesButtons-button">
-                {this.lockButton}
-            </div>
-            <div className="propertiesButtons-button" style={{ display: isFreeForm ? "" : "none" }}>
-                {this.panButton}
-            </div>
-            <div className="propertiesButtons-button">
-                {this.dictationButton}
-            </div>
-            <div className="propertiesButtons-button">
-                {this.onClickButton}
-            </div>
-            <div className="propertiesButtons-button" style={{ display: !considerPush ? "none" : "" }}>
-                {this.considerGoogleDocsPush}
-            </div>
-            <div className="propertiesButtons-button" style={{ display: !considerPull ? "none" : "" }}>
-                {this.considerGoogleDocsPull}
-            </div>
-            <div className="propertiesButtons-button" style={{ display: !isImage ? "none" : "" }}>
-                {this.googlePhotosButton}
-            </div>
-
-            <div className="propertiesButtons-button" style={{ display: !isFreeForm ? "none" : "" }}>
-                {this.clustersButton}
-            </div>
-            <div className="propertiesButtons-button" style={{ display: !isFreeForm && !isText ? "none" : "" }}>
-                {this.fitContentButton}
-            </div>
-            <div className="propertiesButtons-button">
-                {this.fitWidthButton}
-            </div>
-            <div className="propertiesButtons-button" style={{ display: !isInk ? "none" : "" }}>
-                {this.maskButton}
-            </div>
-        </div>;
+        const isCollection = this.selectedDoc?.type === DocumentType.COL;
+        const isFreeForm = this.selectedDoc?._viewType === CollectionViewType.Freeform;
+        const toggle = (ele: JSX.Element | null, style?: React.CSSProperties) => <div className="propertiesButtons-button" style={style}> {ele} </div>;
+
+        return !this.selectedDoc ? (null) :
+            <div className="propertiesButtons">
+                {toggle(this.titleButton)}
+                {toggle(this.captionButton)}
+                {toggle(this.chromeButton, { display: isCollection ? "" : "none" })}
+                {toggle(this.lockButton)}
+                {toggle(this.dictationButton)}
+                {toggle(this.onClickButton)}
+                {toggle(this.clustersButton, { display: !isFreeForm ? "none" : "" })}
+                {toggle(this.panButton, { display: !isFreeForm ? "none" : "" })}
+                {toggle(this.fitContentButton, { display: !isFreeForm && !isText ? "none" : "" })}
+                {toggle(this.fitWidthButton)}
+                {toggle(this.maskButton, { display: !isInk ? "none" : "" })}
+            </div>;
     }
 }
\ No newline at end of file
diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx
index 162a2ebb8..9f04e8a6e 100644
--- a/src/client/views/TemplateMenu.tsx
+++ b/src/client/views/TemplateMenu.tsx
@@ -45,7 +45,7 @@ class OtherToggle extends React.Component<{ checked: boolean, name: string, togg
 
 export interface TemplateMenuProps {
     docViews: DocumentView[];
-    templates?: Map<string, boolean>;
+    templates: Map<string, boolean>;
 }
 
 
@@ -81,7 +81,7 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
     @action
     toggleChrome = (): void => {
         this.props.docViews.map(dv => Doc.Layout(dv.layoutDoc)).forEach(layout =>
-            layout._chromeStatus = (layout._chromeStatus !== undefined ? undefined : StrCast(layout._replacedChrome, "enabled")));
+            layout._chromeStatus = (layout._chromeStatus ? undefined : StrCast(layout._replacedChrome, "enabled")));
     }
 
     // todo: add brushes to brushMap to save with a style name
@@ -115,11 +115,11 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
         const addedTypes = Doc.UserDoc().noviceMode ? [] : DocListCast(Cast(Doc.UserDoc()["template-buttons"], Doc, null)?.data);
         const layout = Doc.Layout(firstDoc);
         const templateMenu: Array<JSX.Element> = [];
-        this.props.templates?.forEach((checked, template) =>
+        this.props.templates.forEach((checked, template) =>
             templateMenu.push(<TemplateToggle key={template} template={template} checked={checked} toggle={this.toggleTemplate} />));
         templateMenu.push(<OtherToggle key={"audio"} name={"Audio"} checked={firstDoc._showAudio ? true : false} toggle={this.toggleAudio} />);
         templateMenu.push(<OtherToggle key={"default"} name={"Default"} checked={templateName === "layout"} toggle={this.toggleDefault} />);
-        !Doc.UserDoc().noviceMode && templateMenu.push(<OtherToggle key={"chrome"} name={"Chrome"} checked={layout._chromeStatus !== undefined} toggle={this.toggleChrome} />);
+        !Doc.UserDoc().noviceMode && templateMenu.push(<OtherToggle key={"chrome"} name={"Chrome"} checked={layout._chromeStatus !== "disabled"} toggle={this.toggleChrome} />);
         addedTypes.concat(noteTypes).map(template => template.treeViewChecked = this.templateIsUsed(firstDoc, template));
         this._addedKeys && Array.from(this._addedKeys).filter(key => !noteTypes.some(nt => nt.title === key)).forEach(template => templateMenu.push(
             <OtherToggle key={template} name={template} checked={templateName === template} toggle={e => this.toggleLayout(e, template)} />));
@@ -140,7 +140,6 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
                 rootSelected={returnFalse}
                 onCheckedClick={this.scriptField}
                 onChildClick={this.scriptField}
-                setHeight={returnFalse}
                 dropAction={undefined}
                 active={returnTrue}
                 parentActive={returnFalse}
diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
index 2013b3f43..46bfd841e 100644
--- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
+++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
@@ -253,7 +253,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
         const rows = Math.max(1, Math.min(this.props.docList.length, Math.floor((this.props.parent.props.PanelWidth() - 2 * this.props.parent.xMargin) / (this.props.parent.columnWidth + this.props.parent.gridGap))));
         const style = this.props.parent;
         const chromeStatus = this.props.parent.props.Document._chromeStatus;
-        const showChrome = (chromeStatus !== 'view-mode' && chromeStatus !== 'disabled');
+        const showChrome = (chromeStatus !== 'view-mode' && chromeStatus);
         const stackPad = showChrome ? `0px ${this.props.parent.xMargin}px` : `${this.props.parent.yMargin}px ${this.props.parent.xMargin}px 0px ${this.props.parent.xMargin}px `;
         return this.collapsed ? (null) :
             <div style={{ position: "relative" }}>
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index f3c1c4464..e3d7118e9 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -63,7 +63,7 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
     @computed get gridGap() { return NumCast(this.layoutDoc._gridGap, 10); }
     @computed get isStackingView() { return (this.props.viewType ?? this.layoutDoc._viewType) === CollectionViewType.Stacking; }
     @computed get numGroupColumns() { return this.isStackingView ? Math.max(1, this.Sections.size + (this.showAddAGroup ? 1 : 0)) : 1; }
-    @computed get showAddAGroup() { return (this.pivotField && (this.chromeStatus !== 'view-mode' && this.chromeStatus !== 'disabled')); }
+    @computed get showAddAGroup() { return (this.pivotField && (this.chromeStatus !== 'view-mode' && this.chromeStatus)); }
     @computed get columnWidth() {
         return Math.min(this.props.PanelWidth() /* / NumCast(this.layoutDoc._viewScale, 1)*/ - 2 * this.xMargin,
             this.isStackingView ? Number.MAX_VALUE : this.layoutDoc._columnWidth === -1 ? this.props.PanelWidth() - 2 * this.xMargin : NumCast(this.layoutDoc._columnWidth, 250));
@@ -539,7 +539,7 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
                             style={{ width: !this.isStackingView ? "100%" : this.columnWidth / this.numGroupColumns - 10, marginTop: 10 }}>
                             <EditableView {...editableViewProps} />
                         </div>}
-                    {/* {this.chromeStatus === 'disabled' || !this.props.isSelected() ? (null) :
+                    {/* {!this.chromeStatus || !this.props.isSelected() ? (null) :
                         <Switch
                             onChange={this.onToggle}
                             onClick={this.onToggle}
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 75ec6cd1a..389b449b5 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -300,7 +300,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
                     marginTop: NumCast(this.props.parent.yMargin, 5),
                     width: (style.columnWidth) /
                         ((uniqueHeadings.length +
-                            ((this.props.parent.chromeStatus !== 'view-mode' && this.props.parent.chromeStatus !== 'disabled') ? 1 : 0)) || 1)
+                            ((this.props.parent.chromeStatus !== 'view-mode' && this.props.parent.chromeStatus) ? 1 : 0)) || 1)
                 }}>
                 <div className={"collectionStackingView-collapseBar" + (this.props.headingObject.collapsed === true ? " active" : "")} onClick={this.collapseSection}></div>
                 {/* the default bucket (no key value) has a tooltip that describes what it is.
@@ -359,7 +359,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
                             {this.props.parent.children(this.props.docList, uniqueHeadings.length)}
                             {singleColumn ? (null) : this.props.parent.columnDragger}
                         </div>
-                        {(chromeStatus !== 'view-mode' && chromeStatus !== 'disabled' && type !== DocumentType.PRES) ?
+                        {(chromeStatus !== 'view-mode' && chromeStatus && type !== DocumentType.PRES) ?
                             <div key={`${heading}-add-document`} className="collectionStackingView-addDocumentButton"
                                 style={{ width: style.columnWidth / style.numGroupColumns, marginBottom: 10 }}>
                                 <EditableView
@@ -385,7 +385,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
         return (
             <div className={"collectionStackingViewFieldColumn" + (SnappingManager.GetIsDragging() ? "Dragging" : "")} key={heading}
                 style={{
-                    width: `${100 / ((uniqueHeadings.length + ((chromeStatus !== 'view-mode' && chromeStatus !== 'disabled') ? 1 : 0)) || 1)}%`,
+                    width: `${100 / ((uniqueHeadings.length + ((chromeStatus !== 'view-mode' && chromeStatus) ? 1 : 0)) || 1)}%`,
                     height: undefined, // DraggingManager.GetIsDragging() ? "100%" : undefined,
                     background: this._background
                 }}
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 77dfd126e..d22f6cfdc 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1203,19 +1203,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
         prosediv && (prosediv.keeplocation = undefined);
         const pos = this._editorView?.state.selection.$from.pos || 1;
         keeplocation && setTimeout(() => this._editorView?.dispatch(this._editorView?.state.tr.setSelection(TextSelection.create(this._editorView.state.doc, pos))));
-        const coords = !Number.isNaN(this._downX) ? { left: this._downX, top: this._downY, bottom: this._downY, right: this._downX } : this._editorView?.coordsAtPos(pos);
-
-        // jump rich text menu to this textbox
-        const bounds = this._ref.current?.getBoundingClientRect();
-        if (bounds && this.layoutDoc._chromeStatus && RichTextMenu.Instance) {
-            const x = Math.min(Math.max(bounds.left, 0), window.innerWidth - RichTextMenu.Instance.width);
-            let y = Math.min(Math.max(0, bounds.top - RichTextMenu.Instance.height - 50), window.innerHeight - RichTextMenu.Instance.height);
-            if (coords && coords.left > x && coords.left < x + RichTextMenu.Instance.width && coords.top > y && coords.top < y + RichTextMenu.Instance.height + 50) {
-                y = Math.min(bounds.bottom, window.innerHeight - RichTextMenu.Instance.height);
-            }
-            this._editorView && RichTextMenu.Instance?.updateMenu(this._editorView, undefined, this.props);
-            setTimeout(() => window.document.activeElement === this.ProseRef?.children[0] && RichTextMenu.Instance.jumpTo(x, y), 250);
-        }
+
+        this._editorView && RichTextMenu.Instance?.updateMenu(this._editorView, undefined, this.props);
     }
     onPointerWheel = (e: React.WheelEvent): void => {
         // if a text note is selected and scrollable, stop event to prevent, say, outer collection from zooming.
-- 
cgit v1.2.3-70-g09d2


From d5be520f31d7afe108071734fdc47a22d80f8f45 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 16 Mar 2021 21:04:01 -0400
Subject: from last

---
 src/client/views/PropertiesButtons.tsx | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'src/client/views/PropertiesButtons.tsx')

diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index 15214b692..fbcd55c47 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -37,7 +37,8 @@ export class PropertiesButtons extends React.Component<{}, {}> {
             <Tooltip title={<div className={`dash-tooltip`}>{tooltip(targetDoc?.[property])} </div>} placement="top">
                 <div>
                     <div className={`propertiesButtons-linkButton-empty toggle-${StrCast(targetDoc[property]).includes(":hover") ? "hover" : targetDoc[property] ? "on" : "off"}`}
-                        onPointerDown={undoBatch(() => {
+                        onPointerDown={e => e.stopPropagation()}
+                        onClick={undoBatch(() => {
                             if (SelectionManager.Views().length) {
                                 SelectionManager.Views().forEach(dv => (onClick ?? onPropToggle)(dv, dv.rootDoc, property));
                             } else if (targetDoc) (onClick ?? onPropToggle)(undefined, targetDoc, property);
-- 
cgit v1.2.3-70-g09d2

