From 065a29e87c771b5cd9301b0468fb036e070cad17 Mon Sep 17 00:00:00 2001
From: yunahi <60233430+yunahi@users.noreply.github.com>
Date: Fri, 10 Jul 2020 05:08:53 +0900
Subject: added format shape

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

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 4fda10926..8edd4c4a9 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -293,6 +293,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         SelectionManager.SelectedDocuments().forEach(action((element: DocumentView) => {
             const doc = Document(element.rootDoc);
             if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) {
+                doc.rotation = Number(doc.rotation) + Number(angle);
+                console.log(doc.rotation);
                 const ink = Cast(doc.data, InkField)?.inkData;
                 if (ink) {
 
-- 
cgit v1.2.3-70-g09d2


From 6b5c11a26e114f26f3907342f9afbd47b27cecf4 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sat, 11 Jul 2020 17:54:20 -0400
Subject: restructured ink to make more react-friendly

---
 src/client/util/CurrentUserUtils.ts                |   6 +-
 src/client/util/InteractionUtils.tsx               |  21 +-
 src/client/util/SelectionManager.ts                |   3 -
 src/client/views/AntimodeMenu.tsx                  |   1 -
 src/client/views/DocumentDecorations.tsx           |   5 +-
 src/client/views/InkingStroke.tsx                  |  18 +-
 .../collectionFreeForm/FormatShapePane.tsx         | 801 +++++++--------------
 .../collectionFreeForm/InkOptionsMenu.tsx          |  24 +-
 src/client/views/nodes/ColorBox.tsx                |   1 -
 9 files changed, 299 insertions(+), 581 deletions(-)

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

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index d0ca0e57e..0b644fa79 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -760,9 +760,9 @@ export class CurrentUserUtils {
         doc.activeInkColor = StrCast(doc.activeInkColor, "rgb(0, 0, 0)");
         doc.activeInkWidth = StrCast(doc.activeInkWidth, "1");
         doc.activeInkBezier = StrCast(doc.activeInkBezier, "0");
-        doc.activeFillColor = StrCast(doc.activeFillColor, "none");
-        doc.activeArrowStart = StrCast(doc.activeArrowStart, "none");
-        doc.activeArrowEnd = StrCast(doc.activeArrowEnd, "none");
+        doc.activeFillColor = StrCast(doc.activeFillColor, "");
+        doc.activeArrowStart = StrCast(doc.activeArrowStart, "");
+        doc.activeArrowEnd = StrCast(doc.activeArrowEnd, "");
         doc.activeDash = StrCast(doc.activeDash, "0");
         doc.fontSize = NumCast(doc.fontSize, 12);
         doc["constants-snapThreshold"] = NumCast(doc["constants-snapThreshold"], 10); // 
diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx
index 2883e2056..6ab7bcc87 100644
--- a/src/client/util/InteractionUtils.tsx
+++ b/src/client/util/InteractionUtils.tsx
@@ -3,7 +3,6 @@ import * as beziercurve from 'bezier-curve';
 import * as fitCurve from 'fit-curve';
 import "./InteractionUtils.scss";
 import { Utils } from "../../Utils";
-import InkOptionsMenu from "../views/collections/collectionFreeForm/InkOptionsMenu";
 
 export namespace InteractionUtils {
     export const MOUSETYPE = "mouse";
@@ -96,12 +95,6 @@ export namespace InteractionUtils {
         color: string, width: number, strokeWidth: number, bezier: string, fill: string, arrowStart: string, arrowEnd: string,
         dash: string, scalex: number, scaley: number, shape: string, pevents: string, drawHalo: boolean, nodefs: boolean) {
 
-        // if (InkOptionsMenu.Instance.Pinned) {
-        //     for (var i = 0; i < points.length; i++) {
-        //         points[i].Y -= 35;
-        //     }
-        // }
-
         let pts: { X: number; Y: number; }[] = [];
         if (shape) { //if any of the shape are true
             pts = makePolygon(shape, points);
@@ -127,15 +120,15 @@ export namespace InteractionUtils {
         const dashArray = String(Number(width) * Number(dash));
         const defGuid = Utils.GenerateGuid();
         const arrowDim = Math.max(0.5, 8 / Math.log(Math.max(2, strokeWidth)));
-        return (<svg fill={fill === "none" ? color : fill}> {/* setting the svg fill sets the arrowhead fill */}
+        return (<svg fill={!fill || fill === "none" ? color : fill}> {/* setting the svg fill sets the arrowStart fill */}
             {nodefs ? (null) : <defs>
                 {arrowStart !== "dot" && arrowEnd !== "dot" ? (null) : <marker id={`dot${defGuid}`} orient="auto" overflow="visible">
                     <circle r={1} fill="context-stroke" />
                 </marker>}
-                {arrowStart !== "arrowHead" && arrowEnd !== "arrowHead" ? (null) : <marker id={`arrowHead${defGuid}`} orient="auto" overflow="visible" refX="1.6" refY="0" markerWidth="10" markerHeight="7">
+                {arrowStart !== "arrow" && arrowEnd !== "arrow" ? (null) : <marker id={`arrowStart${defGuid}`} orient="auto" overflow="visible" refX="1.6" refY="0" markerWidth="10" markerHeight="7">
                     <polygon points={`${arrowDim} ${-Math.max(1, arrowDim / 2)}, ${arrowDim} ${Math.max(1, arrowDim / 2)}, -1 0`} />
                 </marker>}
-                {arrowStart !== "arrowEnd" && arrowEnd !== "arrowEnd" ? (null) : <marker id={`arrowEnd${defGuid}`} orient="auto" overflow="visible" refX="1.6" refY="0" markerWidth="10" markerHeight="7">
+                {arrowStart !== "arrow" && arrowEnd !== "arrow" ? (null) : <marker id={`arrowEnd${defGuid}`} orient="auto" overflow="visible" refX="1.6" refY="0" markerWidth="10" markerHeight="7">
                     <polygon points={`${2 - arrowDim} ${-Math.max(1, arrowDim / 2)}, ${2 - arrowDim} ${Math.max(1, arrowDim / 2)}, 3 0`} />
                 </marker>}
             </defs>}
@@ -144,7 +137,7 @@ export namespace InteractionUtils {
                 points={strpts}
                 style={{
                     filter: drawHalo ? "url(#inkSelectionHalo)" : undefined,
-                    fill,
+                    fill: fill ? fill : "transparent",
                     opacity: strokeWidth !== width ? 0.5 : undefined,
                     pointerEvents: pevents as any,
                     stroke: color ?? "rgb(0, 0, 0)",
@@ -153,8 +146,8 @@ export namespace InteractionUtils {
                     strokeLinecap: "round",
                     strokeDasharray: dashArray
                 }}
-                markerStart={`url(#${arrowStart + defGuid})`}
-                markerEnd={`url(#${arrowEnd + defGuid})`}
+                markerStart={`url(#${arrowStart + "Start" + defGuid})`}
+                markerEnd={`url(#${arrowEnd + "End" + defGuid})`}
             />
 
         </svg>);
@@ -163,7 +156,7 @@ export namespace InteractionUtils {
     // export function makeArrow() {
     //     return (
     //         InkOptionsMenu.Instance.getColors().map(color => {
-    //             const id1 = "arrowHeadTest" + color;
+    //             const id1 = "arrowStartTest" + color;
     //             console.log(color);
     //             <marker id={id1} orient="auto" overflow="visible" refX="0" refY="1" markerWidth="10" markerHeight="7">
     //                 <polygon points="0 0, 3 1, 0 2" fill={"#" + color} />
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index af2f320d3..9a968aeda 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -5,7 +5,6 @@ import { computedFn } from "mobx-utils";
 import { List } from "../../fields/List";
 import { Scripting } from "./Scripting";
 import { DocumentManager } from "./DocumentManager";
-import FormatShapePane from "../views/collections/collectionFreeForm/FormatShapePane";
 
 export namespace SelectionManager {
 
@@ -31,8 +30,6 @@ export namespace SelectionManager {
                 manager.SelectedDocuments.set(docView, true);
             }
             Doc.UserDoc().activeSelection = new List(SelectionManager.SelectedDocuments().map(dv => dv.props.Document));
-            FormatShapePane.Instance.selected();
-
         }
         @action
         DeselectDoc(docView: DocumentView): void {
diff --git a/src/client/views/AntimodeMenu.tsx b/src/client/views/AntimodeMenu.tsx
index cb6de1785..3303a5e68 100644
--- a/src/client/views/AntimodeMenu.tsx
+++ b/src/client/views/AntimodeMenu.tsx
@@ -1,7 +1,6 @@
 import React = require("react");
 import { observable, action } from "mobx";
 import "./AntimodeMenu.scss";
-import { inherits } from "util";
 
 /**
  * This is an abstract class that serves as the base for a PDF-style or Marquee-style
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 8edd4c4a9..81b4f9162 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -152,8 +152,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         if (e.button === 0 && !e.altKey && !e.ctrlKey) {
             let child = SelectionManager.SelectedDocuments()[0].ContentDiv!.children[0];
             while (child.children.length) {
-                const next = Array.from(child.children).find(c => !c.className.includes("collectionViewChrome"));
-                if (next?.className.includes("documentView-node")) break;
+                const next = Array.from(child.children).find(c => typeof (c.className) !== "string" || !c.className.includes("collectionViewChrome"));
+                if (typeof (next?.className) === "string" && next?.className.includes("documentView-node")) break;
                 if (next) child = next;
                 else break;
             }
@@ -294,7 +294,6 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             const doc = Document(element.rootDoc);
             if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) {
                 doc.rotation = Number(doc.rotation) + Number(angle);
-                console.log(doc.rotation);
                 const ink = Cast(doc.data, InkField)?.inkData;
                 if (ink) {
 
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 7d9a3c8b3..224abfd77 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -43,8 +43,6 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
     @action
     private formatShape = () => {
         FormatShapePane.Instance.Pinned = true;
-        FormatShapePane.Instance.selected();
-
     }
 
     render() {
@@ -62,14 +60,14 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
         const height = bottom - top;
         const scaleX = (this.props.PanelWidth() - strokeWidth) / (width - strokeWidth);
         const scaleY = (this.props.PanelHeight() - strokeWidth) / (height - strokeWidth);
-        const strokeColor = StrCast(this.layoutDoc.color, ActiveInkColor());
+        const strokeColor = StrCast(this.layoutDoc.color, "");
         const points = InteractionUtils.CreatePolyline(data, left, top, strokeColor, strokeWidth, strokeWidth,
-            StrCast(this.layoutDoc.strokeBezier, ActiveInkBezierApprox()), StrCast(this.layoutDoc.fillColor, ActiveFillColor()),
-            StrCast(this.layoutDoc.arrowStart, ActiveArrowStart()), StrCast(this.layoutDoc.arrowEnd, ActiveArrowEnd()),
-            StrCast(this.layoutDoc.dash, ActiveDash()), scaleX, scaleY, "", "none", this.props.isSelected() && strokeWidth <= 5, false);
+            StrCast(this.layoutDoc.strokeBezier), StrCast(this.layoutDoc.fillColor, "transparent"),
+            StrCast(this.layoutDoc.arrowStart), StrCast(this.layoutDoc.arrowEnd),
+            StrCast(this.layoutDoc.dash), scaleX, scaleY, "", "none", this.props.isSelected() && strokeWidth <= 5, false);
         const hpoints = InteractionUtils.CreatePolyline(data, left, top,
             this.props.isSelected() && strokeWidth > 5 ? strokeColor : "transparent", strokeWidth, (strokeWidth + 15),
-            StrCast(this.layoutDoc.strokeBezier, ActiveInkBezierApprox()), StrCast(this.layoutDoc.fillColor, ActiveFillColor()),
+            StrCast(this.layoutDoc.strokeBezier), StrCast(this.layoutDoc.fillColor, "transparent"),
             "none", "none", "0", scaleX, scaleY, "", this.props.active() ? "visiblepainted" : "none", false, true);
         return (
             <svg className="inkingStroke"
@@ -106,9 +104,9 @@ export function SetActiveArrowEnd(value: string) { ActiveInkPen() && (ActiveInkP
 export function SetActiveDash(dash: string): void { !isNaN(parseInt(dash)) && ActiveInkPen() && (ActiveInkPen().activeDash = dash); }
 export function ActiveInkPen(): Doc { return Cast(Doc.UserDoc().activeInkPen, Doc, null); }
 export function ActiveInkColor(): string { return StrCast(ActiveInkPen()?.activeInkColor, "black"); }
-export function ActiveFillColor(): string { return StrCast(ActiveInkPen()?.activeFillColor, "none"); }
-export function ActiveArrowStart(): string { return StrCast(ActiveInkPen()?.activeArrowStart, "none"); }
-export function ActiveArrowEnd(): string { return StrCast(ActiveInkPen()?.activeArrowEnd, "none"); }
+export function ActiveFillColor(): string { return StrCast(ActiveInkPen()?.activeFillColor, ""); }
+export function ActiveArrowStart(): string { return StrCast(ActiveInkPen()?.activeArrowStart, ""); }
+export function ActiveArrowEnd(): string { return StrCast(ActiveInkPen()?.activeArrowEnd, ""); }
 export function ActiveDash(): string { return StrCast(ActiveInkPen()?.activeDash, "0"); }
 export function ActiveInkWidth(): string { return StrCast(ActiveInkPen()?.activeInkWidth, "1"); }
 export function ActiveInkBezierApprox(): string { return StrCast(ActiveInkPen()?.activeInkBezier); }
diff --git a/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx b/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx
index bf2218fdc..321b5648e 100644
--- a/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx
+++ b/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx
@@ -3,10 +3,9 @@ import AntimodeMenu from "../../AntimodeMenu";
 import { observer } from "mobx-react";
 import { observable, action, computed } from "mobx";
 import "./FormatShapePane.scss";
-import { SetActiveInkWidth } from "../../InkingStroke";
 import { Scripting } from "../../../util/Scripting";
 import { InkField } from "../../../../fields/InkField";
-import { Doc } from "../../../../fields/Doc";
+import { Doc, Opt } from "../../../../fields/Doc";
 import { SelectionManager } from "../../../util/SelectionManager";
 import { DocumentView } from "../../../views/nodes/DocumentView";
 import { Document } from "../../../../fields/documentSchemas";
@@ -15,7 +14,6 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { IconProp, library } from '@fortawesome/fontawesome-svg-core';
 import { faRulerCombined, faFillDrip, faPenNib } from "@fortawesome/free-solid-svg-icons";
 import { Cast, StrCast, BoolCast, NumCast } from "../../../../fields/Types";
-import e = require("express");
 
 library.add(faRulerCombined, faFillDrip, faPenNib);
 
@@ -27,31 +25,131 @@ export default class FormatShapePane extends AntimodeMenu {
     private _width = ["1", "5", "10", "100"];
     private _mode = ["fill-drip", "ruler-combined"];
     private _subMenu = ["fill", "line", "size", "position"];
+    @computed get inks() {
+        const inks: DocumentView[] = [];
+        const docs = SelectionManager.SelectedDocuments();
+        for (var i = 0; i < docs.length; i++) {
+            if (Document(docs[i].rootDoc).type === DocumentType.INK) {
+                inks.push(docs[i]);
+            }
+        }
+        return inks.length ? inks : undefined;
+    }
     @observable private _subOpen = [false, false, false, false];
     @observable private collapsed: boolean = false;
     @observable private currMode: string = "fill-drip";
+    @observable _lock = false;
     @observable _fillBtn = false;
     @observable _lineBtn = false;
-    @observable _selectDoc: DocumentView[] = [];
-    @observable _noFill = false;
-    @observable _solidFill = false;
-    @observable _noLine = false;
-    @observable _solidLine = false;
-    @observable _dashLine = false;
-    @observable _lock = false;
-    @observable _multiple = false;
-    @observable _widthBtn = false;
-    @observable _single = false;
-    @observable _arrowHead = false;
-    @observable _arrowEnd = false;
-    @observable _currSizeHeight = "10";
-    @observable _currSizeWidth = "10";
-    @observable _currRotation = "10";
-    @observable _currPositionHorizontal = "10";
-    @observable _currPositionVertical = "10";
-    @observable _currWidth = "10";
-    @observable _currFill = "#D0021B";
-    @observable _currColor = "#D0021B";
+    _lastFill = "#D0021B";
+    _lastLine = "#D0021B";
+    _lastDash = "2";
+
+    @computed get _noFill() {
+        return this.inks?.reduce((p, i) => p && !i.rootDoc.fillColor ? true : false, true) || false;
+    }
+    @computed get _solidFill() {
+        return this.inks?.reduce((p, i) => p && i.rootDoc.fillColor ? true : false, true) || false;
+    }
+    set _noFill(value) { this._currFill = value ? "" : this._lastFill; }
+    set _solidFill(value) { this._noFill = !value; }
+
+    @computed get _noLine() {
+        return this.inks?.reduce((p, i) => p && !i.rootDoc.color ? true : false, true) || false;
+    }
+    @computed get _solidLine() {
+        return this.inks?.reduce((p, i) => p &&
+            i.rootDoc.color && (i.rootDoc.dash === undefined || i.rootDoc.dash === "0") ? true : false, true) || false;
+    }
+    @computed get _dashLine() {
+        return !this._noLine && this.inks?.reduce((p, i) =>
+            (p === undefined || (p && p === i.rootDoc.dash)) && i.rootDoc.dash !== "0" ? StrCast(i.rootDoc.dash) : "", undefined as Opt<string>) || "";
+    }
+    set _noLine(value) { this._currColor = value ? "" : this._lastLine; }
+    set _solidLine(value) { this._dashLine = ""; this._noLine = !value; }
+    set _dashLine(value) {
+        value && (this._lastDash = value); this._noLine = false;
+        this.inks?.forEach(i => i.rootDoc.dash = value ? this._lastDash : undefined)
+    }
+
+    @computed get _currFill() {
+        const cfill = this._noFill || !this.inks ? "" : StrCast(this.inks[0].rootDoc.fillColor);
+        cfill && (this._lastFill = cfill);
+        return cfill;
+    }
+    @computed get _currColor() {
+        const ccol = this._noLine || !this.inks ? "" : StrCast(this.inks[0].rootDoc.color, "");
+        this._lastLine = ccol ? ccol : this._lastLine;
+        return ccol;
+    }
+    set _currFill(value) { value && (this._lastFill = value); this.inks?.forEach(i => i.rootDoc.fillColor = value); }
+    set _currColor(value) { value && (this._lastLine = value); this.inks?.forEach(i => i.rootDoc.color = value ? value : undefined) }
+
+    @computed get _arrowStart() {
+        return this.inks?.reduce((p, i) =>
+            (p === undefined || (p && p === i.rootDoc.arrowStart)) ? StrCast(i.rootDoc.arrowStart) : "", undefined as Opt<string>) || "";
+    }
+    @computed get _arrowEnd() {
+        return this.inks?.reduce((p, i) =>
+            (p === undefined || (p && p === i.rootDoc.arrowEnd)) ? StrCast(i.rootDoc.arrowEnd) : "", undefined as Opt<string>) || ""
+    }
+    set _arrowStart(value) { this.inks?.forEach(i => i.rootDoc.arrowStart = value); }
+    set _arrowEnd(value) { this.inks?.forEach(i => i.rootDoc.arrowEnd = value); }
+
+    @computed get _currSizeHeight() {
+        return this.inks?.reduce((p, i) =>
+            (p === undefined || (p === NumCast(i.rootDoc._height).toString())) ? NumCast(i.rootDoc._height).toString() : "", undefined as Opt<string>) || ""
+    }
+    @computed get _currSizeWidth() {
+        return this.inks?.reduce((p, i) =>
+            (p === undefined || (p === NumCast(i.rootDoc._width).toString())) ? NumCast(i.rootDoc._width).toString() : "", undefined as Opt<string>) || ""
+    }
+    @computed get _currRotation() {
+        return this.inks?.reduce((p, i) =>
+            (p === undefined || (p === NumCast(i.rootDoc.rotation).toString())) ? NumCast(i.rootDoc.rotation).toString() : "", undefined as Opt<string>) || ""
+    }
+    @computed get _currPositionHorizontal() {
+        return this.inks?.reduce((p, i) =>
+            (p === undefined || (p === NumCast(i.rootDoc.x).toString())) ? NumCast(i.rootDoc.x).toString() : "", undefined as Opt<string>) || ""
+    }
+    @computed get _currPositionVertical() {
+        return this.inks?.reduce((p, i) =>
+            (p === undefined || (p === NumCast(i.rootDoc.y).toString())) ? NumCast(i.rootDoc.y).toString() : "", undefined as Opt<string>) || ""
+    }
+    @computed get _currStrokeWidth() {
+        return this.inks?.reduce((p, i) =>
+            (p === undefined || (p === NumCast(i.rootDoc.strokeWidth).toString())) ? NumCast(i.rootDoc.strokeWidth).toString() : "", undefined as Opt<string>) || ""
+    }
+    set _currPositionHorizontal(value) { this.inks?.forEach(i => i.rootDoc.x = Number(value)); }
+    set _currPositionVertical(value) { this.inks?.forEach(i => i.rootDoc.y = Number(value)); }
+    set _currRotation(value) { this.inks?.forEach(i => i.rootDoc.rotation = Number(value)); }
+    set _currStrokeWidth(value) { this.inks?.forEach(i => i.rootDoc.strokeWidth = Number(value)); }
+    set _currSizeWidth(value) {
+        this.inks?.forEach(i => {
+            const doc = i.rootDoc;
+            if (doc._width && doc._height) {
+                const oldWidth = NumCast(doc._width);
+                const oldHeight = NumCast(doc._height);
+                doc._width = Number(value);
+                if (this._lock) {
+                    doc._height = (doc._width * oldHeight) / oldWidth;
+                }
+            }
+        });
+    }
+    set _currSizeHeight(value) {
+        this.inks?.forEach(i => {
+            const doc = i.rootDoc;
+            if (doc._width && doc._height) {
+                const oldWidth = NumCast(doc._width);
+                const oldHeight = NumCast(doc._height);
+                doc._height = Number(value);
+                if (this._lock) {
+                    doc._width = (doc._height * oldWidth) / oldHeight;
+                }
+            }
+        });
+    }
 
     constructor(props: Readonly<{}>) {
         super(props);
@@ -80,191 +178,40 @@ export default class FormatShapePane extends AntimodeMenu {
         this.Pinned = false;
     }
 
-    //if multiple inks are selected and do not share the same prop, leave blank
-    @action
-    checkSame = () => {
-        const docs = SelectionManager.SelectedDocuments();
-        const inks: DocumentView[] = [];
-        for (var i = 0; i < docs.length; i++) {
-            if (Document(docs[i].rootDoc).type === DocumentType.INK) {
-                inks.push(docs[i]);
-            }
-        }
-        this._noFill = Document(inks[0].rootDoc).fillColor === "none" ? true : false;
-        this._solidFill = Document(inks[0].rootDoc).fillColor === "none" ? false : true;
-        this._noLine = Document(inks[0].rootDoc).color === "none" ? true : false;
-        if (Document(inks[0].rootDoc).color !== "none") {
-            this._solidLine = true;
-            this._dashLine = true;
-            if (Document(inks[0].rootDoc).dash === "0") {
-                this._dashLine = false;
-            } else {
-                this._solidLine = false;
-
-            }
-        }
-        this._currWidth = String(Document(inks[0].rootDoc).strokeWidth);
-        this._currFill = String(Document(inks[0].rootDoc).fillColor);
-        this._currColor = String(Document(inks[0].rootDoc).color);
-        this._arrowHead = Document(inks[0].rootDoc).arrowStart === "none" ? false : true;
-        this._arrowEnd = Document(inks[0].rootDoc).arrowEnd === "none" ? false : true;
-        this._currSizeHeight = String(Document(inks[0].rootDoc)._height);
-        this._currSizeWidth = String(Document(inks[0].rootDoc)._width);
-        this._currRotation = String(Document(inks[0].rootDoc).rotation);
-        this._currPositionHorizontal = String(Document(inks[0].rootDoc).x);
-        this._currPositionVertical = String(Document(inks[0].rootDoc).y);
-        for (var i = 0; i < inks.length; i++) {
-            if (Document(inks[i].rootDoc).strokeWidth !== Document(inks[0].rootDoc).strokeWidth) {
-                this._currWidth = "";
-            }
-            if (Document(inks[i].rootDoc).color !== Document(inks[0].rootDoc).color) {
-                this._noLine = false;
-                this._solidLine = false;
-                this._dashLine = false;
-            }
-            if (Document(inks[i].rootDoc).fillColor !== Document(inks[0].rootDoc).fillColor) {
-                this._solidFill = false;
-                this._noFill = false;
-            }
-            if (Document(inks[i].rootDoc).arrowStart !== Document(inks[0].rootDoc).arrowStart) {
-                this._arrowHead = false;
-            }
-            if (Document(inks[i].rootDoc).arrowEnd !== Document(inks[0].rootDoc).arrowEnd) {
-                this._arrowEnd = false;
-            }
-            if (Document(inks[i].rootDoc).x !== Document(inks[0].rootDoc).x) {
-                this._currPositionHorizontal = "";
-            }
-            if (Document(inks[i].rootDoc).y !== Document(inks[0].rootDoc).y) {
-                this._currPositionVertical = "";
-            }
-            if (Document(inks[i].rootDoc)._width !== Document(inks[0].rootDoc)._width) {
-                this._currSizeWidth = "";
-            }
-            if (Document(inks[i].rootDoc)._height !== Document(inks[0].rootDoc)._height) {
-                this._currSizeHeight = "";
-            }
-            if (Document(inks[i].rootDoc).rotation !== Document(inks[0].rootDoc).rotation) {
-                this._currRotation = "";
-            }
-        }
-    }
-
-
     @action
     upDownButtons = (dirs: string, field: string) => {
-        SelectionManager.SelectedDocuments().forEach(action((element: DocumentView) => {
-            const doc = Document(element.rootDoc);
-            if (doc.type === DocumentType.INK) {
-                switch (field) {
-                    case "width":
-                        if (doc.strokeWidth) {
-                            doc.strokeWidth = dirs === "up" ? doc.strokeWidth + 1 : doc.strokeWidth - 1;
-                            SetActiveInkWidth(String(doc.strokeWidth));
+        switch (field) {
+            case "horizontal": this.inks?.forEach(i => i.rootDoc.x = NumCast(i.rootDoc.x) + (dirs === "up" ? 10 : -10)); break;
+            case "vertical": this.inks?.forEach(i => i.rootDoc.y = NumCast(i.rootDoc.y) + (dirs === "up" ? 10 : -10)); break;
+            case "rotation": this.rotate((dirs === "up" ? .1 : -.1)); break;
+            case "width": this.inks?.forEach(i => i.rootDoc.strokeWidth = NumCast(i.rootDoc.strokeWidth) + (dirs === "up" ? .1 : -.1)); break;
+            case "sizeWidth":
+                this.inks?.forEach(i => {
+                    const doc = i.rootDoc;
+                    if (doc._width && doc._height) {
+                        const oldWidth = NumCast(doc._width);
+                        const oldHeight = NumCast(doc._height);
+                        doc._width = NumCast(doc._width) + (dirs === "up" ? 10 : - 10);
+                        if (this._lock) {
+                            doc._height = (NumCast(doc._width) * oldHeight) / oldWidth;
                         }
-                        break;
-                    case "sizeWidth":
-                        if (doc._width && doc._height) {
-                            const oldWidth = doc._width;
-                            const oldHeight = doc._height;
-                            doc._width = dirs === "up" ? doc._width + 10 : doc._width - 10;
-                            if (this._lock) {
-                                doc._height = (doc._width * oldHeight) / oldWidth;
-                            }
-                        }
-                        break;
-                    case "sizeHeight":
-                        if (doc._width && doc._height) {
-                            const oldWidth = doc._width;
-                            const oldHeight = doc._height;
-                            doc._height = dirs === "up" ? doc._height + 10 : doc._height - 10;
-                            if (this._lock) {
-                                doc._width = (doc._height * oldWidth) / oldHeight;
-                            }
-                        }
-                        break;
-                    case "horizontal":
-                        if (doc.x) {
-                            doc.x = dirs === "up" ? doc.x + 10 : doc.x - 10;
-                        }
-                        break;
-                    case "vertical":
-                        if (doc.y) {
-                            doc.y = dirs === "up" ? doc.y + 10 : doc.y - 10;
-                        }
-                    case "rotation":
-                        this.rotate(dirs === "up" ? Number(doc.rotation) + Number(0.1) : Number(doc.rotation) - Number(0.1));
-                        break;
-                    default:
-                        break;
-                }
-                this.selected();
-            }
-        }));
-    }
-
-
-    @action
-    editProperties = (value: any, field: string) => {
-        SelectionManager.SelectedDocuments().forEach(action((element: DocumentView) => {
-            const doc = Document(element.rootDoc);
-            if (doc.type === DocumentType.INK) {
-                switch (field) {
-                    case "width":
-                        SetActiveInkWidth(value);
-                        doc.strokeWidth = Number(value);
-                        break;
-                    case "color":
-                        doc.color = String(value);
-                        break;
-                    case "fill":
-                        doc.fillColor = String(value);
-                        break;
-                    case "bezier":
-                        break;
-                    case "arrowStart":
-                        doc.arrowStart = String(value);
-                        break;
-                    case "arrowEnd":
-                        doc.arrowEnd = String(value);
-                        break;
-                    case "dash":
-                        doc.dash = String(value);
-                        break;
-                    case "widthSize":
-                        if (doc._width && doc._height) {
-                            const oldWidth = doc._width;
-                            const oldHeight = doc._height;
-                            doc._width = Number(value);
-                            if (this._lock) {
-                                doc._height = (doc._width * oldHeight) / oldWidth;
-                            }
-                        }
-                        break;
-                    case "heightSize":
-                        if (doc._width && doc._height) {
-                            const oldWidth = doc._width;
-                            const oldHeight = doc._height;
-                            doc._height = Number(value);
-                            if (this._lock) {
-                                doc._width = (doc._height * oldWidth) / oldHeight;
-                            }
+                    }
+                });
+                break;
+            case "sizeHeight":
+                this.inks?.forEach(i => {
+                    const doc = i.rootDoc;
+                    if (doc._width && doc._height) {
+                        const oldWidth = NumCast(doc._width);
+                        const oldHeight = NumCast(doc._height)
+                        doc._height = NumCast(doc._height) + (dirs === "up" ? 10 : - 10);
+                        if (this._lock) {
+                            doc._width = (NumCast(doc._height) * oldWidth) / oldHeight;
                         }
-                        break;
-                    case "horizontal":
-                        doc.x = Number(value);
-                        break;
-                    case "vertical":
-                        doc.y = Number(value);
-                        break;
-                    default:
-                        break;
-                }
-            }
-            this.selected();
-        }));
-        this.checkSame();
-
+                    }
+                });
+                break;
+        }
     }
 
     @computed get close() {
@@ -294,69 +241,6 @@ export default class FormatShapePane extends AntimodeMenu {
         return modes;
     }
 
-    //detects currently selected document and change value in pane
-    @action
-    selected = () => {
-        this._selectDoc = SelectionManager.SelectedDocuments();
-        if (this._selectDoc.length === 1 && Document(this._selectDoc[0].rootDoc).type === DocumentType.INK) {
-            this._single = true;
-            const doc = Document(this._selectDoc[0].rootDoc);
-            if (doc.type === DocumentType.INK) {
-                if (doc.fillColor === "none") {
-                    this._noFill = true;
-                    this._solidFill = false;
-                } else {
-                    this._solidFill = true;
-                    this._noFill = false;
-                    this._currFill = String(doc.fillColor);
-                }
-                if (doc.color === "none") {
-                    this._noLine = true;
-                    this._solidLine = false;
-                    this._dashLine = false;
-                } else {
-                    this._currWidth = String(doc.strokeWidth);
-                    this._currColor = String(doc.color);
-                    if (doc.dash === "0") {
-                        this._solidLine = true;
-                        this._noLine = false;
-                        this._dashLine = false;
-                    } else {
-                        this._dashLine = true;
-                        this._noLine = false;
-                        this._solidLine = false;
-                    }
-
-                    this._arrowHead = doc.arrowStart === "none" ? false : true;
-                    this._arrowEnd = doc.arrowEnd === "none" ? false : true;
-                    this._currPositionHorizontal = String(doc.x);
-                    this._currPositionVertical = String(doc.y);
-                    this._currRotation = String(doc.rotation);
-                    this._currSizeHeight = String(doc._height);
-                    this._currSizeWidth = String(doc._width);
-                }
-
-            }
-        } else {
-            this._noFill = false;
-            this._solidFill = false;
-            this._single = false;
-            this._currFill = "#D0021B";
-            this._noLine = false;
-            this._solidLine = false;
-            this._dashLine = false;
-            this._currColor = "#D0021B";
-            this._arrowHead = false;
-            this._arrowEnd = false;
-            this._currPositionHorizontal = "";
-            this._currPositionVertical = "";
-            this._currRotation = "";
-            this._currSizeHeight = "";
-            this._currSizeWidth = "";
-        }
-        this.checkSame();
-    }
-
     @action
     rotate = (degrees: number) => {
         SelectionManager.SelectedDocuments().forEach(action((element: DocumentView) => {
@@ -395,143 +279,80 @@ export default class FormatShapePane extends AntimodeMenu {
         }));
     }
 
-    @action
-    toggle = (check: string) => {
-        switch (check) {
-            case "noFill":
-                if (!this._noFill) {
-                    this._noFill = true;
-                    this._solidFill = false;
-                }
-                break;
-            case "solidFill":
-                if (!this._solidFill) {
-                    this._solidFill = true;
-                    this._noFill = false;
-                    if (this._currFill === "none") {
-                        this._currFill = "#D0021B";
-                    }
-                }
-                break;
-            case "noLine":
-                if (!this._noLine) {
-                    this._noLine = true;
-                    this._solidLine = false;
-                    this._dashLine = false;
-                }
-                break;
-            case "solidLine":
-                if (!this._solidLine) {
-                    this._solidLine = true;
-                    this._noLine = false;
-                    this._dashLine = false;
-                    if (this._currColor === "none") {
-                        this._currColor = "#D0021B";
-                    }
-                }
-                break;
-            case "dashLine":
-                if (!this._dashLine) {
-                    this._dashLine = true;
-                    this._solidLine = false;
-                    this._noLine = false;
-                    if (this._currColor === "none") {
-                        this._currColor = "#D0021B";
-                    }
-                }
-                break;
-            case "lock":
-                if (this._lock) {
-                    this._lock = false;
-                } else {
-                    this._lock = true;
-                }
-                break;
-            case "arrowHead":
-                this._arrowHead = this._arrowHead ? false : true;
-                break;
-            case "arrowEnd":
-                this._arrowEnd = this._arrowEnd ? false : true;
-                break;
-            default:
-                break;
-        }
-    }
-
     @computed get subMenu() {
         const fillCheck = <div style={{ width: "inherit", backgroundColor: "#323232", color: "white", }}>
-            <input id="nofill" style={{ width: "inherit", position: "absolute" }} type="checkbox" checked={this._noFill} onChange={action(() => { this.toggle("noFill"); this.editProperties("none", "fill"); })} />
+            <input id="nofill" style={{ width: "inherit", position: "absolute" }} type="checkbox" checked={this._noFill} onChange={action(() => this._noFill = true)} />
             No Fill
-            <br></br>
-            <input id="solidfill" style={{ width: "inherit", position: "absolute" }} type="checkbox" checked={this._solidFill} onChange={action(() => { this.toggle("solidFill"); this.editProperties(this._currFill, "fill"); })} />
+            <br />
+            <input id="solidfill" style={{ width: "inherit", position: "absolute" }} type="checkbox" checked={this._solidFill} onChange={action(() => this._solidFill = true)} />
             Solid Fill
-            <br></br>
-            <br></br>
+            <br />
+            <br />
             {this._solidFill ? "Color" : ""}
             {this._solidFill ? this.fillButton : ""}
             {this._fillBtn && this._solidFill ? this.fillPicker : ""}
 
         </div>;
-        const arrows = <> <input id="arrowHead" style={{ width: "inherit", position: "absolute" }} type="checkbox" checked={this._arrowHead} onChange={action(() => { this.toggle("arrowHead"); this.editProperties(this._arrowHead ? "arrowHead" : "none", "arrowStart"); })} />
+        const arrows = <> <input id="arrowStart" style={{ width: "inherit", position: "absolute" }} type="checkbox" checked={this._arrowStart !== ""} onChange={action(() => this._arrowStart = this._arrowStart ? "" : "arrow")} />
          Arrow Head
-            <br></br>
+            <br />
 
-            <input id="arrowEnd" style={{ width: "inherit", position: "absolute" }} type="checkbox" checked={this._arrowEnd} onChange={action(() => { this.toggle("arrowEnd"); this.editProperties(this._arrowEnd ? "arrowEnd" : "none", "arrowEnd"); })} />
+            <input id="arrowEnd" style={{ width: "inherit", position: "absolute" }} type="checkbox" checked={this._arrowEnd !== ""} onChange={action(() => this._arrowEnd = this._arrowEnd ? "" : "arrow")} />
          Arrow End
-            <br></br></>;
+            <br /></>;
         const lineCheck = <div style={{ width: "inherit", backgroundColor: "#323232", color: "white", }}>
-            <input id="noLine" style={{ width: "inherit", position: "absolute" }} type="checkbox" checked={this._noLine} onChange={action(() => { this.toggle("noLine"); this.editProperties("none", "color"); })} />
+            <input id="noLine" style={{ width: "inherit", position: "absolute" }} type="checkbox" checked={this._noLine} onChange={action(() => this._noLine = true)} />
                 No Line
-                <br></br>
-            <input id="solidLine" style={{ width: "inherit", position: "absolute" }} type="checkbox" checked={this._solidLine} onChange={action(() => { this.toggle("solidLine"); this.editProperties(this._currColor, "color"); this.editProperties("0", "dash"); })} />
+            <br />
+            <input id="solidLine" style={{ width: "inherit", position: "absolute" }} type="checkbox" checked={this._solidLine} onChange={action(() => this._solidLine = true)} />
                 Solid Line
-                <br></br>
-            <input id="dashLine" style={{ width: "inherit", position: "absolute" }} type="checkbox" checked={this._dashLine} onChange={action(() => { this.toggle("dashLine"); this.editProperties(this._currColor, "color"); this.editProperties("2", "dash"); })} />
+            <br />
+            <input id="dashLine" style={{ width: "inherit", position: "absolute" }} type="checkbox" checked={this._dashLine ? true : false} onChange={action(() => this._dashLine = "2")} />
                 Dash Line
-                <br></br>
-            <br></br>
+            <br />
+            <br />
             {(this._solidLine || this._dashLine) ? "Color" : ""}
             {(this._solidLine || this._dashLine) ? this.lineButton : ""}
             {this._lineBtn && (this._solidLine || this._dashLine) ? this.linePicker : ""}
-            <br></br>
+            <br />
             {(this._solidLine || this._dashLine) ? "Width" : ""}
             {(this._solidLine || this._dashLine) ? this.widthInput : ""}
-            <br></br>
-            <br></br>
+            <br />
+            <br />
             {(this._solidLine || this._dashLine) ? arrows : ""}
 
         </div>;
 
         const sizeCheck = <div style={{ width: "inherit", backgroundColor: "#323232", color: "white", }}>
             Height {this.sizeHeightInput}
-            <br></br>
-            <br></br>
+            <br />
+            <br />
 
 
             Width {this.sizeWidthInput}
-            <br></br>
-            <br></br>
+            <br />
+            <br />
 
-            <input id="lock" style={{ width: "inherit", position: "absolute", right: 0 }} type="checkbox" checked={this._lock} onChange={action(() => { this.toggle("lock"); })} />
+            <input id="lock" style={{ width: "inherit", position: "absolute", right: 0 }} type="checkbox" checked={this._lock} onChange={action(() => this._lock = !this._lock)} />
                 Lock Ratio
-            <br></br>
-            <br></br>
+            <br />
+            <br />
 
 
             Rotation {this.rotationInput}
-            <br></br>
-            <br></br>
+            <br />
+            <br />
 
 
         </div>;
         const positionCheck = <div style={{ width: "inherit", backgroundColor: "#323232", color: "white", }}>
             Horizontal {this.positionHorizontalInput}
-            <br></br>
-            <br></br>
+            <br />
+            <br />
 
             Vertical {this.positionVerticalInput}
-            <br></br>
-            <br></br>
+            <br />
+            <br />
 
 
         </div>;
@@ -574,29 +395,30 @@ export default class FormatShapePane extends AntimodeMenu {
     }
 
     @computed get fillButton() {
-        const fillButton = <><button
-            className="antimodeMenu-button"
-            key="fill"
-            title="fillChanger"
-            onPointerDown={action(e => this._fillBtn = !this._fillBtn)}
-            style={{
-                // backgroundColor: "121212",
-                position: "absolute", right: 80
-            }}>
-            <FontAwesomeIcon icon="fill-drip" size="lg" />
-            <div className="color-previewI" style={{ backgroundColor: this._currFill ?? "121212" }}></div>
-        </button>
+        return <>
+            <button
+                className="antimodeMenu-button"
+                key="fill"
+                title="fillChanger"
+                onPointerDown={action(e => this._fillBtn = !this._fillBtn)}
+                style={{
+                    // backgroundColor: "121212",
+                    position: "absolute", right: 80
+                }}>
+                <FontAwesomeIcon icon="fill-drip" size="lg" />
+                <div className="color-previewI" style={{ backgroundColor: this._currFill ?? "121212" }}></div>
+            </button>
             <br></br>
-            <br></br></>;
-        return fillButton;
+            <br></br>
+        </>;
     }
     @computed get fillPicker() {
-        const fillPicker = <div className="btn-group-palette" key="fill" >
+        return <div className="btn-group-palette" key="fill" >
             {this._palette.map(color => {
                 return <button
                     className="antimodeMenu-button"
                     key={color}
-                    onPointerDown={action(() => { this._currFill = color; this.editProperties(color, "fill"); })}
+                    onPointerDown={action(() => this._currFill = color)}
                     style={{
                         // backgroundColor: this._fillBtn ? "121212" : "",
                         zIndex: 1001
@@ -606,33 +428,33 @@ export default class FormatShapePane extends AntimodeMenu {
             })}
 
         </div>;
-        return fillPicker;
     }
 
     @computed get lineButton() {
-        const lineButton = <><button
-            className="antimodeMenu-button"
-            key="line"
-            title="lineChanger"
-            onPointerDown={action(e => this._lineBtn = !this._lineBtn)}
-            style={{
-                // backgroundColor: "121212",
-                position: "absolute", right: 80
-            }}>
-            <FontAwesomeIcon icon="pen-nib" size="lg" />
-            <div className="color-previewI" style={{ backgroundColor: this._currColor ?? "121212" }}></div>
-        </button>
-            <br></br>
-            <br></br></>;
-        return lineButton;
+        return <>
+            <button
+                className="antimodeMenu-button"
+                key="line"
+                title="lineChanger"
+                onPointerDown={action(e => this._lineBtn = !this._lineBtn)}
+                style={{
+                    // backgroundColor: "121212",
+                    position: "absolute", right: 80
+                }}>
+                <FontAwesomeIcon icon="pen-nib" size="lg" />
+                <div className="color-previewI" style={{ backgroundColor: this._currColor ?? "121212" }}></div>
+            </button>
+            <br />
+            <br />
+        </>;
     }
     @computed get linePicker() {
-        const linePicker = <div className="btn-group-palette" key="line" >
+        return <div className="btn-group-palette" key="line" >
             {this._palette.map(color => {
                 return <button
                     className="antimodeMenu-button"
                     key={color}
-                    onPointerDown={action(() => { this._currColor = color; this.editProperties(color, "color"); })}
+                    onPointerDown={action(() => this._currColor = color)}
                     style={{
                         // backgroundColor: this._lineBtn ? "121212" : "",
                         zIndex: 1001
@@ -642,19 +464,19 @@ export default class FormatShapePane extends AntimodeMenu {
             })}
 
         </div>;
-        return linePicker;
     }
     @computed get widthInput() {
         const widthInput = <>
             <input
                 style={{ color: "black", width: 80, position: "absolute", right: 20 }}
-                type="text" value={this._currWidth}
-                onChange={e => this.onChange(e.target.value, "width")}
-                autoFocus></input>  <button
-                    className="antiMenu-Buttonup"
-                    key="up"
-                    onPointerDown={action(() => { this.upDownButtons("up", "width"); })}
-                    style={{ position: "absolute", width: 20, height: 10, right: 0, padding: 0 }}>
+                type="text" value={this._currStrokeWidth}
+                onChange={e => this._currStrokeWidth = e.target.value}
+                autoFocus />
+            <button
+                className="antiMenu-Buttonup"
+                key="up"
+                onPointerDown={action(() => { this.upDownButtons("up", "width"); })}
+                style={{ position: "absolute", width: 20, height: 10, right: 0, padding: 0 }}>
                 ˄
             </button>
             <br />
@@ -672,8 +494,8 @@ export default class FormatShapePane extends AntimodeMenu {
             <input
                 style={{ color: "black", width: 80, position: "absolute", right: 20 }}
                 type="text" value={this._currSizeHeight}
-                onChange={e => this.onChange(e.target.value, "sizeHeight")}
-                autoFocus></input>
+                onChange={e => this._currSizeHeight = e.target.value}
+                autoFocus />
             <button
                 className="antiMenu-Buttonup"
                 key="up"
@@ -698,8 +520,8 @@ export default class FormatShapePane extends AntimodeMenu {
             <input
                 style={{ color: "black", width: 80, position: "absolute", right: 20 }}
                 type="text" value={this._currSizeWidth}
-                onChange={e => this.onChange(e.target.value, "sizeWidth")}
-                autoFocus></input>
+                onChange={e => this._currSizeWidth = e.target.value}
+                autoFocus />
             <button
                 className="antiMenu-Buttonup"
                 key="up"
@@ -707,7 +529,7 @@ export default class FormatShapePane extends AntimodeMenu {
                 style={{ position: "absolute", width: 20, height: 10, right: 0, padding: 0 }}>
                 ˄
             </button>
-            <br></br>
+            <br />
             <button
                 className="antiMenu-Buttonup"
                 key="up"
@@ -724,7 +546,7 @@ export default class FormatShapePane extends AntimodeMenu {
                 <input
                     style={{ color: "black", width: 80, position: "absolute", right: 20 }}
                     type="text" value={this._currRotation}
-                    onChange={e => this.onChange(e.target.value, "rotation")}
+                    onChange={e => this._currRotation = e.target.value}
                     autoFocus></input>
                 <button
                     className="antiMenu-Buttonup"
@@ -733,7 +555,7 @@ export default class FormatShapePane extends AntimodeMenu {
                     style={{ position: "absolute", width: 20, height: 10, right: 0, padding: 0 }}>
                     ˄
             </button>
-                <br></br>
+                <br />
                 <button
                     className="antiMenu-Buttonup"
                     key="up"
@@ -745,137 +567,56 @@ export default class FormatShapePane extends AntimodeMenu {
     }
 
     @computed get positionHorizontalInput() {
-        const positionHorizontalInput =
-            <><input
+        return <>
+            <input
                 style={{ color: "black", width: 80, position: "absolute", right: 20 }}
                 type="text" value={this._currPositionHorizontal}
-                onChange={e => this.onChange(e.target.value, "positionHorizontal")}
-                autoFocus></input>
-                <button
-                    className="antiMenu-Buttonup"
-                    key="up"
-                    onPointerDown={action(() => { this.upDownButtons("up", "horizontal"); })}
-                    style={{ position: "absolute", width: 20, height: 10, right: 0, padding: 0 }}>
-                    ˄
+                onChange={e => this._currPositionHorizontal = e.target.value}
+                autoFocus
+            />
+            <button
+                className="antiMenu-Buttonup"
+                key="up"
+                onPointerDown={action(() => { this.upDownButtons("up", "horizontal"); })}
+                style={{ position: "absolute", width: 20, height: 10, right: 0, padding: 0 }}>
+                ˄
+                </button>
+            <br></br>
+            <button
+                className="antiMenu-Buttonup"
+                key="up"
+                onPointerDown={action(() => { this.upDownButtons("down", "horizontal"); })}
+                style={{ position: "absolute", width: 20, height: 10, right: 0, padding: 0, marginTop: -8 }}>
+                ˅
             </button>
-                <br></br>
-                <button
-                    className="antiMenu-Buttonup"
-                    key="up"
-                    onPointerDown={action(() => { this.upDownButtons("down", "horizontal"); })}
-                    style={{ position: "absolute", width: 20, height: 10, right: 0, padding: 0, marginTop: -8 }}>
-                    ˅
-            </button></>;
-        return positionHorizontalInput;
+        </>;
     }
 
     @computed get positionVerticalInput() {
-        const positionVerticalInput =
-            <><input
+        return <>
+            <input
                 style={{ color: "black", width: 80, position: "absolute", right: 20 }}
                 type="text" value={this._currPositionVertical}
-                onChange={e => this.onChange(e.target.value, "positionVertical")}
+                onChange={e => this._currPositionVertical = e.target.value}
                 autoFocus></input>
-                <button
-                    className="antiMenu-Buttonup"
-                    key="up"
-                    onPointerDown={action(() => { this.upDownButtons("down", "vertical"); })}
-                    style={{ position: "absolute", width: 20, height: 10, right: 0, padding: 0 }}>
-                    ˄
+            <button
+                className="antiMenu-Buttonup"
+                key="up"
+                onPointerDown={action(() => { this.upDownButtons("down", "vertical"); })}
+                style={{ position: "absolute", width: 20, height: 10, right: 0, padding: 0 }}>
+                ˄
             </button>
-                <br></br>
-                <button
-                    className="antiMenu-Buttonup"
-                    key="up"
-                    onPointerDown={action(() => { this.upDownButtons("up", "vertical"); })}
-                    style={{ position: "absolute", width: 20, height: 10, right: 0, padding: 0, marginTop: -8 }}>
-                    ˅
-            </button></>;
-        return positionVerticalInput;
-    }
-
-    //change inputs
-    @action
-    onChange = (val: string, property: string): void => {
-        if (!Number.isNaN(Number(val)) && Number(val) !== null && val !== " ") {
-
-            switch (property) {
-                case "width":
-                    this._currWidth = val;
-                    if (val !== "") {
-                        this.editProperties(this._currWidth, "width");
-                    }
-                    break;
-                case "sizeHeight":
-                    this._currSizeHeight = val;
-                    if (val !== "") {
-                        this.editProperties(this._currSizeHeight, "heightSize");
-                    }
-                    break;
-                case "sizeWidth":
-                    this._currSizeWidth = val;
-                    if (val !== "") {
-
-                        this.editProperties(this._currSizeWidth, "widthSize");
-                    }
-                    break;
-                case "rotation":
-
-                    this._currRotation = val;
-                    if (val !== "") {
-
-                        this.rotate(Number(val));
-                    }
-                    break;
-                case "positionHorizontal":
-                    this._currPositionHorizontal = val; if (val !== "") {
-
-                        this.editProperties(this._currPositionHorizontal, "horizontal");
-                    }
-
-                    break;
-                case "positionVertical":
-                    this._currPositionVertical = val;
-                    if (val !== "") {
-
-                        this.editProperties(this._currPositionVertical, "vertical");
-                    }
-
-                    break;
-                default:
-                    break;
-            }
-        }
-    }
-
-
-    @computed get widthPicker() {
-        var widthPicker = <button
-            className="antimodeMenu-button"
-            key="width"
-            onPointerDown={action(e => this._widthBtn = !this._widthBtn)}
-            style={{ backgroundColor: this._widthBtn ? "121212" : "" }}>
-            <FontAwesomeIcon icon="bars" size="lg" />
-        </button>;
-        if (this._widthBtn) {
-            widthPicker = <div className="btn2-group" key="width">
-                {widthPicker}
-                {this._width.map(wid => {
-                    return <button
-                        className="antimodeMenu-button"
-                        key={wid}
-                        onPointerDown={action(() => { SetActiveInkWidth(wid); this._widthBtn = false; this.editProperties(wid, "width"); })}
-                        style={{ backgroundColor: this._widthBtn ? "121212" : "" }}>
-                        {wid}
-                    </button>;
-                })}
-            </div>;
-        }
-        return widthPicker;
+            <br></br>
+            <button
+                className="antiMenu-Buttonup"
+                key="up"
+                onPointerDown={action(() => { this.upDownButtons("up", "vertical"); })}
+                style={{ position: "absolute", width: 20, height: 10, right: 0, padding: 0, marginTop: -8 }}>
+                ˅
+            </button>
+        </>;
     }
 
-
-
     render() {
         const buttons = [
 
diff --git a/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx b/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx
index e4f3248d0..0866db2be 100644
--- a/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx
+++ b/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx
@@ -25,19 +25,19 @@ library.add(faBold, faItalic, faChevronLeft, faUnderline, faStrikethrough, faSup
 export default class InkOptionsMenu extends AntimodeMenu {
     static Instance: InkOptionsMenu;
 
-    private _palette = ["#D0021B", "#F5A623", "#F8E71C", "#8B572A", "#7ED321", "#417505", "#9013FE", "#4A90E2", "#50E3C2", "#B8E986", "#000000", "#4A4A4A", "#9B9B9B", "#FFFFFF", "none"];
+    private _palette = ["#D0021B", "#F5A623", "#F8E71C", "#8B572A", "#7ED321", "#417505", "#9013FE", "#4A90E2", "#50E3C2", "#B8E986", "#000000", "#4A4A4A", "#9B9B9B", "#FFFFFF", ""];
     private _width = ["1", "5", "10", "100"];
     // private _buttons = ["circle", "triangle", "rectangle", "arrow", "line"];
     // private _icons = ["O", "∆", "ロ", "➜", "-"];
     // private _buttons = ["circle", "triangle", "rectangle", "line", "noRec", "",];
     // private _icons = ["O", "∆", "ロ", "⎯⎯⎯", "✖︎", " "];
     //arrowStart and arrowEnd must match and defs must exist in Inking Stroke
-    // private _arrowStart = ["arrowHead", "arrowHead", "dot", "dot", "none"];
+    // private _arrowStart = ["arrowStart", "arrowStart", "dot", "dot", "none"];
     // private _arrowEnd = ["none", "arrowEnd", "none", "dot", "none"];
     // private _arrowIcons = ["→", "↔︎", "•", "••", " "];
     private _draw = ["⎯", "→", "↔︎", "∿", "↝", "↭", "ロ", "O", "∆"];
-    private _head = ["none", "none", "arrowHead", "none", "none", "arrowHead", "none", "none", "none"];
-    private _end = ["none", "arrowEnd", "arrowEnd", "none", "arrowEnd", "arrowEnd", "none", "none", "none"];
+    private _head = ["", "", "arrow", "", "", "arrow", "", "", ""];
+    private _end = ["", "arrow", "arrow", "", "arrow", "arrow", "", "", ""];
     private _shape = ["", "", "", "", "", "", "rectangle", "circle", "triangle"];
 
     @observable _shapesNum = this._shape.length;
@@ -122,12 +122,6 @@ export default class InkOptionsMenu extends AntimodeMenu {
                     case "bezier":
                         // doc.strokeBezier === 300 ? doc.strokeBezier = 0 : doc.strokeBezier = 300;
                         break;
-                    case "arrowStart":
-                        doc.arrowStart = String(value);
-                        break;
-                    case "arrowEnd":
-                        doc.arrowEnd = String(value);
-                        break;
                     case "dash":
                         doc.dash = Number(value);
                     default:
@@ -165,13 +159,12 @@ export default class InkOptionsMenu extends AntimodeMenu {
                             SetActiveArrowEnd(this._end[i]);
                             SetActiveBezierApprox("300");
 
-                            //  this.editProperties(this._head[i], "arrowStart"), this.editProperties(this._end[i], "arrowEnd"); 
                             GestureOverlay.Instance.InkShape = this._shape[i];
                         } else {
                             this._selected = this._shapesNum;
                             Doc.SetSelectedTool(InkTool.None);
-                            SetActiveArrowStart("none");
-                            SetActiveArrowEnd("none");
+                            SetActiveArrowStart("");
+                            SetActiveArrowEnd("");
                             GestureOverlay.Instance.InkShape = "";
                             SetActiveBezierApprox("0");
 
@@ -189,13 +182,12 @@ export default class InkOptionsMenu extends AntimodeMenu {
                             SetActiveArrowEnd(this._end[i]);
                             SetActiveBezierApprox("300");
 
-                            //  this.editProperties(this._head[i], "arrowStart"), this.editProperties(this._end[i], "arrowEnd"); 
                             GestureOverlay.Instance.InkShape = this._shape[i];
                         } else {
                             this._selected = this._shapesNum;
                             Doc.SetSelectedTool(InkTool.None);
-                            SetActiveArrowStart("none");
-                            SetActiveArrowEnd("none");
+                            SetActiveArrowStart("");
+                            SetActiveArrowEnd("");
                             GestureOverlay.Instance.InkShape = "";
                             SetActiveBezierApprox("0");
 
diff --git a/src/client/views/nodes/ColorBox.tsx b/src/client/views/nodes/ColorBox.tsx
index 137b387c0..31c5a8b13 100644
--- a/src/client/views/nodes/ColorBox.tsx
+++ b/src/client/views/nodes/ColorBox.tsx
@@ -14,7 +14,6 @@ import { ViewBoxBaseComponent } from "../DocComponent";
 import { ActiveInkPen, ActiveInkWidth, ActiveInkBezierApprox, SetActiveInkColor, SetActiveInkWidth, SetActiveBezierApprox } from "../InkingStroke";
 import "./ColorBox.scss";
 import { FieldView, FieldViewProps } from './FieldView';
-import { FormattedTextBox } from "./formattedText/FormattedTextBox";
 
 type ColorDocument = makeInterface<[typeof documentSchema]>;
 const ColorDocument = makeInterface(documentSchema);
-- 
cgit v1.2.3-70-g09d2


From c77f890a3ddd817738564a84046e65f0916d8a46 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Sun, 12 Jul 2020 12:02:19 -0500
Subject: more tooltips

---
 src/client/views/DocumentButtonBar.tsx             | 87 +++++++++++-----------
 src/client/views/DocumentDecorations.tsx           | 41 +++++-----
 .../views/collections/CollectionLinearView.tsx     | 23 +++---
 src/client/views/nodes/DocumentLinksButton.tsx     |  4 +-
 4 files changed, 85 insertions(+), 70 deletions(-)

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

diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index 1667b2f65..072648ef0 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -23,6 +23,7 @@ import { TemplateMenu } from "./TemplateMenu";
 import { Template, Templates } from "./Templates";
 import React = require("react");
 import { DocumentLinksButton } from './nodes/DocumentLinksButton';
+import { Tooltip } from '@material-ui/core';
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -118,18 +119,18 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
         const targetDoc = this.view0?.props.Document;
         const published = targetDoc && Doc.GetProto(targetDoc)[GoogleRef] !== undefined;
         const animation = this.isAnimatingPulse ? "shadow-pulse 1s linear infinite" : "none";
-        return !targetDoc ? (null) : <div
-            title={`${published ? "Push" : "Publish"} to Google Docs`}
-            className="documentButtonBar-linker"
-            style={{ animation }}
-            onClick={async () => {
-                await GoogleAuthenticationManager.Instance.fetchOrGenerateAccessToken();
-                !published && runInAction(() => this.isAnimatingPulse = true);
-                DocumentButtonBar.hasPushedHack = false;
-                targetDoc[Pushes] = NumCast(targetDoc[Pushes]) + 1;
-            }}>
-            <FontAwesomeIcon className="documentdecorations-icon" icon={published ? (this.pushIcon as any) : cloud} size={published ? "sm" : "xs"} />
-        </div>;
+        return !targetDoc ? (null) : <Tooltip title={`${published ? "Push" : "Publish"} to Google Docs`}>
+            <div
+                className="documentButtonBar-linker"
+                style={{ animation }}
+                onClick={async () => {
+                    await GoogleAuthenticationManager.Instance.fetchOrGenerateAccessToken();
+                    !published && runInAction(() => this.isAnimatingPulse = true);
+                    DocumentButtonBar.hasPushedHack = false;
+                    targetDoc[Pushes] = NumCast(targetDoc[Pushes]) + 1;
+                }}>
+                <FontAwesomeIcon className="documentdecorations-icon" icon={published ? (this.pushIcon as any) : cloud} size={published ? "sm" : "xs"} />
+            </div></Tooltip>;
     }
 
     @computed
@@ -137,7 +138,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
         const targetDoc = this.view0?.props.Document;
         const dataDoc = targetDoc && Doc.GetProto(targetDoc);
         const animation = this.isAnimatingFetch ? "spin 0.5s linear infinite" : "none";
-        return !targetDoc || !dataDoc || !dataDoc[GoogleRef] ? (null) : <div className="documentButtonBar-linker"
+        return !targetDoc || !dataDoc || !dataDoc[GoogleRef] ? (null) : <Tooltip
             title={(() => {
                 switch (this.openHover) {
                     default:
@@ -146,6 +147,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
                     case UtilityButtonState.OpenExternally: return "Open in new Browser Tab";
                 }
             })()}
+        ><div className="documentButtonBar-linker"
             style={{ backgroundColor: this.pullColor }}
             onPointerEnter={action(e => {
                 if (e.altKey) {
@@ -176,43 +178,43 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
                     dataDoc.unchanged && runInAction(() => this.isAnimatingFetch = true);
                 }
             }}>
-            <FontAwesomeIcon className="documentdecorations-icon" size="sm"
-                style={{ WebkitAnimation: animation, MozAnimation: animation }}
-                icon={(() => {
-                    switch (this.openHover) {
-                        default:
-                        case UtilityButtonState.Default: return dataDoc.unchanged === false ? (this.pullIcon as any) : fetch;
-                        case UtilityButtonState.OpenRight: return "arrow-alt-circle-right";
-                        case UtilityButtonState.OpenExternally: return "share";
-                    }
-                })()}
-            />
-        </div>;
+                <FontAwesomeIcon className="documentdecorations-icon" size="sm"
+                    style={{ WebkitAnimation: animation, MozAnimation: animation }}
+                    icon={(() => {
+                        switch (this.openHover) {
+                            default:
+                            case UtilityButtonState.Default: return dataDoc.unchanged === false ? (this.pullIcon as any) : fetch;
+                            case UtilityButtonState.OpenRight: return "arrow-alt-circle-right";
+                            case UtilityButtonState.OpenExternally: return "share";
+                        }
+                    })()}
+                />
+            </div></Tooltip>;
     }
     @computed
     get pinButton() {
         const targetDoc = this.view0?.props.Document;
         const isPinned = targetDoc && Doc.isDocPinned(targetDoc);
-        return !targetDoc ? (null) : <div className="documentButtonBar-linker"
-            title={Doc.isDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}
-            style={{ backgroundColor: isPinned ? "black" : "white", color: isPinned ? "white" : "black" }}
-            onClick={e => DockedFrameRenderer.PinDoc(targetDoc, isPinned)}>
-            <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="map-pin"
-            />
-        </div>;
+        return !targetDoc ? (null) : <Tooltip title={Doc.isDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}>
+            <div className="documentButtonBar-linker"
+                style={{ backgroundColor: isPinned ? "black" : "white", color: isPinned ? "white" : "black" }}
+                onClick={e => DockedFrameRenderer.PinDoc(targetDoc, isPinned)}>
+                <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="map-pin"
+                />
+            </div></Tooltip>;
     }
 
     @computed
     get metadataButton() {
         const view0 = this.view0;
-        return !view0 ? (null) : <div title="Show metadata panel" className="documentButtonBar-linkFlyout">
+        return !view0 ? (null) : <Tooltip title="Show metadata panel"><div className="documentButtonBar-linkFlyout">
             <Flyout anchorPoint={anchorPoints.LEFT_TOP}
                 content={<MetadataEntryMenu docs={() => this.props.views().filter(dv => dv).map(dv => dv!.props.Document)} suggestWithFunction />  /* tfs: @bcz This might need to be the data document? */}>
                 <div className={"documentButtonBar-linkButton-" + "empty"} onPointerDown={e => e.stopPropagation()} >
                     {<FontAwesomeIcon className="documentdecorations-icon" icon="tag" size="sm" />}
                 </div>
             </Flyout>
-        </div>;
+        </div></Tooltip>;
     }
 
     @computed
@@ -253,14 +255,15 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
         Array.from(Object.values(Templates.TemplateList)).map(template =>
             templates.set(template, views.reduce((checked, doc) => checked || doc?.props.Document["_show" + template.Name] ? true : false, false as boolean)));
         return !view0 ? (null) :
-            <div title="Tap: Customize layout.  Drag: Create alias" className="documentButtonBar-linkFlyout" ref={this._dragRef}>
-                <Flyout anchorPoint={anchorPoints.LEFT_TOP} onOpen={action(() => this._aliasDown = true)} onClose={action(() => this._aliasDown = false)}
-                    content={!this._aliasDown ? (null) : <TemplateMenu docViews={views.filter(v => v).map(v => v as DocumentView)} templates={templates} />}>
-                    <div className={"documentButtonBar-linkButton-empty"} ref={this._dragRef} onPointerDown={this.onAliasButtonDown} >
-                        {<FontAwesomeIcon className="documentdecorations-icon" icon="edit" size="sm" />}
-                    </div>
-                </Flyout>
-            </div>;
+            <Tooltip title="Tap: Customize layout.  Drag: Create alias" >
+                <div className="documentButtonBar-linkFlyout" ref={this._dragRef}>
+                    <Flyout anchorPoint={anchorPoints.LEFT_TOP} onOpen={action(() => this._aliasDown = true)} onClose={action(() => this._aliasDown = false)}
+                        content={!this._aliasDown ? (null) : <TemplateMenu docViews={views.filter(v => v).map(v => v as DocumentView)} templates={templates} />}>
+                        <div className={"documentButtonBar-linkButton-empty"} ref={this._dragRef} onPointerDown={this.onAliasButtonDown} >
+                            {<FontAwesomeIcon className="documentdecorations-icon" icon="edit" size="sm" />}
+                        </div>
+                    </Flyout>
+                </div></Tooltip>;
     }
 
     render() {
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 0bf4814e7..d7324e1a6 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -25,6 +25,7 @@ import { HtmlField } from '../../fields/HtmlField';
 import { InkData, InkField, InkTool } from "../../fields/InkField";
 import { update } from 'serializr';
 import { Transform } from "../util/Transform";
+import { Tooltip } from '@material-ui/core';
 
 library.add(faCaretUp);
 library.add(faObjectGroup);
@@ -546,13 +547,15 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         }
         const minimal = bounds.r - bounds.x < 100 ? true : false;
         const maximizeIcon = minimal ? (
-            <div className="documentDecorations-contextMenu" title="Show context menu" onPointerDown={this.onSettingsDown}>
-                <FontAwesomeIcon size="lg" icon="cog" />
-            </div>) : (
-                <div className="documentDecorations-minimizeButton" title="Iconify" onClick={this.onCloseClick}>
-                    {/* Currently, this is set to be enabled if there is no ink selected. It might be interesting to think about minimizing ink if it's useful? -syip2*/}
-                    <FontAwesomeIcon className="documentdecorations-times" icon={faTimes} size="lg" />
-                </div>);
+            <Tooltip title="Show context menu" placement="top">
+                <div className="documentDecorations-contextMenu" onPointerDown={this.onSettingsDown}>
+                    <FontAwesomeIcon size="lg" icon="cog" />
+                </div></Tooltip>) : (
+                <Tooltip title="Iconify" placement="top">
+                    <div className="documentDecorations-minimizeButton" onClick={this.onCloseClick}>
+                        {/* Currently, this is set to be enabled if there is no ink selected. It might be interesting to think about minimizing ink if it's useful? -syip2*/}
+                        <FontAwesomeIcon className="documentdecorations-times" icon={faTimes} size="lg" />
+                    </div></Tooltip>);
 
         const titleArea = this._edtingTitle ?
             <>
@@ -572,9 +575,9 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 </div>}
             </> :
             <>
-                {minimal ? (null) : <div className="documentDecorations-contextMenu" key="menu" title="Show context menu" onPointerDown={this.onSettingsDown}>
+                {minimal ? (null) : <Tooltip title="Show context menu" placement="top"><div className="documentDecorations-contextMenu" key="menu" onPointerDown={this.onSettingsDown}>
                     <FontAwesomeIcon size="lg" icon="cog" />
-                </div>}
+                </div></Tooltip>}
                 <div className="documentDecorations-title" key="title" onPointerDown={this.onTitleDown} >
                     <span style={{ width: "100%", display: "inline-block" }}>{`${this.selectionTitle}`}</span>
                 </div>
@@ -611,12 +614,13 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                     {maximizeIcon}
                     {titleArea}
                     {SelectionManager.SelectedDocuments().length !== 1 || seldoc.Document.type === DocumentType.INK ? (null) :
-                        <div className="documentDecorations-iconifyButton" title={`${seldoc.finalLayoutKey.includes("icon") ? "De" : ""}Iconify Document`} onPointerDown={this.onIconifyDown}>
-                            {"_"}
-                        </div>}
-                    <div className="documentDecorations-closeButton" title="Open Document in Tab" onPointerDown={this.onMaximizeDown}>
+                        <Tooltip title={`${seldoc.finalLayoutKey.includes("icon") ? "De" : ""}Iconify Document`} placement="top">
+                            <div className="documentDecorations-iconifyButton" onPointerDown={this.onIconifyDown}>
+                                {"_"}
+                            </div></Tooltip>}
+                    <Tooltip title="Open Document in Tab" placement="top"><div className="documentDecorations-closeButton" onPointerDown={this.onMaximizeDown}>
                         {SelectionManager.SelectedDocuments().length === 1 ? DocumentDecorations.DocumentIcon(StrCast(seldoc.props.Document.layout, "...")) : "..."}
-                    </div>
+                    </div></Tooltip>
                     <div id="documentDecorations-rotation" className="documentDecorations-rotation"
                         onPointerDown={this.onRotateDown}> ⟲ </div>
                     <div id="documentDecorations-topLeftResizer" className="documentDecorations-resizer"
@@ -637,10 +641,11 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                     <div id="documentDecorations-bottomRightResizer" className="documentDecorations-resizer"
                         onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                     {seldoc.props.renderDepth <= 1 || !seldoc.props.ContainingCollectionView ? (null) :
-                        <div id="documentDecorations-levelSelector" className="documentDecorations-selector"
-                            title="tap to select containing document" onPointerDown={this.onSelectorUp} onContextMenu={e => e.preventDefault()}>
-                            <FontAwesomeIcon className="documentdecorations-times" icon={faArrowAltCircleUp} size="lg" />
-                        </div>}
+                        <Tooltip title="tap to select containing document" placement="top">
+                            <div id="documentDecorations-levelSelector" className="documentDecorations-selector"
+                                onPointerDown={this.onSelectorUp} onContextMenu={e => e.preventDefault()}>
+                                <FontAwesomeIcon className="documentdecorations-times" icon={faArrowAltCircleUp} size="lg" />
+                            </div></Tooltip>}
                     <div id="documentDecorations-borderRadius" className="documentDecorations-radius"
                         onPointerDown={this.onRadiusDown} onContextMenu={(e) => e.preventDefault()}></div>
 
diff --git a/src/client/views/collections/CollectionLinearView.tsx b/src/client/views/collections/CollectionLinearView.tsx
index 2dd48aa27..4c68cc949 100644
--- a/src/client/views/collections/CollectionLinearView.tsx
+++ b/src/client/views/collections/CollectionLinearView.tsx
@@ -111,17 +111,22 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
         const flexDir: any = StrCast(this.Document.flexDirection);
         const backgroundColor = StrCast(this.props.Document.backgroundColor, "black");
         const color = StrCast(this.props.Document.color, "white");
+
+        const menuOpener = <label htmlFor={`${guid}`} style={{
+            background: backgroundColor === color ? "black" : backgroundColor,
+            // width: "18px", height: "18px", fontSize: "12.5px",
+            // transition: this.props.Document.linearViewIsExpanded ? "transform 0.2s" : "transform 0.5s",
+            // transform: this.props.Document.linearViewIsExpanded ? "" : "rotate(45deg)"
+        }}
+            onPointerDown={e => e.stopPropagation()} >
+            <p>+</p>
+        </label>;
+
         return <div className="collectionLinearView-outer">
             <div className="collectionLinearView" ref={this.createDashEventsTarget} >
-                <label htmlFor={`${guid}`} title="Close Menu" style={{
-                    background: backgroundColor === color ? "black" : backgroundColor,
-                    // width: "18px", height: "18px", fontSize: "12.5px",
-                    // transition: this.props.Document.linearViewIsExpanded ? "transform 0.2s" : "transform 0.5s",
-                    // transform: this.props.Document.linearViewIsExpanded ? "" : "rotate(45deg)"
-                }}
-                    onPointerDown={e => e.stopPropagation()} >
-                    <p>+</p>
-                </label>
+                <Tooltip title={BoolCast(this.props.Document.linearViewIsExpanded) ? "Close menu" : "Open menu"} placement="top">
+                    {menuOpener}
+                </Tooltip>
                 <input id={`${guid}`} type="checkbox" checked={BoolCast(this.props.Document.linearViewIsExpanded)} ref={this.addMenuToggle}
                     onChange={action((e: any) => this.props.Document.linearViewIsExpanded = this.addMenuToggle.current!.checked)} />
 
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 03a96ea4a..1c15b31de 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -64,6 +64,8 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
                 //action(() => Doc.BrushDoc(this.props.View.Document));
                 DocumentLinksButton.StartLink = this.props.View;
             } else if (!!!this.props.InMenu) {
+                console.log("editing");
+                this.props.View ? console.log("view") : null;
                 DocumentLinksButton.EditLink = this.props.View;
                 DocumentLinksButton.EditLinkLoc = [e.clientX + 10, e.clientY];
             }
@@ -159,7 +161,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
     get linkButton() {
         const links = DocListCast(this.props.View.props.Document.links);
 
-        const title = this.props.InMenu ? "Drag or tap to create links" : "Tap to view links";
+        const title = this.props.InMenu ? "Drag or tap to create links" : DocumentLinksButton.StartLink ? "Tap to finish link" : "Tap to view links";
 
         const linkButton = <div ref={this._linkButton} style={{ minWidth: 20, minHeight: 20, position: "absolute", left: this.props.Offset?.[0] }}>
             <div className={"documentLinksButton"} style={{
-- 
cgit v1.2.3-70-g09d2


From 0dafe85b7d0c826340299a7e6b51190a6eaa7004 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Mon, 13 Jul 2020 17:56:46 -0500
Subject: fixed preview backgrounds, text size, tooltip size, adding labels,
 conditional end link btn, tooltips size

---
 src/client/views/DocumentButtonBar.tsx             | 106 +++++++++++----------
 src/client/views/DocumentDecorations.tsx           |  12 +--
 src/client/views/MainView.tsx                      |   4 +-
 .../views/collections/CollectionLinearView.tsx     |   9 +-
 src/client/views/linking/LinkEditor.scss           |  24 ++++-
 src/client/views/linking/LinkEditor.tsx            |  27 ++++--
 src/client/views/linking/LinkMenuItem.scss         |   1 +
 src/client/views/linking/LinkMenuItem.tsx          |   6 +-
 src/client/views/nodes/DocumentLinksButton.scss    |  12 +--
 src/client/views/nodes/DocumentLinksButton.tsx     |  24 ++---
 src/client/views/nodes/LinkDocPreview.tsx          |   3 +-
 .../formattedText/FormattedTextBoxComment.tsx      |   4 +-
 12 files changed, 135 insertions(+), 97 deletions(-)

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

diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index a3d24b3b6..c132eb5bb 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -119,7 +119,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
         const targetDoc = this.view0?.props.Document;
         const published = targetDoc && Doc.GetProto(targetDoc)[GoogleRef] !== undefined;
         const animation = this.isAnimatingPulse ? "shadow-pulse 1s linear infinite" : "none";
-        return !targetDoc ? (null) : <Tooltip title={`${published ? "Push" : "Publish"} to Google Docs`}>
+        return !targetDoc ? (null) : <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{`${published ? "Push" : "Publish"} to Google Docs`}</div></React.Fragment>}>
             <div
                 className="documentButtonBar-linker"
                 style={{ animation }}
@@ -138,46 +138,49 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
         const targetDoc = this.view0?.props.Document;
         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?.unchanged ? "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={(() => {
-                switch (this.openHover) {
-                    default:
-                    case UtilityButtonState.Default: return `${!dataDoc.unchanged ? "Pull from" : "Fetch"} Google Docs`;
-                    case UtilityButtonState.OpenRight: return "Open in Right Split";
-                    case UtilityButtonState.OpenExternally: return "Open in new Browser Tab";
-                }
-            })()}
-        ><div className="documentButtonBar-linker"
-            style={{ backgroundColor: this.pullColor }}
-            onPointerEnter={action(e => {
-                if (e.altKey) {
-                    this.openHover = UtilityButtonState.OpenExternally;
-                } else if (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, isAnnotating: false, UseCors: false };
-                        googleDoc = Docs.Create.WebDocument(googleDocUrl, options);
-                        dataDoc.googleDoc = googleDoc;
+            title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{title}</div></React.Fragment>}>
+            <div className="documentButtonBar-linker"
+                style={{ backgroundColor: this.pullColor }}
+                onPointerEnter={action(e => {
+                    if (e.altKey) {
+                        this.openHover = UtilityButtonState.OpenExternally;
+                    } else if (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, isAnnotating: false, UseCors: false };
+                            googleDoc = Docs.Create.WebDocument(googleDocUrl, options);
+                            dataDoc.googleDoc = googleDoc;
+                        }
+                        CollectionDockingView.AddRightSplit(googleDoc);
+                    } else if (e.altKey) {
+                        e.preventDefault();
+                        window.open(googleDocUrl);
+                    } else {
+                        this.clearPullColor();
+                        DocumentButtonBar.hasPulledHack = false;
+                        targetDoc[Pulls] = NumCast(targetDoc[Pulls]) + 1;
+                        dataDoc.unchanged && runInAction(() => this.isAnimatingFetch = true);
                     }
-                    CollectionDockingView.AddRightSplit(googleDoc);
-                } else if (e.altKey) {
-                    e.preventDefault();
-                    window.open(googleDocUrl);
-                } else {
-                    this.clearPullColor();
-                    DocumentButtonBar.hasPulledHack = false;
-                    targetDoc[Pulls] = NumCast(targetDoc[Pulls]) + 1;
-                    dataDoc.unchanged && runInAction(() => this.isAnimatingFetch = true);
-                }
-            }}>
+                }}>
                 <FontAwesomeIcon className="documentdecorations-icon" size="sm"
                     style={{ WebkitAnimation: animation, MozAnimation: animation }}
                     icon={(() => {
@@ -195,7 +198,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
     get pinButton() {
         const targetDoc = this.view0?.props.Document;
         const isPinned = targetDoc && Doc.isDocPinned(targetDoc);
-        return !targetDoc ? (null) : <Tooltip title={Doc.isDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}>
+        return !targetDoc ? (null) : <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{Doc.isDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}</div></React.Fragment>}>
             <div className="documentButtonBar-linker"
                 style={{ backgroundColor: isPinned ? "black" : "white", color: isPinned ? "white" : "black" }}
                 onClick={e => DockedFrameRenderer.PinDoc(targetDoc, isPinned)}>
@@ -207,14 +210,15 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
     @computed
     get metadataButton() {
         const view0 = this.view0;
-        return !view0 ? (null) : <Tooltip title="Show metadata panel"><div className="documentButtonBar-linkFlyout">
-            <Flyout anchorPoint={anchorPoints.LEFT_TOP}
-                content={<MetadataEntryMenu docs={() => this.props.views().filter(dv => dv).map(dv => dv!.props.Document)} suggestWithFunction />  /* tfs: @bcz This might need to be the data document? */}>
-                <div className={"documentButtonBar-linkButton-" + "empty"} onPointerDown={e => e.stopPropagation()} >
-                    {<FontAwesomeIcon className="documentdecorations-icon" icon="tag" size="sm" />}
-                </div>
-            </Flyout>
-        </div></Tooltip>;
+        return !view0 ? (null) : <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Show metadata panel</div></React.Fragment>}>
+            <div className="documentButtonBar-linkFlyout">
+                <Flyout anchorPoint={anchorPoints.LEFT_TOP}
+                    content={<MetadataEntryMenu docs={() => this.props.views().filter(dv => dv).map(dv => dv!.props.Document)} suggestWithFunction />  /* tfs: @bcz This might need to be the data document? */}>
+                    <div className={"documentButtonBar-linkButton-" + "empty"} onPointerDown={e => e.stopPropagation()} >
+                        {<FontAwesomeIcon className="documentdecorations-icon" icon="tag" size="sm" />}
+                    </div>
+                </Flyout>
+            </div></Tooltip>;
     }
 
     @computed
@@ -255,7 +259,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
         Array.from(Object.values(Templates.TemplateList)).map(template =>
             templates.set(template, views.reduce((checked, doc) => checked || doc?.props.Document["_show" + template.Name] ? true : false, false as boolean)));
         return !view0 ? (null) :
-            <Tooltip title="Tap: Customize layout.  Drag: Create alias" >
+            <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Tap: Customize layout.  Drag: Create alias</div></React.Fragment>}>
                 <div className="documentButtonBar-linkFlyout" ref={this._dragRef}>
                     <Flyout anchorPoint={anchorPoints.LEFT_TOP} onOpen={action(() => this._aliasDown = true)} onClose={action(() => this._aliasDown = false)}
                         content={!this._aliasDown ? (null) : <TemplateMenu docViews={views.filter(v => v).map(v => v as DocumentView)} templates={templates} />}>
@@ -276,9 +280,9 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
             <div className="documentButtonBar-button">
                 <DocumentLinksButton View={this.view0} AlwaysOn={true} InMenu={true} StartLink={true} />
             </div>
-            <div className="documentButtonBar-button">
+            {DocumentLinksButton.StartLink ? <div className="documentButtonBar-button">
                 <DocumentLinksButton View={this.view0} AlwaysOn={true} InMenu={true} StartLink={false} />
-            </div>
+            </div> : null}
             <div className="documentButtonBar-button">
                 {this.templateButton}
             </div>
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index d7324e1a6..2e3c63cf2 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -547,11 +547,11 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         }
         const minimal = bounds.r - bounds.x < 100 ? true : false;
         const maximizeIcon = minimal ? (
-            <Tooltip title="Show context menu" placement="top">
+            <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Show context menu</div></React.Fragment>} placement="top">
                 <div className="documentDecorations-contextMenu" onPointerDown={this.onSettingsDown}>
                     <FontAwesomeIcon size="lg" icon="cog" />
                 </div></Tooltip>) : (
-                <Tooltip title="Iconify" placement="top">
+                <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Iconify</div></React.Fragment>} placement="top">
                     <div className="documentDecorations-minimizeButton" onClick={this.onCloseClick}>
                         {/* Currently, this is set to be enabled if there is no ink selected. It might be interesting to think about minimizing ink if it's useful? -syip2*/}
                         <FontAwesomeIcon className="documentdecorations-times" icon={faTimes} size="lg" />
@@ -575,7 +575,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 </div>}
             </> :
             <>
-                {minimal ? (null) : <Tooltip title="Show context menu" placement="top"><div className="documentDecorations-contextMenu" key="menu" onPointerDown={this.onSettingsDown}>
+                {minimal ? (null) : <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Show context menu</div></React.Fragment>} placement="top"><div className="documentDecorations-contextMenu" key="menu" onPointerDown={this.onSettingsDown}>
                     <FontAwesomeIcon size="lg" icon="cog" />
                 </div></Tooltip>}
                 <div className="documentDecorations-title" key="title" onPointerDown={this.onTitleDown} >
@@ -614,11 +614,11 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                     {maximizeIcon}
                     {titleArea}
                     {SelectionManager.SelectedDocuments().length !== 1 || seldoc.Document.type === DocumentType.INK ? (null) :
-                        <Tooltip title={`${seldoc.finalLayoutKey.includes("icon") ? "De" : ""}Iconify Document`} placement="top">
+                        <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{`${seldoc.finalLayoutKey.includes("icon") ? "De" : ""}Iconify Document`}</div></React.Fragment>} placement="top">
                             <div className="documentDecorations-iconifyButton" onPointerDown={this.onIconifyDown}>
                                 {"_"}
                             </div></Tooltip>}
-                    <Tooltip title="Open Document in Tab" placement="top"><div className="documentDecorations-closeButton" onPointerDown={this.onMaximizeDown}>
+                    <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Open Document In Tab</div></React.Fragment>} placement="top"><div className="documentDecorations-closeButton" onPointerDown={this.onMaximizeDown}>
                         {SelectionManager.SelectedDocuments().length === 1 ? DocumentDecorations.DocumentIcon(StrCast(seldoc.props.Document.layout, "...")) : "..."}
                     </div></Tooltip>
                     <div id="documentDecorations-rotation" className="documentDecorations-rotation"
@@ -641,7 +641,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                     <div id="documentDecorations-bottomRightResizer" className="documentDecorations-resizer"
                         onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                     {seldoc.props.renderDepth <= 1 || !seldoc.props.ContainingCollectionView ? (null) :
-                        <Tooltip title="tap to select containing document" placement="top">
+                        <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>tap to select containing document</div></React.Fragment>} placement="top">
                             <div id="documentDecorations-levelSelector" className="documentDecorations-selector"
                                 onPointerDown={this.onSelectorUp} onContextMenu={e => e.preventDefault()}>
                                 <FontAwesomeIcon className="documentdecorations-times" icon={faArrowAltCircleUp} size="lg" />
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 2ed528836..a54973489 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -6,7 +6,7 @@ import {
     faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter,
     faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, faTimesCircle,
     faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faArrowsAlt, faQuoteLeft, faSortAmountDown, faAlignLeft, faAlignCenter, faAlignRight,
-    faHeading, faRulerCombined, faFillDrip, faUnlink
+    faHeading, faRulerCombined, faFillDrip, faUnlink, faHandPaper
 } from '@fortawesome/free-solid-svg-icons';
 import { ANTIMODEMENU_HEIGHT } from './globalCssVariables.scss';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
@@ -147,7 +147,7 @@ export class MainView extends React.Component {
             faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter,
             faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, faTrashAlt, faAngleRight, faBell,
             faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faArrowsAlt, faQuoteLeft, faSortAmountDown, faAlignLeft, faAlignCenter, faAlignRight,
-            faHeading, faRulerCombined, faFillDrip, faUnlink);
+            faHeading, faRulerCombined, faFillDrip, faUnlink, faHandPaper);
         this.initEventListeners();
         this.initAuthenticationRouters();
     }
diff --git a/src/client/views/collections/CollectionLinearView.tsx b/src/client/views/collections/CollectionLinearView.tsx
index dd4df20c9..319cca70f 100644
--- a/src/client/views/collections/CollectionLinearView.tsx
+++ b/src/client/views/collections/CollectionLinearView.tsx
@@ -124,7 +124,7 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
 
         return <div className="collectionLinearView-outer">
             <div className="collectionLinearView" ref={this.createDashEventsTarget} >
-                <Tooltip title={BoolCast(this.props.Document.linearViewIsExpanded) ? "Close menu" : "Open menu"} placement="top">
+                <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{BoolCast(this.props.Document.linearViewIsExpanded) ? "Close menu" : "Open menu"}</div></React.Fragment>} placement="top">
                     {menuOpener}
                 </Tooltip>
                 <input id={`${guid}`} type="checkbox" checked={BoolCast(this.props.Document.linearViewIsExpanded)} ref={this.addMenuToggle}
@@ -177,14 +177,15 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
                     onPointerDown={e => e.stopPropagation()} >
                     <span className="bottomPopup-text" >
                         Creating link from: {DocumentLinksButton.StartLink.title} </span>
-                    <Tooltip title={LinkDescriptionPopup.showDescriptions ? "Turn off description pop-up" :
-                        "Turn on description pop-up"} placement="top">
+
+                    <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{LinkDescriptionPopup.showDescriptions ? "Turn off description pop-up" :
+                        "Turn on description pop-up"} </div></React.Fragment>} placement="top">
                         <span className="bottomPopup-descriptions" onClick={this.changeDescriptionSetting}
                         > Labels: {LinkDescriptionPopup.showDescriptions ? LinkDescriptionPopup.showDescriptions : "ON"}
                         </span>
                     </Tooltip>
 
-                    <Tooltip title="Exit link clicking mode" placement="top">
+                    <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Exit link clicking mode </div></React.Fragment>} placement="top">
                         <span className="bottomPopup-exit" onClick={this.exitLongLinks}
                         >Clear</span>
                     </Tooltip>
diff --git a/src/client/views/linking/LinkEditor.scss b/src/client/views/linking/LinkEditor.scss
index 87afc99eb..d26b7920a 100644
--- a/src/client/views/linking/LinkEditor.scss
+++ b/src/client/views/linking/LinkEditor.scss
@@ -13,6 +13,10 @@
     width: 18px;
     height: 18px;
     padding: 0;
+
+    &:hover {
+        cursor: pointer;
+    }
 }
 
 .linkEditor-info {
@@ -28,7 +32,13 @@
     .linkEditor-linkedTo {
         width: calc(100% - 26px);
         padding-left: 5px;
-        padding-right: 5px
+        padding-right: 5px;
+
+        .linkEditor-downArrow {
+            &:hover {
+                cursor: pointer;
+            }
+        }
     }
 }
 
@@ -43,6 +53,10 @@
 
     .button {
         color: black;
+
+        &:hover {
+            cursor: pointer;
+        }
     }
 }
 
@@ -83,6 +97,10 @@
             padding-right: 8px;
             height: 80%;
             color: white;
+
+            &:hover {
+                cursor: pointer;
+            }
         }
     }
 }
@@ -92,6 +110,10 @@
     padding-right: 6.5px;
     padding-bottom: 6px;
 
+    &:hover {
+        cursor: pointer;
+    }
+
     .linkEditor-followingDropdown-label {
         color: black;
     }
diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx
index a26685318..1cc981d42 100644
--- a/src/client/views/linking/LinkEditor.tsx
+++ b/src/client/views/linking/LinkEditor.tsx
@@ -13,6 +13,7 @@ import { DocumentView } from "../nodes/DocumentView";
 import { DocumentLinksButton } from "../nodes/DocumentLinksButton";
 import { EditableView } from "../EditableView";
 import { RefObject } from "react";
+import { Tooltip } from "@material-ui/core";
 
 library.add(faArrowLeft, faEllipsisV, faTable, faTrash, faCog, faExchangeAlt, faTimes, faPlus);
 
@@ -285,15 +286,12 @@ interface LinkEditorProps {
 @observer
 export class LinkEditor extends React.Component<LinkEditorProps> {
 
-
     @observable description = StrCast(LinkManager.currentLink?.description);
     @observable openDropdown: boolean = false;
-
     @observable followBehavior = this.props.linkDoc.follow ? this.props.linkDoc.follow : "Default";
-
     @observable showInfo: boolean = false;
-
     @computed get infoIcon() { if (this.showInfo) { return "chevron-up"; } return "chevron-down"; }
+    @observable private buttonColor: string = "black";
 
 
     //@observable description = this.props.linkDoc.description ? StrCast(this.props.linkDoc.description) : "DESCRIPTION";
@@ -308,6 +306,10 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
     setDescripValue = (value: string) => {
         if (LinkManager.currentLink) {
             LinkManager.currentLink.description = value;
+            this.buttonColor = "rgb(62, 133, 55)";
+            setTimeout(action(() => {
+                this.buttonColor = "black";
+            }), 750);
             return true;
         }
     }
@@ -349,7 +351,8 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
                     ></input>
                 </div>
                 <div className="linkEditor-description-add-button"
-                    onPointerDown={this.onDown}>Add</div>
+                    style={{ backgroundColor: this.buttonColor }}
+                    onPointerDown={this.onDown}>Set</div>
             </div></div>;
     }
 
@@ -413,15 +416,19 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
         return !destination ? (null) : (
             <div className="linkEditor">
                 <div className="linkEditor-info">
-                    <button className="linkEditor-button-back"
-                        style={{ display: this.props.hideback ? "none" : "" }}
-                        onClick={this.props.showLinks}>
-                        <FontAwesomeIcon icon="arrow-left" size="sm" /> </button>
+                    <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Return to link menu</div></React.Fragment>} placement="top">
+                        <button className="linkEditor-button-back"
+                            style={{ display: this.props.hideback ? "none" : "" }}
+                            onClick={this.props.showLinks}>
+                            <FontAwesomeIcon icon="arrow-left" size="sm" /> </button>
+                    </Tooltip>
                     <p className="linkEditor-linkedTo">Editing Link to: <b>{
                         destination.proto?.title ?? destination.title ?? "untitled"}</b></p>
                     {/* <button className="linkEditor-button" onPointerDown={() => this.deleteLink()} title="Delete link">
                         <FontAwesomeIcon icon="trash" size="sm" /></button> */}
-                    <FontAwesomeIcon className="button" icon={this.infoIcon} size="lg" onPointerDown={this.changeInfo} />
+                    <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Show more link information</div></React.Fragment>} placement="top">
+                        <div className="linkEditor-downArrow"><FontAwesomeIcon className="button" icon={this.infoIcon} size="lg" onPointerDown={this.changeInfo} /></div>
+                    </Tooltip>
                 </div>
                 {this.showInfo ? <div className="linkEditor-moreInfo">
                     <div>{this.props.linkDoc.author ? <div> <b>Author:</b> {this.props.linkDoc.author}</div> : null}</div>
diff --git a/src/client/views/linking/LinkMenuItem.scss b/src/client/views/linking/LinkMenuItem.scss
index f70f5a23e..4e13ef8c8 100644
--- a/src/client/views/linking/LinkMenuItem.scss
+++ b/src/client/views/linking/LinkMenuItem.scss
@@ -67,6 +67,7 @@
                         color: rgb(60, 90, 156);
                         //display: inline;
                         text-overflow: break;
+                        cursor: pointer;
                     }
                 }
             }
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index b451f0168..ff9401696 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -253,16 +253,16 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
                             {canExpand ? <div title="Show more" className="button" onPointerDown={e => this.toggleShowMore(e)}>
                                 <FontAwesomeIcon className="fa-icon" icon={this._showMore ? "chevron-up" : "chevron-down"} size="sm" /></div> : <></>}
 
-                            <Tooltip title={showTitle}>
+                            <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{showTitle}</div></React.Fragment>}>
                                 <div className="button" ref={this._editRef} onPointerDown={this.showLink}>
                                     <FontAwesomeIcon className="fa-icon" icon={eyeIcon} size="sm" /></div>
                             </Tooltip>
 
-                            <Tooltip title="Edit Link">
+                            <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Edit Link</div></React.Fragment>}>
                                 <div className="button" ref={this._editRef} onPointerDown={this.onEdit}>
                                     <FontAwesomeIcon className="fa-icon" icon="edit" size="sm" /></div>
                             </Tooltip>
-                            <Tooltip title="Delete Link">
+                            <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Delete Link</div></React.Fragment>}>
                                 <div className="button" onPointerDown={this.deleteLink}>
                                     <FontAwesomeIcon className="fa-icon" icon="trash" size="sm" /></div>
                             </Tooltip>
diff --git a/src/client/views/nodes/DocumentLinksButton.scss b/src/client/views/nodes/DocumentLinksButton.scss
index 35d99d44b..97e714cd5 100644
--- a/src/client/views/nodes/DocumentLinksButton.scss
+++ b/src/client/views/nodes/DocumentLinksButton.scss
@@ -13,18 +13,18 @@
     color: black;
     text-transform: uppercase;
     letter-spacing: 2px;
-    font-size: 75%;
+    font-size: 10px;
     transition: transform 0.2s;
     text-align: center;
     display: flex;
     justify-content: center;
     align-items: center;
 
-    // &:hover {
-    //     background: deepskyblue;
-    //     transform: scale(1.05);
-    //     cursor: pointer;
-    // }
+    &:hover {
+        // background: deepskyblue;
+        // transform: scale(1.05);
+        cursor: pointer;
+    }
 }
 
 .documentLinksButton {
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 83710cfbf..96ff0157e 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -168,8 +168,8 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
         const links = DocListCast(this.props.View.props.Document.links);
 
         const menuTitle = this.props.StartLink ? "Drag or tap to start link" : "Tap to complete link";
-
-        const title = this.props.InMenu ? menuTitle : "Tap to view links";
+        const buttonTitle = "Tap to view links";
+        const title = this.props.InMenu ? menuTitle : buttonTitle;
 
 
         const startLink = <img
@@ -202,14 +202,10 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
             //     Location: [e.clientX, e.clientY + 20]
             // }))} 
             >
-                {/* {this.props.InMenu ? this.props.StartLink ? <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" /> :
-                    <FontAwesomeIcon className="documentdecorations-icon" icon="unlink" size="sm" /> : links.length} */}
 
-                {/* {this.props.InMenu ? this.props.StartLink ? <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" /> :
-                    link : links.length} */}
+                {this.props.InMenu ? this.props.StartLink ? <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" /> :
+                    <FontAwesomeIcon className="documentdecorations-icon" icon="hand-paper" size="sm" /> : links.length}
 
-                {this.props.InMenu ? this.props.StartLink ? startLink :
-                    endLink : links.length}
             </div>
             {DocumentLinksButton.StartLink && this.props.InMenu && !!!this.props.StartLink && DocumentLinksButton.StartLink !== this.props.View ? <div className={"documentLinksButton-endLink"}
                 style={{ width: this.props.InMenu ? "20px" : "30px", height: this.props.InMenu ? "20px" : "30px" }}
@@ -217,10 +213,16 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
             {DocumentLinksButton.StartLink === this.props.View && this.props.InMenu && this.props.StartLink ? <div className={"documentLinksButton-startLink"}
                 style={{ width: this.props.InMenu ? "20px" : "30px", height: this.props.InMenu ? "20px" : "30px" }} /> : (null)}
         </div>;
+
         return (!links.length) && !this.props.AlwaysOn ? (null) :
-            <Tooltip title={title}>
-                {linkButton}
-            </Tooltip>;
+            this.props.InMenu ?
+                <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{title}</div></React.Fragment>}>
+                    {linkButton}
+                </Tooltip> : !!!DocumentLinksButton.EditLink ?
+                    <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{title}</div></React.Fragment>}>
+                        {linkButton}
+                    </Tooltip> :
+                    linkButton;
     }
     render() {
         return this.linkButton;
diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx
index 079920f56..1caa82380 100644
--- a/src/client/views/nodes/LinkDocPreview.tsx
+++ b/src/client/views/nodes/LinkDocPreview.tsx
@@ -123,7 +123,8 @@ export class LinkDocPreview extends React.Component<Props> {
                 bringToFront={returnFalse}
                 ContentScaling={returnOne}
                 NativeWidth={returnZero}
-                NativeHeight={returnZero} />;
+                NativeHeight={returnZero}
+                backgroundColor={this.props.backgroundColor} />;
     }
 
     render() {
diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
index fa2548cb5..c98b5eac1 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
@@ -270,14 +270,14 @@ export class FormattedTextBoxComment {
                                         </div>
                                         <div className="wrapper" style={{ float: "right" }}>
 
-                                            <Tooltip title="Delete Link" placement="top">
+                                            <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Delete Link</div></React.Fragment>} placement="top">
                                                 <div className="FormattedTextBoxComment-button"
                                                     ref={(r) => this._deleteRef = r}>
                                                     <FontAwesomeIcon className="FormattedTextBoxComment-fa-icon" icon="trash" color="white"
                                                         size="sm" /></div>
                                             </Tooltip>
 
-                                            <Tooltip title="Follow Link" placement="top">
+                                            <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Follow Link</div></React.Fragment>} placement="top">
                                                 <div className="FormattedTextBoxComment-button"
                                                     ref={(r) => this._followRef = r}>
                                                     <FontAwesomeIcon className="FormattedTextBoxComment-fa-icon" icon="arrow-right" color="white"
-- 
cgit v1.2.3-70-g09d2


From fcc7d375deb197854367ec40691fe0e72fba74f5 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 14 Jul 2020 02:13:06 -0400
Subject: fixed cursor for doc decoration title drag

---
 src/client/views/DocumentDecorations.tsx | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index d7324e1a6..444d2fe50 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -17,14 +17,11 @@ import { DocumentButtonBar } from './DocumentButtonBar';
 import './DocumentDecorations.scss';
 import { DocumentView } from "./nodes/DocumentView";
 import React = require("react");
-import { Id, Copy, Update } from '../../fields/FieldSymbols';
 import e = require('express');
 import { CollectionDockingView } from './collections/CollectionDockingView';
 import { SnappingManager } from '../util/SnappingManager';
 import { HtmlField } from '../../fields/HtmlField';
 import { InkData, InkField, InkTool } from "../../fields/InkField";
-import { update } from 'serializr';
-import { Transform } from "../util/Transform";
 import { Tooltip } from '@material-ui/core';
 
 library.add(faCaretUp);
@@ -579,7 +576,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                     <FontAwesomeIcon size="lg" icon="cog" />
                 </div></Tooltip>}
                 <div className="documentDecorations-title" key="title" onPointerDown={this.onTitleDown} >
-                    <span style={{ width: "100%", display: "inline-block" }}>{`${this.selectionTitle}`}</span>
+                    <span style={{ width: "100%", display: "inline-block", cursor: "move" }}>{`${this.selectionTitle}`}</span>
                 </div>
             </>;
 
-- 
cgit v1.2.3-70-g09d2


From ba86637704663e4791b0bccd2762f15a55fc188d Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 15 Jul 2020 11:32:25 -0400
Subject: moved all of collectionViewChrome permanently into CollectionMenu

---
 src/client/views/DocumentDecorations.tsx           |   2 +-
 src/client/views/collections/CollectionMenu.scss   |   5 +-
 src/client/views/collections/CollectionMenu.tsx    |  25 +-
 .../views/collections/CollectionViewChromes.scss   | 466 ------------
 .../views/collections/CollectionViewChromes.tsx    | 800 ---------------------
 5 files changed, 15 insertions(+), 1283 deletions(-)
 delete mode 100644 src/client/views/collections/CollectionViewChromes.scss
 delete mode 100644 src/client/views/collections/CollectionViewChromes.tsx

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 444d2fe50..bf3037e91 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -150,7 +150,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         if (e.button === 0 && !e.altKey && !e.ctrlKey) {
             let child = SelectionManager.SelectedDocuments()[0].ContentDiv!.children[0];
             while (child.children.length) {
-                const next = Array.from(child.children).find(c => typeof (c.className) !== "string" || !c.className.includes("collectionViewChrome"));
+                const next = Array.from(child.children).find(c => typeof (c.className) !== "string");
                 if (typeof (next?.className) === "string" && next?.className.includes("documentView-node")) break;
                 if (next) child = next;
                 else break;
diff --git a/src/client/views/collections/CollectionMenu.scss b/src/client/views/collections/CollectionMenu.scss
index c1a3f9c09..348b9e6ea 100644
--- a/src/client/views/collections/CollectionMenu.scss
+++ b/src/client/views/collections/CollectionMenu.scss
@@ -11,6 +11,8 @@
     background: #121721;
     color: white;
     transform-origin: top left;
+    top: 0;
+    width:100%;
 
     .antimodeMenu-button {
         padding:0;
@@ -21,13 +23,14 @@
         }
     }
 
-    .collectionViewChrome {
+    .collectionMenu {
         display: flex;
         padding-bottom: 1px;
         height: 32px;
         border-bottom: .5px solid rgb(180, 180, 180);
         overflow: visible;
         z-index: 9001;
+        border: unset;
 
         .collectionViewBaseChrome {
             display: flex;
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index d7e2baca8..827c3e299 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -47,7 +47,7 @@ export default class CollectionMenu extends AntimodeMenu {
     }
 }
 
-interface CollectionViewChromeProps {
+interface CollectionMenuProps {
     CollectionView: CollectionView;
     type: CollectionViewType;
 }
@@ -55,7 +55,7 @@ interface CollectionViewChromeProps {
 const stopPropagation = (e: React.SyntheticEvent) => e.stopPropagation();
 
 @observer
-export class CollectionViewBaseChrome extends React.Component<CollectionViewChromeProps> {
+export class CollectionViewBaseChrome extends React.Component<CollectionMenuProps> {
     //(!)?\(\(\(doc.(\w+) && \(doc.\w+ as \w+\).includes\(\"(\w+)\"\)
 
     get target() { return this.props.CollectionView.props.Document; }
@@ -249,14 +249,9 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
     }
 
     render() {
-        const scale = Math.min(1, this.props.CollectionView.props.ScreenToLocalTransform()?.Scale);
         return (
-            <div className="collectionMenu-cont" style={{
-                top: 0,
-                transform: `scale(${scale})`,
-                width: "100%"
-            }}>
-                <div className="collectionViewChrome" style={{ border: "unset" }}>
+            <div className="collectionMenu-cont" >
+                <div className="collectionMenu">
                     <div className="collectionViewBaseChrome">
                         {this.viewModes}
                         <div className="collectionViewBaseChrome-viewSpecs" title="filter documents to show" style={{ display: "grid" }}>
@@ -274,7 +269,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
 }
 
 @observer
-export class CollectionFreeFormViewChrome extends React.Component<CollectionViewChromeProps> {
+export class CollectionFreeFormViewChrome extends React.Component<CollectionMenuProps> {
 
     get Document() { return this.props.CollectionView.props.Document; }
     @computed get dataField() {
@@ -323,7 +318,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionView
     }
 }
 @observer
-export class CollectionStackingViewChrome extends React.Component<CollectionViewChromeProps> {
+export class CollectionStackingViewChrome extends React.Component<CollectionMenuProps> {
     @observable private _currentKey: string = "";
     @observable private suggestions: string[] = [];
 
@@ -423,7 +418,7 @@ export class CollectionStackingViewChrome extends React.Component<CollectionView
 
 
 @observer
-export class CollectionSchemaViewChrome extends React.Component<CollectionViewChromeProps> {
+export class CollectionSchemaViewChrome extends React.Component<CollectionMenuProps> {
     // private _textwrapAllRows: boolean = Cast(this.props.CollectionView.props.Document.textwrappedSchemaRows, listSpec("string"), []).length > 0;
 
     @undoBatch
@@ -470,7 +465,7 @@ export class CollectionSchemaViewChrome extends React.Component<CollectionViewCh
 }
 
 @observer
-export class CollectionTreeViewChrome extends React.Component<CollectionViewChromeProps> {
+export class CollectionTreeViewChrome extends React.Component<CollectionMenuProps> {
 
     get sortAscending() {
         return this.props.CollectionView.props.Document[this.props.CollectionView.props.fieldKey + "-sortAscending"];
@@ -506,7 +501,7 @@ export class CollectionTreeViewChrome extends React.Component<CollectionViewChro
 
 // Enter scroll speed for 3D Carousel 
 @observer
-export class Collection3DCarouselViewChrome extends React.Component<CollectionViewChromeProps> {
+export class Collection3DCarouselViewChrome extends React.Component<CollectionMenuProps> {
     @computed get scrollSpeed() {
         return this.props.CollectionView.props.Document._autoScrollSpeed;
     }
@@ -545,7 +540,7 @@ export class Collection3DCarouselViewChrome extends React.Component<CollectionVi
  * Chrome for grid view.
  */
 @observer
-export class CollectionGridViewChrome extends React.Component<CollectionViewChromeProps> {
+export class CollectionGridViewChrome extends React.Component<CollectionMenuProps> {
 
     private clicked: boolean = false;
     private entered: boolean = false;
diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss
deleted file mode 100644
index b1e8d20ad..000000000
--- a/src/client/views/collections/CollectionViewChromes.scss
+++ /dev/null
@@ -1,466 +0,0 @@
-@import "../globalCssVariables";
-@import '~js-datepicker/dist/datepicker.min.css';
-
-.collectionViewChrome-cont {
-    position: absolute;
-    width: 100%;
-    opacity: 0.9;
-    z-index: 9001;
-    transition: top .5s;
-    background: lightgrey;
-    transform-origin: top left;
-
-    .collectionViewChrome {
-        display: flex;
-        padding-bottom: 1px;
-        height: 32px;
-        border-bottom: .5px solid rgb(180, 180, 180);
-        overflow: visible;
-        z-index: 9001;
-
-        .collectionViewBaseChrome {
-            display: flex;
-
-            .collectionViewBaseChrome-viewPicker {
-                font-size: 75%;
-                //text-transform: uppercase;
-                //letter-spacing: 2px;
-                background: rgb(238, 238, 238);
-                color: grey;
-                outline-color: black;
-                border: none;
-                //padding: 12px 10px 11px 10px;
-            }
-
-            .collectionViewBaseChrome-viewPicker:active {
-                outline-color: black;
-            }
-
-            .collectionViewBaseChrome-button {
-                font-size: 75%;
-                text-transform: uppercase;
-                letter-spacing: 2px;
-                background: rgb(238, 238, 238);
-                color: purple;
-                outline-color: black;
-                border: none;
-                padding: 12px 10px 11px 10px;
-                margin-left: 10px;
-            }
-
-            .collectionViewBaseChrome-cmdPicker {
-                margin-left: 3px;
-                margin-right: 0px;
-                font-size: 75%;
-                background: rgb(238, 238, 238);
-                border: none;
-                color: grey;
-            }
-
-            .commandEntry-outerDiv {
-                pointer-events: all;
-                background-color: gray;
-                display: flex;
-                flex-direction: row;
-                height: 30px;
-
-                .commandEntry-drop {
-                    color: white;
-                    width: 25px;
-                    margin-top: auto;
-                    margin-bottom: auto;
-                }
-            }
-
-            .collectionViewBaseChrome-collapse {
-                transition: all .5s, opacity 0.3s;
-                position: absolute;
-                width: 40px;
-                transform-origin: top left;
-                pointer-events: all;
-                // margin-top: 10px;
-            }
-
-            @media only screen and (max-device-width: 480px) {
-                .collectionViewBaseChrome-collapse {
-                    display: none;
-                }
-            }
-
-            .collectionViewBaseChrome-template,
-            .collectionViewBaseChrome-viewModes {
-                display: grid;
-                background: rgb(238, 238, 238);
-                color: grey;
-                margin-top: auto;
-                margin-bottom: auto;
-                margin-left: 5px;
-            }
-
-            .collectionViewBaseChrome-viewModes {
-                margin-left: 25px;
-            }
-
-            .collectionViewBaseChrome-viewSpecs {
-                margin-left: 5px;
-                display: grid;
-
-                .collectionViewBaseChrome-filterIcon {
-                    position: relative;
-                    display: flex;
-                    margin: auto;
-                    background: gray;
-                    color: white;
-                    width: 30px;
-                    height: 30px;
-                    align-items: center;
-                    justify-content: center;
-                }
-
-                .collectionViewBaseChrome-viewSpecsInput {
-                    padding: 12px 10px 11px 10px;
-                    border: 0px;
-                    color: grey;
-                    text-align: center;
-                    letter-spacing: 2px;
-                    outline-color: black;
-                    font-size: 75%;
-                    background: rgb(238, 238, 238);
-                    height: 100%;
-                    width: 75px;
-                }
-
-                .collectionViewBaseChrome-viewSpecsMenu {
-                    overflow: hidden;
-                    transition: height .5s, display .5s;
-                    position: absolute;
-                    top: 60px;
-                    z-index: 100;
-                    display: flex;
-                    flex-direction: column;
-                    background: rgb(238, 238, 238);
-                    box-shadow: grey 2px 2px 4px;
-
-                    .qs-datepicker {
-                        left: unset;
-                        right: 0;
-                    }
-
-                    .collectionViewBaseChrome-viewSpecsMenu-row {
-                        display: grid;
-                        grid-template-columns: 150px 200px 150px;
-                        margin-top: 10px;
-                        margin-right: 10px;
-
-                        .collectionViewBaseChrome-viewSpecsMenu-rowLeft,
-                        .collectionViewBaseChrome-viewSpecsMenu-rowMiddle,
-                        .collectionViewBaseChrome-viewSpecsMenu-rowRight {
-                            font-size: 75%;
-                            letter-spacing: 2px;
-                            color: grey;
-                            margin-left: 10px;
-                            padding: 5px;
-                            border: none;
-                            outline-color: black;
-                        }
-                    }
-
-                    .collectionViewBaseChrome-viewSpecsMenu-lastRow {
-                        display: grid;
-                        grid-template-columns: 1fr 1fr 1fr;
-                        grid-gap: 10px;
-                        margin: 10px;
-                    }
-                }
-            }
-        }
-
-        .collectionStackingViewChrome-cont,
-        .collectionTreeViewChrome-cont,
-        .collection3DCarouselViewChrome-cont {
-            display: flex;
-            justify-content: space-between;
-        }
-
-        .collectionGridViewChrome-cont {
-            display: flex;
-            margin-left: 10;
-
-            .collectionGridViewChrome-viewPicker {
-                font-size: 75%;
-                //text-transform: uppercase;
-                //letter-spacing: 2px;
-                background: rgb(238, 238, 238);
-                color: grey;
-                outline-color: black;
-                border: none;
-                //padding: 12px 10px 11px 10px;
-            }
-
-            .collectionGridViewChrome-viewPicker:active {
-                outline-color: black;
-            }
-
-            .grid-control {
-                align-self: center;
-                display: flex;
-                flex-direction: row;
-                margin-right: 5px;
-
-                .grid-icon {
-                    margin-right: 5px;
-                    align-self: center;
-                }
-
-                .flexLabel {
-                    margin-bottom: 0;
-                }
-            }
-
-            .collectionGridViewChrome-entryBox {
-                width: 50%;
-            }
-        }
-
-
-        .collectionStackingViewChrome-sort,
-        .collectionTreeViewChrome-sort {
-            display: flex;
-            align-items: center;
-            justify-content: space-between;
-
-            .collectionStackingViewChrome-sortIcon,
-            .collectionTreeViewChrome-sortIcon {
-                transition: transform .5s;
-                margin-left: 10px;
-            }
-        }
-
-        button:hover {
-            transform: scale(1);
-        }
-
-
-        .collectionStackingViewChrome-pivotField-cont,
-        .collectionTreeViewChrome-pivotField-cont,
-        .collection3DCarouselViewChrome-scrollSpeed-cont {
-            justify-self: right;
-            display: flex;
-            font-size: 75%;
-            letter-spacing: 2px;
-
-            .collectionStackingViewChrome-pivotField-label,
-            .collectionTreeViewChrome-pivotField-label,
-            .collection3DCarouselViewChrome-scrollSpeed-label {
-                vertical-align: center;
-                padding-left: 10px;
-                margin: auto;
-            }
-
-            .collectionStackingViewChrome-pivotField,
-            .collectionTreeViewChrome-pivotField,
-            .collection3DCarouselViewChrome-scrollSpeed {
-                color: white;
-                width: 100%;
-                min-width: 100px;
-                display: flex;
-                align-items: center;
-                background: rgb(238, 238, 238);
-
-                .editable-view-input,
-                input,
-                .editableView-container-editing-oneLine,
-                .editableView-container-editing {
-                    margin: auto;
-                    border: 0px;
-                    color: grey !important;
-                    text-align: center;
-                    letter-spacing: 2px;
-                    outline-color: black;
-                    height: 100%;
-                }
-
-                .react-autosuggest__container {
-                    margin: 0;
-                    color: grey;
-                    padding: 0px;
-                }
-            }
-        }
-
-        .collectionStackingViewChrome-pivotField:hover,
-        .collectionTreeViewChrome-pivotField:hover,
-        .collection3DCarouselViewChrome-scrollSpeed:hover {
-            cursor: text;
-        }
-
-    }
-}
-
-.collectionFreeFormViewChrome-cont {
-    width: 60px;
-    display: flex;
-    position: relative;
-    align-items: center;
-
-    .fwdKeyframe,
-    .numKeyframe,
-    .backKeyframe {
-        cursor: pointer;
-        position: absolute;
-        width: 20;
-        height: 30;
-        bottom: 0;
-        background: gray;
-        display: flex;
-        align-items: center;
-        color: white;
-    }
-
-    .backKeyframe {
-        left: 0;
-
-        svg {
-            display: block;
-            margin: auto;
-        }
-    }
-
-    .numKeyframe {
-        left: 20;
-        display: flex;
-        flex-direction: column;
-        padding: 5px;
-    }
-
-    .fwdKeyframe {
-        left: 40;
-
-        svg {
-            display: block;
-            margin: auto;
-        }
-    }
-}
-
-.collectionSchemaViewChrome-cont {
-    display: flex;
-    font-size: 10.5px;
-
-    .collectionSchemaViewChrome-toggle {
-        display: flex;
-        margin-left: 10px;
-    }
-
-    .collectionSchemaViewChrome-label {
-        text-transform: uppercase;
-        letter-spacing: 2px;
-        margin-right: 5px;
-        display: flex;
-        flex-direction: column;
-        justify-content: center;
-    }
-
-    .collectionSchemaViewChrome-toggler {
-        width: 100px;
-        height: 41px;
-        background-color: black;
-        position: relative;
-    }
-
-    .collectionSchemaViewChrome-togglerButton {
-        width: 47px;
-        height: 35px;
-        background-color: $light-color-secondary;
-        // position: absolute;
-        transition: all 0.5s ease;
-        // top: 3px;
-        margin-top: 3px;
-        color: gray;
-        letter-spacing: 2px;
-        text-transform: uppercase;
-        display: flex;
-        flex-direction: column;
-        justify-content: center;
-        text-align: center;
-
-        &.on {
-            margin-left: 3px;
-        }
-
-        &.off {
-            margin-left: 50px;
-        }
-    }
-}
-
-
-.commandEntry-outerDiv {
-    display: flex;
-    flex-direction: column;
-    height: 40px;
-}
-
-.commandEntry-inputArea {
-    display: flex;
-    flex-direction: row;
-    width: 150px;
-    margin: auto auto auto auto;
-}
-
-.react-autosuggest__container {
-    position: relative;
-    width: 100%;
-    margin-left: 5px;
-    margin-right: 5px;
-}
-
-.react-autosuggest__input {
-    border: 1px solid #aaa;
-    border-radius: 4px;
-    width: 100%;
-}
-
-.react-autosuggest__input--focused {
-    outline: none;
-}
-
-.react-autosuggest__input--open {
-    border-bottom-left-radius: 0;
-    border-bottom-right-radius: 0;
-}
-
-.react-autosuggest__suggestions-container {
-    display: none;
-}
-
-.react-autosuggest__suggestions-container--open {
-    display: block;
-    position: fixed;
-    overflow-y: auto;
-    max-height: 400px;
-    width: 180px;
-    border: 1px solid #aaa;
-    background-color: #fff;
-    font-family: Helvetica, sans-serif;
-    font-weight: 300;
-    font-size: 16px;
-    border-bottom-left-radius: 4px;
-    border-bottom-right-radius: 4px;
-    z-index: 2;
-}
-
-.react-autosuggest__suggestions-list {
-    margin: 0;
-    padding: 0;
-    list-style-type: none;
-}
-
-.react-autosuggest__suggestion {
-    cursor: pointer;
-    padding: 10px 20px;
-}
-
-.react-autosuggest__suggestion--highlighted {
-    background-color: #ddd;
-}
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx
deleted file mode 100644
index 7f1fe7649..000000000
--- a/src/client/views/collections/CollectionViewChromes.tsx
+++ /dev/null
@@ -1,800 +0,0 @@
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { action, computed, observable, runInAction, Lambda } from "mobx";
-import { observer } from "mobx-react";
-import * as React from "react";
-import { Doc, DocListCast, Opt } from "../../../fields/Doc";
-import { Id } from "../../../fields/FieldSymbols";
-import { List } from "../../../fields/List";
-import { listSpec } from "../../../fields/Schema";
-import { BoolCast, Cast, NumCast, StrCast } from "../../../fields/Types";
-import { Utils, emptyFunction, setupMoveUpEvents } from "../../../Utils";
-import { DragManager } from "../../util/DragManager";
-import { undoBatch } from "../../util/UndoManager";
-import { EditableView } from "../EditableView";
-import { COLLECTION_BORDER_WIDTH } from "../globalCssVariables.scss";
-import { CollectionViewType } from "./CollectionView";
-import { CollectionView } from "./CollectionView";
-import "./CollectionViewChromes.scss";
-import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView";
-
-interface CollectionViewChromeProps {
-    CollectionView: CollectionView;
-    type: CollectionViewType;
-    collapse?: (value: boolean) => any;
-    PanelWidth: () => number;
-}
-
-interface Filter {
-    key: string;
-    value: string;
-    contains: boolean;
-}
-
-const stopPropagation = (e: React.SyntheticEvent) => e.stopPropagation();
-
-@observer
-export class CollectionViewBaseChrome extends React.Component<CollectionViewChromeProps> {
-    //(!)?\(\(\(doc.(\w+) && \(doc.\w+ as \w+\).includes\(\"(\w+)\"\)
-
-    get target() { return this.props.CollectionView.props.Document; }
-    _templateCommand = {
-        params: ["target", "source"], title: "=> item view",
-        script: "this.target.childLayout = getDocTemplate(this.source?.[0])",
-        immediate: undoBatch((source: Doc[]) => source.length && (this.target.childLayout = Doc.getDocTemplate(source?.[0]))),
-        initialize: emptyFunction,
-    };
-    _narrativeCommand = {
-        params: ["target", "source"], title: "=> child click view",
-        script: "this.target.childClickedOpenTemplateView = getDocTemplate(this.source?.[0])",
-        immediate: undoBatch((source: Doc[]) => source.length && (this.target.childClickedOpenTemplateView = Doc.getDocTemplate(source?.[0]))),
-        initialize: emptyFunction,
-    };
-    _contentCommand = {
-        params: ["target", "source"], title: "=> clear content",
-        script: "getProto(this.target).data = copyField(this.source);",
-        immediate: undoBatch((source: Doc[]) => Doc.GetProto(this.target).data = new List<Doc>(source)), // Doc.aliasDocs(source),
-        initialize: emptyFunction,
-    };
-    _viewCommand = {
-        params: ["target"], title: "=> reset view",
-        script: "this.target._panX = this.restoredPanX; this.target._panY = this.restoredPanY; this.target.scale = this.restoredScale;",
-        immediate: undoBatch((source: Doc[]) => { this.target._panX = 0; this.target._panY = 0; this.target.scale = 1; }),
-        initialize: (button: Doc) => { button.restoredPanX = this.target._panX; button.restoredPanY = this.target._panY; button.restoredScale = this.target.scale; },
-    };
-    _clusterCommand = {
-        params: ["target"], title: "=> fit content",
-        script: "this.target._fitToBox = !this.target._fitToBox;",
-        immediate: undoBatch((source: Doc[]) => this.target._fitToBox = !this.target._fitToBox),
-        initialize: emptyFunction
-    };
-    _fitContentCommand = {
-        params: ["target"], title: "=> toggle clusters",
-        script: "this.target.useClusters = !this.target.useClusters;",
-        immediate: undoBatch((source: Doc[]) => this.target.useClusters = !this.target.useClusters),
-        initialize: emptyFunction
-    };
-
-    _freeform_commands = [this._viewCommand, this._fitContentCommand, this._clusterCommand, this._contentCommand, this._templateCommand, this._narrativeCommand];
-    _stacking_commands = [this._contentCommand, this._templateCommand];
-    _masonry_commands = [this._contentCommand, this._templateCommand];
-    _schema_commands = [this._templateCommand, this._narrativeCommand];
-    _tree_commands = [];
-    private get _buttonizableCommands() {
-        switch (this.props.type) {
-            case CollectionViewType.Tree: return this._tree_commands;
-            case CollectionViewType.Schema: return this._schema_commands;
-            case CollectionViewType.Stacking: return this._stacking_commands;
-            case CollectionViewType.Masonry: return this._stacking_commands;
-            case CollectionViewType.Freeform: return this._freeform_commands;
-            case CollectionViewType.Time: return this._freeform_commands;
-            case CollectionViewType.Carousel: return this._freeform_commands;
-            case CollectionViewType.Carousel3D: return this._freeform_commands;
-        }
-        return [];
-    }
-    private _picker: any;
-    private _commandRef = React.createRef<HTMLInputElement>();
-    private _viewRef = React.createRef<HTMLInputElement>();
-    @observable private _currentKey: string = "";
-
-    componentDidMount = action(() => {
-        this._currentKey = this._currentKey || (this._buttonizableCommands.length ? this._buttonizableCommands[0]?.title : "");
-        // chrome status is one of disabled, collapsed, or visible. this determines initial state from document
-        switch (this.props.CollectionView.props.Document._chromeStatus) {
-            case "disabled":
-                throw new Error("how did you get here, if chrome status is 'disabled' on a collection, a chrome shouldn't even be instantiated!");
-            case "collapsed":
-                this.props.collapse?.(true);
-                break;
-        }
-    });
-
-    @undoBatch
-    viewChanged = (e: React.ChangeEvent) => {
-        //@ts-ignore
-        this.document._viewType = e.target.selectedOptions[0].value;
-    }
-
-    commandChanged = (e: React.ChangeEvent) => {
-        //@ts-ignore
-        runInAction(() => this._currentKey = e.target.selectedOptions[0].value);
-    }
-
-    @action
-    toggleViewSpecs = (e: React.SyntheticEvent) => {
-        this.document._facetWidth = this.document._facetWidth ? 0 : 200;
-        e.stopPropagation();
-    }
-
-    @action closeViewSpecs = () => {
-        this.document._facetWidth = 0;
-    }
-
-    // @action
-    // openDatePicker = (e: React.PointerEvent) => {
-    //     if (this._picker) {
-    //         this._picker.alwaysShow = true;
-    //         this._picker.show();
-    //         // TODO: calendar is offset when zoomed in/out
-    //         // this._picker.calendar.style.position = "absolute";
-    //         // let transform = this.props.CollectionView.props.ScreenToLocalTransform();
-    //         // let x = parseInt(this._picker.calendar.style.left) / transform.Scale;
-    //         // let y = parseInt(this._picker.calendar.style.top) / transform.Scale;
-    //         // this._picker.calendar.style.left = x;
-    //         // this._picker.calendar.style.top = y;
-
-    //         e.stopPropagation();
-    //     }
-    // }
-
-    // <input className="collectionViewBaseChrome-viewSpecsMenu-rowRight"
-    //     id={Utils.GenerateGuid()}
-    //     ref={this.datePickerRef}
-    //     value={this._dateValue instanceof Date ? this._dateValue.toLocaleDateString() : this._dateValue}
-    //     onChange={(e) => runInAction(() => this._dateValue = e.target.value)}
-    //     onPointerDown={this.openDatePicker}
-    //     placeholder="Value" />
-    // @action.bound
-    // applyFilter = (e: React.MouseEvent) => {
-    //     const keyRestrictionScript = "(" + this._keyRestrictions.map(i => i[1]).filter(i => i.length > 0).join(" && ") + ")";
-    //     const yearOffset = this._dateWithinValue[1] === 'y' ? 1 : 0;
-    //     const monthOffset = this._dateWithinValue[1] === 'm' ? parseInt(this._dateWithinValue[0]) : 0;
-    //     const weekOffset = this._dateWithinValue[1] === 'w' ? parseInt(this._dateWithinValue[0]) : 0;
-    //     const dayOffset = (this._dateWithinValue[1] === 'd' ? parseInt(this._dateWithinValue[0]) : 0) + weekOffset * 7;
-    //     let dateRestrictionScript = "";
-    //     if (this._dateValue instanceof Date) {
-    //         const lowerBound = new Date(this._dateValue.getFullYear() - yearOffset, this._dateValue.getMonth() - monthOffset, this._dateValue.getDate() - dayOffset);
-    //         const upperBound = new Date(this._dateValue.getFullYear() + yearOffset, this._dateValue.getMonth() + monthOffset, this._dateValue.getDate() + dayOffset + 1);
-    //         dateRestrictionScript = `((doc.creationDate as any).date >= ${lowerBound.valueOf()} && (doc.creationDate as any).date <= ${upperBound.valueOf()})`;
-    //     }
-    //     else {
-    //         const createdDate = new Date(this._dateValue);
-    //         if (!isNaN(createdDate.getTime())) {
-    //             const lowerBound = new Date(createdDate.getFullYear() - yearOffset, createdDate.getMonth() - monthOffset, createdDate.getDate() - dayOffset);
-    //             const upperBound = new Date(createdDate.getFullYear() + yearOffset, createdDate.getMonth() + monthOffset, createdDate.getDate() + dayOffset + 1);
-    //             dateRestrictionScript = `((doc.creationDate as any).date >= ${lowerBound.valueOf()} && (doc.creationDate as any).date <= ${upperBound.valueOf()})`;
-    //         }
-    //     }
-    //     const fullScript = dateRestrictionScript.length || keyRestrictionScript.length ? dateRestrictionScript.length ?
-    //         `${dateRestrictionScript} ${keyRestrictionScript.length ? "&&" : ""} (${keyRestrictionScript})` :
-    //         `(${keyRestrictionScript}) ${dateRestrictionScript.length ? "&&" : ""} ${dateRestrictionScript}` :
-    //         "true";
-
-    //     this.props.CollectionView.props.Document.viewSpecScript = ScriptField.MakeFunction(fullScript, { doc: Doc.name });
-    // }
-
-    // datePickerRef = (node: HTMLInputElement) => {
-    //     if (node) {
-    //         try {
-    //             this._picker = datepicker("#" + node.id, {
-    //                 disabler: (date: Date) => date > new Date(),
-    //                 onSelect: (instance: any, date: Date) => runInAction(() => {}), //  this._dateValue = date),
-    //                 dateSelected: new Date()
-    //             });
-    //         } catch (e) {
-    //             console.log("date picker exception:" + e);
-    //         }
-    //     }
-    // }
-
-
-    @action
-    toggleCollapse = () => {
-        this.document._chromeStatus = this.document._chromeStatus === "enabled" ? "collapsed" : "enabled";
-        if (this.props.collapse) {
-            this.props.collapse(this.props.CollectionView.props.Document._chromeStatus !== "enabled");
-        }
-    }
-
-    @computed get subChrome() {
-        const collapsed = this.document._chromeStatus !== "enabled";
-        if (collapsed) return null;
-        switch (this.props.type) {
-            case CollectionViewType.Freeform: return (<CollectionFreeFormViewChrome key="collchrome" PanelWidth={this.props.PanelWidth} CollectionView={this.props.CollectionView} type={this.props.type} />);
-            case CollectionViewType.Stacking: return (<CollectionStackingViewChrome key="collchrome" PanelWidth={this.props.PanelWidth} CollectionView={this.props.CollectionView} type={this.props.type} />);
-            case CollectionViewType.Schema: return (<CollectionSchemaViewChrome key="collchrome" PanelWidth={this.props.PanelWidth} CollectionView={this.props.CollectionView} type={this.props.type} />);
-            case CollectionViewType.Tree: return (<CollectionTreeViewChrome key="collchrome" PanelWidth={this.props.PanelWidth} CollectionView={this.props.CollectionView} type={this.props.type} />);
-            case CollectionViewType.Masonry: return (<CollectionStackingViewChrome key="collchrome" PanelWidth={this.props.PanelWidth} CollectionView={this.props.CollectionView} type={this.props.type} />);
-            case CollectionViewType.Carousel3D: return (<Collection3DCarouselViewChrome key="collchrome" PanelWidth={this.props.PanelWidth} CollectionView={this.props.CollectionView} type={this.props.type} />);
-            case CollectionViewType.Grid: return (<CollectionGridViewChrome key="collchrome" PanelWidth={this.props.PanelWidth} CollectionView={this.props.CollectionView} type={this.props.type} />);
-            default: return null;
-        }
-    }
-
-    private get document() {
-        return this.props.CollectionView.props.Document;
-    }
-
-    private dropDisposer?: DragManager.DragDropDisposer;
-    protected createDropTarget = (ele: HTMLDivElement) => {
-        this.dropDisposer?.();
-        if (ele) {
-            this.dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this), this.document);
-        }
-    }
-
-    @undoBatch
-    @action
-    protected drop(e: Event, de: DragManager.DropEvent): boolean {
-        const docDragData = de.complete.docDragData;
-        if (docDragData?.draggedDocuments.length) {
-            this._buttonizableCommands.filter(c => c.title === this._currentKey).map(c => c.immediate(docDragData.draggedDocuments || []));
-            e.stopPropagation();
-        }
-        return true;
-    }
-
-    dragViewDown = (e: React.PointerEvent) => {
-        setupMoveUpEvents(this, e, (e, down, delta) => {
-            const vtype = this.props.CollectionView.collectionViewType;
-            const c = {
-                params: ["target"], title: vtype,
-                script: `this.target._viewType = '${StrCast(this.props.CollectionView.props.Document._viewType)}'`,
-                immediate: (source: Doc[]) => this.props.CollectionView.props.Document._viewType = Doc.getDocTemplate(source?.[0]),
-                initialize: emptyFunction,
-            };
-            DragManager.StartButtonDrag([this._viewRef.current!], c.script, StrCast(c.title),
-                { target: this.props.CollectionView.props.Document }, c.params, c.initialize, e.clientX, e.clientY);
-            return true;
-        }, emptyFunction, emptyFunction);
-    }
-    dragCommandDown = (e: React.PointerEvent) => {
-        setupMoveUpEvents(this, e, (e, down, delta) => {
-            this._buttonizableCommands.filter(c => c.title === this._currentKey).map(c =>
-                DragManager.StartButtonDrag([this._commandRef.current!], c.script, c.title,
-                    { target: this.props.CollectionView.props.Document }, c.params, c.initialize, e.clientX, e.clientY));
-            return true;
-        }, emptyFunction, () => {
-            this._buttonizableCommands.filter(c => c.title === this._currentKey).map(c => c.immediate([]));
-        });
-    }
-
-    @computed get templateChrome() {
-        const collapsed = this.props.CollectionView.props.Document._chromeStatus !== "enabled";
-        return <div className="collectionViewBaseChrome-template" ref={this.createDropTarget} style={{ display: collapsed ? "none" : undefined }}>
-            <div className="commandEntry-outerDiv" title="drop document to apply or drag to create button" ref={this._commandRef} onPointerDown={this.dragCommandDown}>
-                <div className="commandEntry-drop">
-                    <FontAwesomeIcon icon="bullseye" size="2x" />
-                </div>
-                <select
-                    className="collectionViewBaseChrome-cmdPicker" onPointerDown={stopPropagation} onChange={this.commandChanged} value={this._currentKey}
-                    style={{ width: this.props.PanelWidth() < 300 ? 15 : undefined }}>
-                    <option className="collectionViewBaseChrome-viewOption" onPointerDown={stopPropagation} key={"empty"} value={""} />
-                    {this._buttonizableCommands.map(cmd =>
-                        <option className="collectionViewBaseChrome-viewOption" onPointerDown={stopPropagation} key={cmd.title} value={cmd.title}>{cmd.title}</option>
-                    )}
-                </select>
-            </div>
-        </div>;
-    }
-
-    @computed get viewModes() {
-        const collapsed = this.props.CollectionView.props.Document._chromeStatus !== "enabled";
-        return <div className="collectionViewBaseChrome-viewModes" style={{ display: collapsed ? "none" : undefined }}>
-            <div className="commandEntry-outerDiv" title="drop document to apply or drag to create button" ref={this._viewRef} onPointerDown={this.dragViewDown}>
-                <div className="commandEntry-drop">
-                    <FontAwesomeIcon icon="bullseye" size="2x" />
-                </div>
-                <select
-                    className="collectionViewBaseChrome-viewPicker" style={{ width: this.props.PanelWidth() < 300 ? 15 : undefined }}
-                    onPointerDown={stopPropagation}
-                    onChange={this.viewChanged}
-                    value={StrCast(this.props.CollectionView.props.Document._viewType)}>
-                    {Object.values(CollectionViewType).map(type => [CollectionViewType.Invalid, CollectionViewType.Docking].includes(type) ? (null) : (
-                        <option
-                            key={Utils.GenerateGuid()}
-                            className="collectionViewBaseChrome-viewOption"
-                            onPointerDown={stopPropagation}
-                            value={type}>
-                            {type[0].toUpperCase() + type.substring(1)}
-                        </option>
-                    ))}
-                </select>
-            </div>
-        </div>;
-    }
-
-    render() {
-        const collapsed = this.props.CollectionView.props.Document._chromeStatus !== "enabled";
-        const scale = Math.min(1, this.props.CollectionView.props.ScreenToLocalTransform()?.Scale);
-        return (
-            <div className="collectionViewChrome-cont" style={{
-                top: collapsed ? -70 : 0, height: collapsed ? 0 : undefined,
-                transform: collapsed ? "" : `scale(${scale})`,
-                width: `${this.props.PanelWidth() / scale}px`
-            }}>
-                <div className="collectionViewChrome" style={{ border: "unset", pointerEvents: collapsed ? "none" : undefined }}>
-                    <div className="collectionViewBaseChrome">
-                        <button className="collectionViewBaseChrome-collapse"
-                            style={{
-                                top: collapsed ? 70 : 10,
-                                transform: `rotate(${collapsed ? 180 : 0}deg) scale(0.5) translate(${collapsed ? "-100%, -100%" : "0, 0"})`,
-                                opacity: 0.9,
-                                display: (collapsed && !this.props.CollectionView.props.isSelected()) ? "none" : undefined,
-                                left: (collapsed ? 0 : "unset"),
-                            }}
-                            title="Collapse collection chrome" onClick={this.toggleCollapse}>
-                            <FontAwesomeIcon icon="caret-up" size="2x" />
-                        </button>
-                        {this.viewModes}
-                        <div className="collectionViewBaseChrome-viewSpecs" title="filter documents to show" style={{ display: collapsed ? "none" : "grid" }}>
-                            <div className="collectionViewBaseChrome-filterIcon" onPointerDown={this.toggleViewSpecs} >
-                                <FontAwesomeIcon icon="filter" size="2x" />
-                            </div>
-                        </div>
-                        {this.templateChrome}
-                    </div>
-                    {this.subChrome}
-                </div>
-            </div>
-        );
-    }
-}
-
-@observer
-export class CollectionFreeFormViewChrome extends React.Component<CollectionViewChromeProps> {
-
-    get Document() { return this.props.CollectionView.props.Document; }
-    @computed get dataField() {
-        return this.props.CollectionView.props.Document[Doc.LayoutFieldKey(this.props.CollectionView.props.Document)];
-    }
-    @computed get childDocs() {
-        return DocListCast(this.dataField);
-    }
-    @undoBatch
-    @action
-    nextKeyframe = (): void => {
-        const currentFrame = NumCast(this.Document.currentFrame);
-        if (currentFrame === undefined) {
-            this.Document.currentFrame = 0;
-            CollectionFreeFormDocumentView.setupKeyframes(this.childDocs, 0);
-        }
-        CollectionFreeFormDocumentView.updateKeyframe(this.childDocs, currentFrame || 0);
-        this.Document.currentFrame = Math.max(0, (currentFrame || 0) + 1);
-        this.Document.lastFrame = Math.max(NumCast(this.Document.currentFrame), NumCast(this.Document.lastFrame));
-    }
-    @undoBatch
-    @action
-    prevKeyframe = (): void => {
-        const currentFrame = NumCast(this.Document.currentFrame);
-        if (currentFrame === undefined) {
-            this.Document.currentFrame = 0;
-            CollectionFreeFormDocumentView.setupKeyframes(this.childDocs, 0);
-        }
-        CollectionFreeFormDocumentView.gotoKeyframe(this.childDocs.slice());
-        this.Document.currentFrame = Math.max(0, (currentFrame || 0) - 1);
-    }
-    render() {
-        return this.Document.isAnnotationOverlay ? (null) :
-            <div className="collectionFreeFormViewChrome-cont">
-                <div key="back" title="back frame" className="backKeyframe" onClick={this.prevKeyframe}>
-                    <FontAwesomeIcon icon={"caret-left"} size={"lg"} />
-                </div>
-                <div key="num" title="toggle view all" className="numKeyframe" style={{ backgroundColor: this.Document.editing ? "#759c75" : "#c56565" }}
-                    onClick={action(() => this.Document.editing = !this.Document.editing)} >
-                    {NumCast(this.Document.currentFrame)}
-                </div>
-                <div key="fwd" title="forward frame" className="fwdKeyframe" onClick={this.nextKeyframe}>
-                    <FontAwesomeIcon icon={"caret-right"} size={"lg"} />
-                </div>
-            </div>;
-    }
-}
-
-@observer
-export class CollectionStackingViewChrome extends React.Component<CollectionViewChromeProps> {
-    @observable private _currentKey: string = "";
-    @observable private suggestions: string[] = [];
-
-    @computed private get descending() { return StrCast(this.props.CollectionView.props.Document._columnsSort) === "descending"; }
-    @computed get pivotField() { return StrCast(this.props.CollectionView.props.Document._pivotField); }
-
-    getKeySuggestions = async (value: string): Promise<string[]> => {
-        value = value.toLowerCase();
-        const docs = DocListCast(this.props.CollectionView.props.Document[this.props.CollectionView.props.fieldKey]);
-        if (docs instanceof Doc) {
-            return Object.keys(docs).filter(key => key.toLowerCase().startsWith(value));
-        } else {
-            const keys = new Set<string>();
-            docs.forEach(doc => Doc.allKeys(doc).forEach(key => keys.add(key)));
-            return Array.from(keys).filter(key => key.toLowerCase().startsWith(value));
-        }
-    }
-
-    @action
-    onKeyChange = (e: React.ChangeEvent, { newValue }: { newValue: string }) => {
-        this._currentKey = newValue;
-    }
-
-    getSuggestionValue = (suggestion: string) => suggestion;
-
-    renderSuggestion = (suggestion: string) => {
-        return <p>{suggestion}</p>;
-    }
-
-    onSuggestionFetch = async ({ value }: { value: string }) => {
-        const sugg = await this.getKeySuggestions(value);
-        runInAction(() => {
-            this.suggestions = sugg;
-        });
-    }
-
-    @action
-    onSuggestionClear = () => {
-        this.suggestions = [];
-    }
-
-    @action
-    setValue = (value: string) => {
-        this.props.CollectionView.props.Document._pivotField = value;
-        return true;
-    }
-
-    @action toggleSort = () => {
-        this.props.CollectionView.props.Document._columnsSort =
-            this.props.CollectionView.props.Document._columnsSort === "descending" ? "ascending" :
-                this.props.CollectionView.props.Document._columnsSort === "ascending" ? undefined : "descending";
-    }
-    @action resetValue = () => { this._currentKey = this.pivotField; };
-
-    render() {
-        return (
-            <div className="collectionStackingViewChrome-cont">
-                <div className="collectionStackingViewChrome-pivotField-cont">
-                    <div className="collectionStackingViewChrome-pivotField-label">
-                        GROUP BY:
-                    </div>
-                    <div className="collectionStackingViewChrome-sortIcon" onClick={this.toggleSort} style={{ transform: `rotate(${this.descending ? "180" : "0"}deg)` }}>
-                        <FontAwesomeIcon icon="caret-up" size="2x" color="white" />
-                    </div>
-                    <div className="collectionStackingViewChrome-pivotField">
-                        <EditableView
-                            GetValue={() => this.pivotField}
-                            autosuggestProps={
-                                {
-                                    resetValue: this.resetValue,
-                                    value: this._currentKey,
-                                    onChange: this.onKeyChange,
-                                    autosuggestProps: {
-                                        inputProps:
-                                        {
-                                            value: this._currentKey,
-                                            onChange: this.onKeyChange
-                                        },
-                                        getSuggestionValue: this.getSuggestionValue,
-                                        suggestions: this.suggestions,
-                                        alwaysRenderSuggestions: true,
-                                        renderSuggestion: this.renderSuggestion,
-                                        onSuggestionsFetchRequested: this.onSuggestionFetch,
-                                        onSuggestionsClearRequested: this.onSuggestionClear
-                                    }
-                                }}
-                            oneLine
-                            SetValue={this.setValue}
-                            contents={this.pivotField ? this.pivotField : "N/A"}
-                        />
-                    </div>
-                </div>
-            </div>
-        );
-    }
-}
-
-
-@observer
-export class CollectionSchemaViewChrome extends React.Component<CollectionViewChromeProps> {
-    // private _textwrapAllRows: boolean = Cast(this.props.CollectionView.props.Document.textwrappedSchemaRows, listSpec("string"), []).length > 0;
-
-    @undoBatch
-    togglePreview = () => {
-        const dividerWidth = 4;
-        const borderWidth = Number(COLLECTION_BORDER_WIDTH);
-        const panelWidth = this.props.CollectionView.props.PanelWidth();
-        const previewWidth = NumCast(this.props.CollectionView.props.Document.schemaPreviewWidth);
-        const tableWidth = panelWidth - 2 * borderWidth - dividerWidth - previewWidth;
-        this.props.CollectionView.props.Document.schemaPreviewWidth = previewWidth === 0 ? Math.min(tableWidth / 3, 200) : 0;
-    }
-
-    @undoBatch
-    @action
-    toggleTextwrap = async () => {
-        const textwrappedRows = Cast(this.props.CollectionView.props.Document.textwrappedSchemaRows, listSpec("string"), []);
-        if (textwrappedRows.length) {
-            this.props.CollectionView.props.Document.textwrappedSchemaRows = new List<string>([]);
-        } else {
-            const docs = DocListCast(this.props.CollectionView.props.Document[this.props.CollectionView.props.fieldKey]);
-            const allRows = docs instanceof Doc ? [docs[Id]] : docs.map(doc => doc[Id]);
-            this.props.CollectionView.props.Document.textwrappedSchemaRows = new List<string>(allRows);
-        }
-    }
-
-
-    render() {
-        const previewWidth = NumCast(this.props.CollectionView.props.Document.schemaPreviewWidth);
-        const textWrapped = Cast(this.props.CollectionView.props.Document.textwrappedSchemaRows, listSpec("string"), []).length > 0;
-
-        return (
-            <div className="collectionSchemaViewChrome-cont">
-                <div className="collectionSchemaViewChrome-toggle">
-                    <div className="collectionSchemaViewChrome-label">Show Preview: </div>
-                    <div className="collectionSchemaViewChrome-toggler" onClick={this.togglePreview}>
-                        <div className={"collectionSchemaViewChrome-togglerButton" + (previewWidth !== 0 ? " on" : " off")}>
-                            {previewWidth !== 0 ? "on" : "off"}
-                        </div>
-                    </div>
-                </div>
-            </div >
-        );
-    }
-}
-
-@observer
-export class CollectionTreeViewChrome extends React.Component<CollectionViewChromeProps> {
-
-    get sortAscending() {
-        return this.props.CollectionView.props.Document[this.props.CollectionView.props.fieldKey + "-sortAscending"];
-    }
-    set sortAscending(value) {
-        this.props.CollectionView.props.Document[this.props.CollectionView.props.fieldKey + "-sortAscending"] = value;
-    }
-    @computed private get ascending() {
-        return Cast(this.sortAscending, "boolean", null);
-    }
-
-    @action toggleSort = () => {
-        if (this.sortAscending) this.sortAscending = undefined;
-        else if (this.sortAscending === undefined) this.sortAscending = false;
-        else this.sortAscending = true;
-    }
-
-    render() {
-        return (
-            <div className="collectionTreeViewChrome-cont">
-                <button className="collectionTreeViewChrome-sort" onClick={this.toggleSort}>
-                    <div className="collectionTreeViewChrome-sortLabel">
-                        Sort
-                        </div>
-                    <div className="collectionTreeViewChrome-sortIcon" style={{ transform: `rotate(${this.ascending === undefined ? "90" : this.ascending ? "180" : "0"}deg)` }}>
-                        <FontAwesomeIcon icon="caret-up" size="2x" color="white" />
-                    </div>
-                </button>
-            </div>
-        );
-    }
-}
-
-// Enter scroll speed for 3D Carousel 
-@observer
-export class Collection3DCarouselViewChrome extends React.Component<CollectionViewChromeProps> {
-    @computed get scrollSpeed() {
-        return this.props.CollectionView.props.Document._autoScrollSpeed;
-    }
-
-    @action
-    setValue = (value: string) => {
-        const numValue = Number(StrCast(value));
-        if (numValue > 0) {
-            this.props.CollectionView.props.Document._autoScrollSpeed = numValue;
-            return true;
-        }
-        return false;
-    }
-
-    render() {
-        return (
-            <div className="collection3DCarouselViewChrome-cont">
-                <div className="collection3DCarouselViewChrome-scrollSpeed-cont">
-                    <div className="collectionStackingViewChrome-scrollSpeed-label">
-                        AUTOSCROLL SPEED:
-                    </div>
-                    <div className="collection3DCarouselViewChrome-scrollSpeed">
-                        <EditableView
-                            GetValue={() => StrCast(this.scrollSpeed)}
-                            oneLine
-                            SetValue={this.setValue}
-                            contents={this.scrollSpeed ? this.scrollSpeed : 1000} />
-                    </div>
-                </div>
-            </div>
-        );
-    }
-}
-
-/**
- * Chrome for grid view.
- */
-@observer
-export class CollectionGridViewChrome extends React.Component<CollectionViewChromeProps> {
-
-    private clicked: boolean = false;
-    private entered: boolean = false;
-    private decrementLimitReached: boolean = false;
-    @observable private resize = false;
-    private resizeListenerDisposer: Opt<Lambda>;
-
-    componentDidMount() {
-
-        runInAction(() => this.resize = this.props.CollectionView.props.PanelWidth() < 700);
-
-        // listener to reduce text on chrome resize (panel resize)
-        this.resizeListenerDisposer = computed(() => this.props.CollectionView.props.PanelWidth()).observe(({ newValue }) => {
-            runInAction(() => this.resize = newValue < 700);
-        });
-    }
-
-    componentWillUnmount() {
-        this.resizeListenerDisposer?.();
-    }
-
-    get numCols() { return NumCast(this.props.CollectionView.props.Document.gridNumCols, 10); }
-
-    /**
-     * Sets the value of `numCols` on the grid's Document to the value entered.
-     */
-    @undoBatch
-    onNumColsEnter = (e: React.KeyboardEvent<HTMLInputElement>) => {
-        if (e.key === "Enter" || e.key === "Tab") {
-            if (e.currentTarget.valueAsNumber > 0) {
-                this.props.CollectionView.props.Document.gridNumCols = e.currentTarget.valueAsNumber;
-            }
-
-        }
-    }
-
-    /**
-     * Sets the value of `rowHeight` on the grid's Document to the value entered.
-     */
-    // @undoBatch
-    // onRowHeightEnter = (e: React.KeyboardEvent<HTMLInputElement>) => {
-    //     if (e.key === "Enter" || e.key === "Tab") {
-    //         if (e.currentTarget.valueAsNumber > 0 && this.props.CollectionView.props.Document.rowHeight as number !== e.currentTarget.valueAsNumber) {
-    //             this.props.CollectionView.props.Document.rowHeight = e.currentTarget.valueAsNumber;
-    //         }
-    //     }
-    // }
-
-    /**
-     * Sets whether the grid is flexible or not on the grid's Document.
-     */
-    @undoBatch
-    toggleFlex = () => {
-        this.props.CollectionView.props.Document.gridFlex = !BoolCast(this.props.CollectionView.props.Document.gridFlex, true);
-    }
-
-    /**
-     * Increments the value of numCols on button click
-     */
-    onIncrementButtonClick = () => {
-        this.clicked = true;
-        this.entered && (this.props.CollectionView.props.Document.gridNumCols as number)--;
-        undoBatch(() => this.props.CollectionView.props.Document.gridNumCols = this.numCols + 1)();
-        this.entered = false;
-    }
-
-    /**
-     * Decrements the value of numCols on button click
-     */
-    onDecrementButtonClick = () => {
-        this.clicked = true;
-        if (!this.decrementLimitReached) {
-            this.entered && (this.props.CollectionView.props.Document.gridNumCols as number)++;
-            undoBatch(() => this.props.CollectionView.props.Document.gridNumCols = this.numCols - 1)();
-        }
-        this.entered = false;
-    }
-
-    /**
-     * Increments the value of numCols on button hover
-     */
-    incrementValue = () => {
-        this.entered = true;
-        if (!this.clicked && !this.decrementLimitReached) {
-            this.props.CollectionView.props.Document.gridNumCols = this.numCols + 1;
-        }
-        this.decrementLimitReached = false;
-        this.clicked = false;
-    }
-
-    /**
-     * Decrements the value of numCols on button hover
-     */
-    decrementValue = () => {
-        this.entered = true;
-        if (!this.clicked) {
-            if (this.numCols !== 1) {
-                this.props.CollectionView.props.Document.gridNumCols = this.numCols - 1;
-            }
-            else {
-                this.decrementLimitReached = true;
-            }
-        }
-
-        this.clicked = false;
-    }
-
-    /**
-     * Toggles the value of preventCollision
-     */
-    toggleCollisions = () => {
-        this.props.CollectionView.props.Document.gridPreventCollision = !this.props.CollectionView.props.Document.gridPreventCollision;
-    }
-
-    /**
-     * Changes the value of the compactType
-     */
-    changeCompactType = (e: React.ChangeEvent<HTMLSelectElement>) => {
-        // need to change startCompaction so that this operation will be undoable.
-        this.props.CollectionView.props.Document.gridStartCompaction = e.target.selectedOptions[0].value;
-    }
-
-    render() {
-        return (
-            <div className="collectionGridViewChrome-cont" >
-                <span className="grid-control" style={{ width: this.resize ? "25%" : "30%" }}>
-                    <span className="grid-icon">
-                        <FontAwesomeIcon icon="columns" size="1x" />
-                    </span>
-                    <input className="collectionGridViewChrome-entryBox" type="number" placeholder={this.numCols.toString()} onKeyDown={this.onNumColsEnter} onClick={(e: React.MouseEvent<HTMLInputElement, MouseEvent>) => { e.stopPropagation(); e.preventDefault(); e.currentTarget.focus(); }} />
-                    <input className="columnButton" onClick={this.onIncrementButtonClick} onMouseEnter={this.incrementValue} onMouseLeave={this.decrementValue} type="button" value="↑" />
-                    <input className="columnButton" style={{ marginRight: 5 }} onClick={this.onDecrementButtonClick} onMouseEnter={this.decrementValue} onMouseLeave={this.incrementValue} type="button" value="↓" />
-                </span>
-                {/* <span className="grid-control">
-                    <span className="grid-icon">
-                        <FontAwesomeIcon icon="text-height" size="1x" />
-                    </span>
-                    <input className="collectionGridViewChrome-entryBox" type="number" placeholder={this.props.CollectionView.props.Document.rowHeight as string} onKeyDown={this.onRowHeightEnter} onClick={(e: React.MouseEvent<HTMLInputElement, MouseEvent>) => { e.stopPropagation(); e.preventDefault(); e.currentTarget.focus(); }} />
-                </span> */}
-                <span className="grid-control" style={{ width: this.resize ? "12%" : "20%" }}>
-                    <input type="checkbox" style={{ marginRight: 5 }} onChange={this.toggleCollisions} checked={!this.props.CollectionView.props.Document.gridPreventCollision} />
-                    <label className="flexLabel">{this.resize ? "Coll" : "Collisions"}</label>
-                </span>
-
-                <select className="collectionGridViewChrome-viewPicker"
-                    style={{ marginRight: 5, width: this.props.PanelWidth() < 300 ? 25 : undefined }}
-                    onPointerDown={stopPropagation}
-                    onChange={this.changeCompactType}
-                    value={StrCast(this.props.CollectionView.props.Document.gridStartCompaction, StrCast(this.props.CollectionView.props.Document.gridCompaction))}>
-                    {["vertical", "horizontal", "none"].map(type =>
-                        <option className="collectionGridViewChrome-viewOption"
-                            onPointerDown={stopPropagation}
-                            value={type}>
-                            {this.resize ? type[0].toUpperCase() + type.substring(1) : "Compact: " + type}
-                        </option>
-                    )}
-                </select>
-
-                <span className="grid-control" style={{ width: this.resize ? "12%" : "20%" }}>
-                    <input style={{ marginRight: 5 }} type="checkbox" onChange={this.toggleFlex}
-                        checked={BoolCast(this.props.CollectionView.props.Document.gridFlex, true)} />
-                    <label className="flexLabel">{this.resize ? "Flex" : "Flexible"}</label>
-                </span>
-
-                <button onClick={() => this.props.CollectionView.props.Document.gridResetLayout = true}>
-                    {!this.resize ? "Reset" :
-                        <FontAwesomeIcon icon="redo-alt" size="1x" />}
-                </button>
-
-            </div>
-        );
-    }
-}
-- 
cgit v1.2.3-70-g09d2


From 3fdee81100954e66f54c73661cb11967993ff467 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 15 Jul 2020 15:24:53 -0400
Subject: fixed tooltips to share a csss style.  added tooltips for richtext.

---
 src/client/documents/Documents.ts                  |  2 +-
 src/client/views/DocumentButtonBar.tsx             | 10 ++---
 src/client/views/DocumentDecorations.tsx           | 15 +++----
 src/client/views/MainView.scss                     |  4 ++
 .../views/collections/CollectionLinearView.tsx     | 20 +++++----
 src/client/views/collections/CollectionMenu.tsx    | 13 +++---
 src/client/views/collections/CollectionView.tsx    |  3 +-
 .../CollectionFreeFormLinkView.tsx                 | 12 +++---
 src/client/views/linking/LinkEditor.tsx            | 14 +++----
 src/client/views/linking/LinkMenuItem.tsx          | 19 +++------
 src/client/views/nodes/DocumentLinksButton.tsx     |  5 +--
 src/client/views/nodes/DocumentView.tsx            | 25 +++--------
 .../formattedText/FormattedTextBoxComment.tsx      |  4 +-
 .../views/nodes/formattedText/RichTextMenu.tsx     | 49 +++++++++++++---------
 src/client/views/pdf/PDFViewer.tsx                 |  2 +-
 15 files changed, 94 insertions(+), 103 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 1fd533b62..b57f4c6c7 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -915,7 +915,7 @@ export namespace DocUtils {
 
         const linkDoc = Docs.Create.LinkDocument(source, target, { linkRelationship, layoutKey: "layout_linkView", description }, id);
         linkDoc.linkDisplay = true;
-        linkDoc.hideAnhors = true;
+        linkDoc.hidden = true;
         linkDoc.layout_linkView = Cast(Cast(Doc.UserDoc()["template-button-link"], Doc, null).dragFactory, Doc, null);
         Doc.GetProto(linkDoc).title = ComputedField.MakeFunction('self.anchor1?.title +" (" + (self.linkRelationship||"to") +") "  + self.anchor2?.title');
 
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index 05538a28e..45f4c7393 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -118,7 +118,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
         const targetDoc = this.view0?.props.Document;
         const published = targetDoc && Doc.GetProto(targetDoc)[GoogleRef] !== undefined;
         const animation = this.isAnimatingPulse ? "shadow-pulse 1s linear infinite" : "none";
-        return !targetDoc ? (null) : <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{`${published ? "Push" : "Publish"} to Google Docs`}</div></React.Fragment>}>
+        return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{`${published ? "Push" : "Publish"} to Google Docs`}</div></>}>
             <div
                 className="documentButtonBar-linker"
                 style={{ animation }}
@@ -148,7 +148,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
         })();
 
         return !targetDoc || !dataDoc || !dataDoc[GoogleRef] ? (null) : <Tooltip
-            title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{title}</div></React.Fragment>}>
+            title={<><div className="dash-tooltip">{title}</div></>}>
             <div className="documentButtonBar-linker"
                 style={{ backgroundColor: this.pullColor }}
                 onPointerEnter={action(e => {
@@ -197,7 +197,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
     get pinButton() {
         const targetDoc = this.view0?.props.Document;
         const isPinned = targetDoc && Doc.isDocPinned(targetDoc);
-        return !targetDoc ? (null) : <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{Doc.isDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}</div></React.Fragment>}>
+        return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{Doc.isDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}</div></>}>
             <div className="documentButtonBar-linker"
                 style={{ backgroundColor: isPinned ? "black" : "white", color: isPinned ? "white" : "black" }}
                 onClick={e => DockedFrameRenderer.PinDoc(targetDoc, isPinned)}>
@@ -209,7 +209,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
     @computed
     get metadataButton() {
         const view0 = this.view0;
-        return !view0 ? (null) : <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Show metadata panel</div></React.Fragment>}>
+        return !view0 ? (null) : <Tooltip title={<><div className="dash-tooltip">Show metadata panel</div></>}>
             <div className="documentButtonBar-linkFlyout">
                 <Flyout anchorPoint={anchorPoints.LEFT_TOP}
                     content={<MetadataEntryMenu docs={this.props.views().filter(dv => dv).map(dv => dv!.props.Document)} suggestWithFunction />  /* tfs: @bcz This might need to be the data document? */}>
@@ -258,7 +258,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
         Array.from(Object.values(Templates.TemplateList)).map(template =>
             templates.set(template, views.reduce((checked, doc) => checked || doc?.props.Document["_show" + template.Name] ? true : false, false as boolean)));
         return !view0 ? (null) :
-            <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Tap: Customize layout.  Drag: Create alias</div></React.Fragment>}>
+            <Tooltip title={<><div className="dash-tooltip">Tap: Customize layout.  Drag: Create alias</div></>}>
                 <div className="documentButtonBar-linkFlyout" ref={this._dragRef}>
                     <Flyout anchorPoint={anchorPoints.LEFT_TOP} onOpen={action(() => this._aliasDown = true)} onClose={action(() => this._aliasDown = false)}
                         content={!this._aliasDown ? (null) : <TemplateMenu docViews={views.filter(v => v).map(v => v as DocumentView)} templates={templates} />}>
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 2fd017f7b..376b1d46b 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -81,6 +81,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         return SelectionManager.SelectedDocuments().reduce((bounds, documentView) => {
             if (documentView.props.renderDepth === 0 ||
                 documentView.props.treeViewDoc ||
+                !documentView.ContentDiv ||
                 Doc.AreProtosEqual(documentView.props.Document, Doc.UserDoc())) {
                 return bounds;
             }
@@ -88,7 +89,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             var [sptX, sptY] = transform.transformPoint(0, 0);
             let [bptX, bptY] = transform.transformPoint(documentView.props.PanelWidth(), documentView.props.PanelHeight());
             if (documentView.props.Document.type === DocumentType.LINK) {
-                const docuBox = documentView.ContentDiv!.getElementsByClassName("linkAnchorBox-cont");
+                const docuBox = documentView.ContentDiv.getElementsByClassName("linkAnchorBox-cont");
                 if (docuBox.length) {
                     const rect = docuBox[0].getBoundingClientRect();
                     sptX = rect.left;
@@ -544,11 +545,11 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         }
         const minimal = bounds.r - bounds.x < 100 ? true : false;
         const maximizeIcon = minimal ? (
-            <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Show context menu</div></React.Fragment>} placement="top">
+            <Tooltip title={<><div className="dash-tooltip">Show context menu</div></>} placement="top">
                 <div className="documentDecorations-contextMenu" onPointerDown={this.onSettingsDown}>
                     <FontAwesomeIcon size="lg" icon="cog" />
                 </div></Tooltip>) : (
-                <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Iconify</div></React.Fragment>} placement="top">
+                <Tooltip title={<><div className="dash-tooltip">Iconify</div></>} placement="top">
                     <div className="documentDecorations-minimizeButton" onClick={this.onCloseClick}>
                         {/* Currently, this is set to be enabled if there is no ink selected. It might be interesting to think about minimizing ink if it's useful? -syip2*/}
                         <FontAwesomeIcon className="documentdecorations-times" icon={faTimes} size="lg" />
@@ -572,7 +573,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 </div>}
             </> :
             <>
-                {minimal ? (null) : <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Show context menu</div></React.Fragment>} placement="top"><div className="documentDecorations-contextMenu" key="menu" onPointerDown={this.onSettingsDown}>
+                {minimal ? (null) : <Tooltip title={<><div className="dash-tooltip">Show context menu</div></>} placement="top"><div className="documentDecorations-contextMenu" key="menu" onPointerDown={this.onSettingsDown}>
                     <FontAwesomeIcon size="lg" icon="cog" />
                 </div></Tooltip>}
                 <div className="documentDecorations-title" key="title" onPointerDown={this.onTitleDown} >
@@ -611,11 +612,11 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                     {maximizeIcon}
                     {titleArea}
                     {SelectionManager.SelectedDocuments().length !== 1 || seldoc.Document.type === DocumentType.INK ? (null) :
-                        <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{`${seldoc.finalLayoutKey.includes("icon") ? "De" : ""}Iconify Document`}</div></React.Fragment>} placement="top">
+                        <Tooltip title={<><div className="dash-tooltip">{`${seldoc.finalLayoutKey.includes("icon") ? "De" : ""}Iconify Document`}</div></>} placement="top">
                             <div className="documentDecorations-iconifyButton" onPointerDown={this.onIconifyDown}>
                                 {"_"}
                             </div></Tooltip>}
-                    <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Open Document In Tab</div></React.Fragment>} placement="top"><div className="documentDecorations-closeButton" onPointerDown={this.onMaximizeDown}>
+                    <Tooltip title={<><div className="dash-tooltip">Open Document In Tab</div></>} placement="top"><div className="documentDecorations-closeButton" onPointerDown={this.onMaximizeDown}>
                         {SelectionManager.SelectedDocuments().length === 1 ? DocumentDecorations.DocumentIcon(StrCast(seldoc.props.Document.layout, "...")) : "..."}
                     </div></Tooltip>
                     <div id="documentDecorations-rotation" className="documentDecorations-rotation"
@@ -638,7 +639,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                     <div id="documentDecorations-bottomRightResizer" className="documentDecorations-resizer"
                         onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                     {seldoc.props.renderDepth <= 1 || !seldoc.props.ContainingCollectionView ? (null) :
-                        <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>tap to select containing document</div></React.Fragment>} placement="top">
+                        <Tooltip title={<><div className="dash-tooltip">tap to select containing document</div></>} placement="top">
                             <div id="documentDecorations-levelSelector" className="documentDecorations-selector"
                                 onPointerDown={this.onSelectorUp} onContextMenu={e => e.preventDefault()}>
                                 <FontAwesomeIcon className="documentdecorations-times" icon={faArrowAltCircleUp} size="lg" />
diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss
index 5b142ffda..e1ddbc533 100644
--- a/src/client/views/MainView.scss
+++ b/src/client/views/MainView.scss
@@ -1,6 +1,10 @@
 @import "globalCssVariables";
 @import "nodeModuleOverrides";
 
+.dash-tooltip {
+    font-size: 11px;
+    padding: 2px;
+}
 
 .mainView-tabButtons {
     position: relative;
diff --git a/src/client/views/collections/CollectionLinearView.tsx b/src/client/views/collections/CollectionLinearView.tsx
index 319cca70f..407524353 100644
--- a/src/client/views/collections/CollectionLinearView.tsx
+++ b/src/client/views/collections/CollectionLinearView.tsx
@@ -124,7 +124,7 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
 
         return <div className="collectionLinearView-outer">
             <div className="collectionLinearView" ref={this.createDashEventsTarget} >
-                <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{BoolCast(this.props.Document.linearViewIsExpanded) ? "Close menu" : "Open menu"}</div></React.Fragment>} placement="top">
+                <Tooltip title={<><div className="dash-tooltip">{BoolCast(this.props.Document.linearViewIsExpanded) ? "Close menu" : "Open menu"}</div></>} placement="top">
                     {menuOpener}
                 </Tooltip>
                 <input id={`${guid}`} type="checkbox" checked={BoolCast(this.props.Document.linearViewIsExpanded)} ref={this.addMenuToggle}
@@ -176,18 +176,20 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
                 }}
                     onPointerDown={e => e.stopPropagation()} >
                     <span className="bottomPopup-text" >
-                        Creating link from: {DocumentLinksButton.StartLink.title} </span>
+                        Creating link from: {DocumentLinksButton.StartLink.title}
+                    </span>
 
-                    <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{LinkDescriptionPopup.showDescriptions ? "Turn off description pop-up" :
-                        "Turn on description pop-up"} </div></React.Fragment>} placement="top">
-                        <span className="bottomPopup-descriptions" onClick={this.changeDescriptionSetting}
-                        > Labels: {LinkDescriptionPopup.showDescriptions ? LinkDescriptionPopup.showDescriptions : "ON"}
+                    <Tooltip title={<><div className="dash-tooltip">{LinkDescriptionPopup.showDescriptions ? "Turn off description pop-up" :
+                        "Turn on description pop-up"} </div></>} placement="top">
+                        <span className="bottomPopup-descriptions" onClick={this.changeDescriptionSetting}>
+                            Labels: {LinkDescriptionPopup.showDescriptions ? LinkDescriptionPopup.showDescriptions : "ON"}
                         </span>
                     </Tooltip>
 
-                    <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Exit link clicking mode </div></React.Fragment>} placement="top">
-                        <span className="bottomPopup-exit" onClick={this.exitLongLinks}
-                        >Clear</span>
+                    <Tooltip title={<><div className="dash-tooltip">Exit link clicking mode </div></>} placement="top">
+                        <span className="bottomPopup-exit" onClick={this.exitLongLinks}>
+                            Clear
+                        </span>
                     </Tooltip>
 
                     {/* <FontAwesomeIcon icon="times-circle" size="lg" style={{ color: "red" }}
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 827c3e299..0696b93db 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -38,12 +38,13 @@ export default class CollectionMenu extends AntimodeMenu {
     }
 
     render() {
-        return this.getElement([
-            !this.SelectedCollection ? <></> : <CollectionViewBaseChrome CollectionView={this.SelectedCollection} type={StrCast(this.SelectedCollection.props.Document._viewType) as CollectionViewType} />,
-            <button className="antimodeMenu-button" key="pin menu" title="Pin menu" onClick={this.toggleMenuPin} style={{ backgroundColor: "#121721" }}>
-                <FontAwesomeIcon icon="thumbtack" size="lg" style={{ transitionProperty: "transform", transitionDuration: "0.1s", transform: `rotate(${this.Pinned ? 45 : 0}deg)` }} />
-            </button>
-        ]);
+        const button = <button className="antimodeMenu-button" key="pin menu" title="Pin menu" onClick={this.toggleMenuPin} style={{ backgroundColor: "#121721" }}>
+            <FontAwesomeIcon icon="thumbtack" size="lg" style={{ transitionProperty: "transform", transitionDuration: "0.1s", transform: `rotate(${this.Pinned ? 45 : 0}deg)` }} />
+        </button>;
+
+        return this.getElement(!this.SelectedCollection ? [button] :
+            [<CollectionViewBaseChrome key="chrome" CollectionView={this.SelectedCollection} type={StrCast(this.SelectedCollection.props.Document._viewType) as CollectionViewType} />,
+            button]);
     }
 }
 
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index c1a6b5b0d..c1da23470 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -142,6 +142,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
                     const context = Cast(doc.context, Doc, null);
                     if (context && (context.type === DocumentType.VID || context.type === DocumentType.WEB || context.type === DocumentType.PDF || context.type === DocumentType.IMG)) {
                         const pushpin = Docs.Create.FontIconDocument({
+                            title: "pushpin",
                             icon: "map-pin", x: Cast(doc.x, "number", null), y: Cast(doc.y, "number", null), _backgroundColor: "#0000003d", color: "#ACCEF7",
                             _width: 15, _height: 15, _xPadding: 0, isLinkButton: true, displayTimecode: Cast(doc.displayTimecode, "number", null)
                         });
@@ -150,8 +151,6 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
                         Doc.SetInPlace(doc, "annotationOn", undefined, true);
                         Doc.AddDocToList(context, Doc.LayoutFieldKey(context) + "-annotations", pushpin);
                         const pushpinLink = DocUtils.MakeLink({ doc: pushpin }, { doc: doc }, "pushpin", "");
-                        const first = DocListCast(pushpin.links).find(d => d instanceof Doc);
-                        first && (first.hidden = true);
                         doc.displayTimecode = undefined;
                     }
                     doc.context = this.props.Document;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
index dea936113..0933d525a 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
@@ -29,13 +29,13 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
     componentDidMount() {
         this._anchorDisposer = reaction(() => [this.props.A.props.ScreenToLocalTransform(), this.props.B.props.ScreenToLocalTransform(), this.props.A.isSelected() || Doc.IsBrushed(this.props.A.props.Document), this.props.A.isSelected() || Doc.IsBrushed(this.props.A.props.Document)],
             action(() => {
-                if (SnappingManager.GetIsDragging()) return;
+                if (SnappingManager.GetIsDragging() || !this.props.A.ContentDiv || !this.props.B.ContentDiv) return;
                 setTimeout(action(() => this._opacity = 1), 0); // since the render code depends on querying the Dom through getBoudndingClientRect, we need to delay triggering render()
                 setTimeout(action(() => (!this.props.LinkDocs.length || !this.props.LinkDocs[0].linkDisplay) && (this._opacity = 0.05)), 750); // this will unhighlight the link line.
-                const acont = this.props.A.props.Document.type === DocumentType.LINK ? this.props.A.ContentDiv!.getElementsByClassName("linkAnchorBox-cont") : [];
-                const bcont = this.props.B.props.Document.type === DocumentType.LINK ? this.props.B.ContentDiv!.getElementsByClassName("linkAnchorBox-cont") : [];
-                const adiv = (acont.length ? acont[0] : this.props.A.ContentDiv!);
-                const bdiv = (bcont.length ? bcont[0] : this.props.B.ContentDiv!);
+                const acont = this.props.A.props.Document.type === DocumentType.LINK ? this.props.A.ContentDiv.getElementsByClassName("linkAnchorBox-cont") : [];
+                const bcont = this.props.B.props.Document.type === DocumentType.LINK ? this.props.B.ContentDiv.getElementsByClassName("linkAnchorBox-cont") : [];
+                const adiv = (acont.length ? acont[0] : this.props.A.ContentDiv);
+                const bdiv = (bcont.length ? bcont[0] : this.props.B.ContentDiv);
                 const a = adiv.getBoundingClientRect();
                 const b = bdiv.getBoundingClientRect();
                 const abounds = adiv.parentElement!.getBoundingClientRect();
@@ -103,7 +103,7 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
 
 
     render() {
-        if (SnappingManager.GetIsDragging() || !this.props.LinkDocs.length) return null;
+        if (SnappingManager.GetIsDragging() || !this.props.A.ContentDiv || !this.props.B.ContentDiv || !this.props.LinkDocs.length) return (null);
         this.props.A.props.ScreenToLocalTransform().transform(this.props.B.props.ScreenToLocalTransform());
         const acont = this.props.A.ContentDiv!.getElementsByClassName("linkAnchorBox-cont");
         const bcont = this.props.B.ContentDiv!.getElementsByClassName("linkAnchorBox-cont");
diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx
index 1cc981d42..ed2bea722 100644
--- a/src/client/views/linking/LinkEditor.tsx
+++ b/src/client/views/linking/LinkEditor.tsx
@@ -288,7 +288,6 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
 
     @observable description = StrCast(LinkManager.currentLink?.description);
     @observable openDropdown: boolean = false;
-    @observable followBehavior = this.props.linkDoc.follow ? this.props.linkDoc.follow : "Default";
     @observable showInfo: boolean = false;
     @computed get infoIcon() { if (this.showInfo) { return "chevron-up"; } return "chevron-down"; }
     @observable private buttonColor: string = "black";
@@ -364,8 +363,7 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
     @action
     changeFollowBehavior = (follow: string) => {
         this.openDropdown = false;
-        this.followBehavior = follow;
-        this.props.linkDoc.follow = follow;
+        Doc.GetProto(this.props.linkDoc).followLinkLocation = follow;
     }
 
     @computed
@@ -376,7 +374,7 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
             <div className="linkEditor-followingDropdown-dropdown">
                 <div className="linkEditor-followingDropdown-header"
                     onPointerDown={this.changeDropdown}>
-                    {this.followBehavior}
+                    {StrCast(this.props.linkDoc.followLinkLocation, "Default")}
                     <FontAwesomeIcon className="linkEditor-followingDropdown-icon"
                         icon={this.openDropdown ? "chevron-up" : "chevron-down"}
                         size={"lg"} />
@@ -388,11 +386,11 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
                         Default
                         </div>
                     <div className="linkEditor-followingDropdown-option"
-                        onPointerDown={() => this.changeFollowBehavior("Always open in right tab")}>
+                        onPointerDown={() => this.changeFollowBehavior("onRight")}>
                         Always open in right tab
                         </div>
                     <div className="linkEditor-followingDropdown-option"
-                        onPointerDown={() => this.changeFollowBehavior("Always open in new tab")}>
+                        onPointerDown={() => this.changeFollowBehavior("inTab")}>
                         Always open in new tab
                         </div>
                 </div>
@@ -416,7 +414,7 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
         return !destination ? (null) : (
             <div className="linkEditor">
                 <div className="linkEditor-info">
-                    <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Return to link menu</div></React.Fragment>} placement="top">
+                    <Tooltip title={<><div className="dash-tooltip">Return to link menu</div></>} placement="top">
                         <button className="linkEditor-button-back"
                             style={{ display: this.props.hideback ? "none" : "" }}
                             onClick={this.props.showLinks}>
@@ -426,7 +424,7 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
                         destination.proto?.title ?? destination.title ?? "untitled"}</b></p>
                     {/* <button className="linkEditor-button" onPointerDown={() => this.deleteLink()} title="Delete link">
                         <FontAwesomeIcon icon="trash" size="sm" /></button> */}
-                    <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Show more link information</div></React.Fragment>} placement="top">
+                    <Tooltip title={<><div className="dash-tooltip">Show more link information</div></>} placement="top">
                         <div className="linkEditor-downArrow"><FontAwesomeIcon className="button" icon={this.infoIcon} size="lg" onPointerDown={this.changeInfo} /></div>
                     </Tooltip>
                 </div>
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 6782f625b..0e847632b 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -16,7 +16,6 @@ import { DocumentView } from '../nodes/DocumentView';
 import { DocumentLinksButton } from '../nodes/DocumentLinksButton';
 import { LinkDocPreview } from '../nodes/LinkDocPreview';
 import { Tooltip } from '@material-ui/core';
-import { RichTextField } from '../../../fields/RichTextField';
 import { DocumentType } from '../../documents/DocumentTypes';
 library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp, faPencilAlt, faEyeSlash);
 
@@ -157,14 +156,8 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
         DocumentLinksButton.EditLink = undefined;
         LinkDocPreview.LinkInfo = undefined;
 
-        if (this.props.linkDoc.follow) {
-            if (this.props.linkDoc.follow === "Default") {
-                DocumentManager.Instance.FollowLink(this.props.linkDoc, this.props.sourceDoc, doc => this.props.addDocTab(doc, "onRight"), false);
-            } else if (this.props.linkDoc.follow === "Always open in right tab") {
-                this.props.addDocTab(this.props.destinationDoc, "onRight");
-            } else if (this.props.linkDoc.follow === "Always open in new tab") {
-                this.props.addDocTab(this.props.destinationDoc, "inTab");
-            }
+        if (this.props.linkDoc.followLinkLocation && this.props.linkDoc.followLinkLocation !== "Default") {
+            this.props.addDocTab(this.props.destinationDoc, StrCast(this.props.linkDoc.followLinkLocation));
         } else {
             DocumentManager.Instance.FollowLink(this.props.linkDoc, this.props.sourceDoc, doc => this.props.addDocTab(doc, "onRight"), false);
         }
@@ -221,8 +214,6 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
                 StrCast(this.props.linkDoc.storedText).substr(0, 18)
                 : this.props.linkDoc.storedText : undefined : undefined;
 
-        const showTitle = this.props.linkDoc.hidden ? "Show link" : "Hide link";
-
         return (
             <div className="linkMenu-item">
                 <div className={canExpand ? "linkMenu-item-content expand-three" : "linkMenu-item-content expand-two"}>
@@ -255,16 +246,16 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
                             {canExpand ? <div title="Show more" className="button" onPointerDown={e => this.toggleShowMore(e)}>
                                 <FontAwesomeIcon className="fa-icon" icon={this._showMore ? "chevron-up" : "chevron-down"} size="sm" /></div> : <></>}
 
-                            <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{showTitle}</div></React.Fragment>}>
+                            <Tooltip title={<><div className="dash-tooltip">{this.props.linkDoc.hidden ? "Show link" : "Hide link"}</div></>}>
                                 <div className="button" ref={this._editRef} onPointerDown={this.showLink}>
                                     <FontAwesomeIcon className="fa-icon" icon={eyeIcon} size="sm" /></div>
                             </Tooltip>
 
-                            <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Edit Link</div></React.Fragment>}>
+                            <Tooltip title={<><div className="dash-tooltip">Edit Link</div></>}>
                                 <div className="button" ref={this._editRef} onPointerDown={this.onEdit}>
                                     <FontAwesomeIcon className="fa-icon" icon="edit" size="sm" /></div>
                             </Tooltip>
-                            <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Delete Link</div></React.Fragment>}>
+                            <Tooltip title={<><div className="dash-tooltip">Delete Link</div></>}>
                                 <div className="button" onPointerDown={this.deleteLink}>
                                     <FontAwesomeIcon className="fa-icon" icon="trash" size="sm" /></div>
                             </Tooltip>
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 01c068966..bbef48e44 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -134,7 +134,6 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
                 if (DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View) {
                     const linkDoc = DocUtils.MakeLink({ doc: DocumentLinksButton.StartLink.props.Document }, { doc: this.props.View.props.Document }, "long drag");
                     LinkManager.currentLink = linkDoc;
-                    linkDoc ? linkDoc.hidden = true : null;
 
                     runInAction(() => {
                         if (linkDoc) {
@@ -213,10 +212,10 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
 
         return (!links.length) && !this.props.AlwaysOn ? (null) :
             this.props.InMenu ?
-                <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{title}</div></React.Fragment>}>
+                <Tooltip title={<><div className="dash-tooltip">{title}</div></>}>
                     {linkButton}
                 </Tooltip> : !!!DocumentLinksButton.EditLink ?
-                    <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{title}</div></React.Fragment>}>
+                    <Tooltip title={<><div className="dash-tooltip">{title}</div></>}>
                         {linkButton}
                     </Tooltip> :
                     linkButton;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index a6771443a..c0a8b3a59 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -589,16 +589,12 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
 
     @undoBatch
     toggleLinkButtonBehavior = (): void => {
+        this.Document.ignoreClick = false;
         if (this.Document.isLinkButton || this.onClickHandler || this.Document.ignoreClick) {
             this.Document.isLinkButton = false;
-            const first = DocListCast(this.Document.links).find(d => d instanceof Doc);
-            first && (first.hidden = false);
-            this.Document.ignoreClick = false;
             this.Document.onClick = this.layoutDoc.onClick = undefined;
         } else {
             this.Document.isLinkButton = true;
-            const first = DocListCast(this.Document.links).find(d => d instanceof Doc);
-            first && (first.hidden = true);
             this.Document.followLinkZoom = false;
             this.Document.followLinkLocation = undefined;
         }
@@ -606,14 +602,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
 
     @undoBatch
     toggleFollowInPlace = (): void => {
+        this.Document.ignoreClick = false;
+        this.Document.isLinkButton = !this.Document.isLinkButton;
         if (this.Document.isLinkButton) {
-            this.Document.isLinkButton = false;
-            const first = DocListCast(this.Document.links).find(d => d instanceof Doc);
-            first && (first.hidden = false);
-        } else {
-            this.Document.isLinkButton = true;
-            const first = DocListCast(this.Document.links).find(d => d instanceof Doc);
-            first && (first.hidden = true);
             this.Document.followLinkZoom = true;
             this.Document.followLinkLocation = "inPlace";
         }
@@ -621,15 +612,10 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
 
     @undoBatch
     toggleFollowOnRight = (): void => {
+        this.Document.ignoreClick = false;
+        this.Document.isLinkButton = !this.Document.isLinkButton;
         if (this.Document.isLinkButton) {
-            this.Document.isLinkButton = false;
-            const first = DocListCast(this.Document.links).find(d => d instanceof Doc);
-            first && (first.hidden = false);
-        } else {
-            this.Document.isLinkButton = true;
             this.Document.followLinkZoom = false;
-            const first = DocListCast(this.Document.links).find(d => d instanceof Doc);
-            first && (first.hidden = true);
             this.Document.followLinkLocation = "onRight";
         }
     }
@@ -643,7 +629,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         }
         const makeLink = action((linkDoc: Doc) => {
             LinkManager.currentLink = linkDoc;
-            linkDoc.hidden = true;
 
             LinkCreatedBox.popupX = de.x;
             LinkCreatedBox.popupY = de.y - 33;
diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
index c98b5eac1..3687d5513 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
@@ -270,14 +270,14 @@ export class FormattedTextBoxComment {
                                         </div>
                                         <div className="wrapper" style={{ float: "right" }}>
 
-                                            <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Delete Link</div></React.Fragment>} placement="top">
+                                            <Tooltip title={<><div className="dash-tooltip">Delete Link</div></>} placement="top">
                                                 <div className="FormattedTextBoxComment-button"
                                                     ref={(r) => this._deleteRef = r}>
                                                     <FontAwesomeIcon className="FormattedTextBoxComment-fa-icon" icon="trash" color="white"
                                                         size="sm" /></div>
                                             </Tooltip>
 
-                                            <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Follow Link</div></React.Fragment>} placement="top">
+                                            <Tooltip title={<><div className="dash-tooltip">Follow Link</div></>} placement="top">
                                                 <div className="FormattedTextBoxComment-button"
                                                     ref={(r) => this._followRef = r}>
                                                     <FontAwesomeIcon className="FormattedTextBoxComment-fa-icon" icon="arrow-right" color="white"
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index d0e6f3b37..63f6fdc54 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -24,6 +24,7 @@ import "./RichTextMenu.scss";
 import { schema } from "./schema_rts";
 import { TraceMobx } from "../../../../fields/util";
 import { UndoManager } from "../../../util/UndoManager";
+import { Tooltip } from "@material-ui/core";
 const { toggleMark } = require("prosemirror-commands");
 
 library.add(faBold, faItalic, faChevronLeft, faUnderline, faStrikethrough, faSuperscript, faSubscript, faOutdent, faIndent, faHandPointLeft, faHandPointRight, faEyeDropper, faCaretDown, faPalette, faHighlighter, faLink, faPaintRoller);
@@ -357,9 +358,11 @@ export default class RichTextMenu extends AntimodeMenu {
         }
 
         return (
-            <button className={"antimodeMenu-button" + (isActive ? " active" : "")} key={title} title={title} onPointerDown={onClick}>
-                <FontAwesomeIcon icon={faIcon as IconProp} size="lg" />
-            </button>
+            <Tooltip title={<div className="dash-tooltip">{title}</div>} key={title} placement="bottom">
+                <button className={"antimodeMenu-button" + (isActive ? " active" : "")} onPointerDown={onClick}>
+                    <FontAwesomeIcon icon={faIcon as IconProp} size="lg" />
+                </button>
+            </Tooltip>
         );
     }
 
@@ -388,7 +391,9 @@ export default class RichTextMenu extends AntimodeMenu {
                 }
             });
         }
-        return <select onChange={onChange} value={activeOption} key={key}>{items}</select>;
+        return <Tooltip key={key} title={<div className="dash-tooltip">{key}</div>} placement="bottom">
+            <select onChange={onChange} value={activeOption}>{items}</select>
+        </Tooltip>;
     }
 
     createNodesDropdown(activeMap: string, options: { node: NodeType | any | null, title: string, label: string, command: (node: NodeType | any) => void, hidden?: boolean, style?: {} }[], key: string, setter: (val: string) => {}): JSX.Element {
@@ -412,7 +417,10 @@ export default class RichTextMenu extends AntimodeMenu {
                 }
             });
         }
-        return <select value={activeOption} onChange={e => onChange(e.target.value)} key={key}>{items}</select>;
+
+        return <Tooltip key={key} title={<div className="dash-tooltip">{key}</div>} placement="bottom">
+            <select value={activeOption} onChange={e => onChange(e.target.value)}>{items}</select>
+        </Tooltip>;
     }
 
     changeFontSize = (mark: Mark, view: EditorView) => {
@@ -595,10 +603,11 @@ export default class RichTextMenu extends AntimodeMenu {
             label = "No marks are currently stored";
         }
 
-        const button =
-            <button className="antimodeMenu-button" title="" onPointerDown={onBrushClick} style={this.brushMarks?.size > 0 ? { backgroundColor: "121212" } : {}}>
+        const button = <Tooltip title={<div className="dash-tooltip">style brush</div>} placement="bottom">
+            <button className="antimodeMenu-button" onPointerDown={onBrushClick} style={this.brushMarks?.size > 0 ? { backgroundColor: "121212" } : {}}>
                 <FontAwesomeIcon icon="paint-roller" size="lg" style={{ transitionProperty: "transform", transitionDuration: "0.1s", transform: `rotate(${this.brushMarks?.size > 0 ? 45 : 0}deg)` }} />
-            </button>;
+            </button>
+        </Tooltip>;
 
         const dropdownContent =
             <div className="dropdown">
@@ -667,11 +676,12 @@ export default class RichTextMenu extends AntimodeMenu {
             self.TextView.EditorView!.focus();
         }
 
-        const button =
-            <button className="antimodeMenu-button color-preview-button" title="" onPointerDown={onColorClick}>
+        const button = <Tooltip title={<div className="dash-tooltip">set font color</div>} placement="bottom">
+            <button className="antimodeMenu-button color-preview-button" onPointerDown={onColorClick}>
                 <FontAwesomeIcon icon="palette" size="lg" />
                 <div className="color-preview" style={{ backgroundColor: this.activeFontColor }}></div>
-            </button>;
+            </button>
+        </Tooltip>;
 
         const dropdownContent =
             <div className="dropdown" >
@@ -720,11 +730,12 @@ export default class RichTextMenu extends AntimodeMenu {
             UndoManager.RunInBatch(() => self.view && self.insertHighlight(self.activeHighlightColor, self.view.state, self.view.dispatch), "rt highlighter");
         }
 
-        const button =
-            <button className="antimodeMenu-button color-preview-button" title="" key="highilghter-button" onPointerDown={onHighlightClick}>
+        const button = <Tooltip title={<div className="dash-tooltip">set highlight color</div>} placement="bottom">
+            <button className="antimodeMenu-button color-preview-button" key="highilghter-button" onPointerDown={onHighlightClick}>
                 <FontAwesomeIcon icon="highlighter" size="lg" />
                 <div className="color-preview" style={{ backgroundColor: this.activeHighlightColor }}></div>
-            </button>;
+            </button>
+        </Tooltip>;
 
         const dropdownContent =
             <div className="dropdown">
@@ -763,7 +774,9 @@ export default class RichTextMenu extends AntimodeMenu {
 
         const link = this.currentLink ? this.currentLink : "";
 
-        const button = <FontAwesomeIcon icon="link" size="lg" />;
+        const button = <Tooltip title={<div className="dash-tooltip">set hyperlink</div>} placement="bottom">
+            <div><FontAwesomeIcon icon="link" size="lg" /> </div>
+        </Tooltip>;
 
         const dropdownContent =
             <div className="dropdown link-menu">
@@ -774,9 +787,7 @@ export default class RichTextMenu extends AntimodeMenu {
                 <button className="remove-button" onPointerDown={e => this.deleteLink()}>Remove link</button>
             </div>;
 
-        return (
-            <ButtonDropdown view={this.view} key={"link button"} button={button} dropdownContent={dropdownContent} openDropdownOnButton={true} />
-        );
+        return <ButtonDropdown view={this.view} key={"link button"} button={button} dropdownContent={dropdownContent} openDropdownOnButton={true} />;
     }
 
     async getTextLinkTargetTitle() {
@@ -935,7 +946,7 @@ export default class RichTextMenu extends AntimodeMenu {
                 {[this.createMarksDropdown(this.activeFontSize, this.fontSizeOptions, "font size", action((val: string) => this.activeFontSize = val)),
                 this.createMarksDropdown(this.activeFontFamily, this.fontFamilyOptions, "font family", action((val: string) => this.activeFontFamily = val)),
                 <div className="richTextMenu-divider" key="divider 4" />,
-                this.createNodesDropdown(this.activeListType, this.listTypeOptions, "nodes", action((val: string) => this.activeListType = val)),
+                this.createNodesDropdown(this.activeListType, this.listTypeOptions, "list type", action((val: string) => this.activeListType = val)),
                 this.createButton("sort-amount-down", "Summarize", undefined, this.insertSummarizer),
                 this.createButton("quote-left", "Blockquote", undefined, this.insertBlockquote),
                 this.createButton("minus", "Horizontal Rule", undefined, this.insertHorizontalRule),
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 4e5fdbfbb..56212a773 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -637,7 +637,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
 
     @action
     onZoomWheel = (e: React.WheelEvent) => {
-        if (this.active()) {
+        if (this.active(true)) {
             e.stopPropagation();
             if (e.ctrlKey) {
                 const curScale = Number(this._pdfViewer.currentScaleValue);
-- 
cgit v1.2.3-70-g09d2


From f11af49cb5c472cab7960e00198768e729e1395f Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Thu, 16 Jul 2020 21:37:55 -0400
Subject: coerced documents in stacking views to display with a mininum height
 of 20.  fixed selection with marquee to choose documents in the collection
 view, not other aliases.

---
 src/client/views/DocumentDecorations.tsx                                | 1 +
 src/client/views/collections/CollectionStackingView.tsx                 | 2 +-
 .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx     | 2 +-
 3 files changed, 3 insertions(+), 2 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 376b1d46b..35c040f86 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -433,6 +433,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 let nheight = doc._nativeHeight || 0;
                 const width = (doc._width || 0);
                 let height = (doc._height || (nheight / nwidth * width));
+                height = !height || isNaN(height) ? 20 : height;
                 const scale = element.props.ScreenToLocalTransform().Scale * element.props.ContentScaling();
                 if (nwidth && nheight) {
                     if (nwidth / nheight !== width / height) {
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 838e1f664..bf7c51f2c 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -249,7 +249,7 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument)
             return wid * aspect;
         }
         return layoutDoc._fitWidth ? !nh ? this.props.PanelHeight() - 2 * this.yMargin :
-            Math.min(wid * NumCast(layoutDoc.scrollHeight, nh) / (nw || 1), this.props.PanelHeight() - 2 * this.yMargin) : layoutDoc[HeightSym]();
+            Math.min(wid * NumCast(layoutDoc.scrollHeight, nh) / (nw || 1), this.props.PanelHeight() - 2 * this.yMargin) : Math.max(20, layoutDoc[HeightSym]());
     }
 
     columnDividerDown = (e: React.PointerEvent) => {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 0ba860588..922cb17fe 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -186,7 +186,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
 
     private selectDocuments = (docs: Doc[]) => {
         SelectionManager.DeselectAll();
-        docs.map(doc => DocumentManager.Instance.getDocumentView(doc)).map(dv => dv && SelectionManager.SelectDoc(dv, true));
+        docs.map(doc => DocumentManager.Instance.getDocumentView(doc, this.props.CollectionView)).map(dv => dv && SelectionManager.SelectDoc(dv, true));
     }
     public isCurrent(doc: Doc) { return (Math.abs(NumCast(doc.displayTimecode, -1) - NumCast(this.Document.currentTimecode, -1)) < 1.5 || NumCast(doc.displayTimecode, -1) === -1); }
 
-- 
cgit v1.2.3-70-g09d2

