From 8bbe55468f2ea222ed8c4dc513e65707c8835737 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 7 Dec 2020 17:15:09 -0500
Subject: got rid of LibraryPath.  Fixed collectionFreeFormDocViews to use pres
 Effects whenever doc is selected

---
 src/client/views/pdf/PDFViewer.tsx | 1 -
 1 file changed, 1 deletion(-)

(limited to 'src/client/views/pdf/PDFViewer.tsx')

diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 48c7b1762..9b689eb6b 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -736,7 +736,6 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
                 transform: `scale(${this._zoomed})`
             }}>
             <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit}
-                LibraryPath={this.props.ContainingCollectionView?.props.LibraryPath ?? emptyPath}
                 annotationsKey={this.annotationKey}
                 setPreviewCursor={this.setPreviewCursor}
                 PanelHeight={this.panelWidth}
-- 
cgit v1.2.3-70-g09d2


From 30338491c7b3cbba852931c76774f6bfd44d4060 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 10 Dec 2020 12:54:41 -0500
Subject: removed annotationsKey prop in favor of reusing fieldKey.  Fixed web
 pages to allow dash annotations again.

---
 src/client/views/MainView.tsx                              |  1 -
 src/client/views/TemplateMenu.tsx                          |  1 -
 src/client/views/collections/CollectionStackingView.tsx    |  4 ++--
 src/client/views/collections/CollectionSubView.tsx         | 14 ++++++--------
 src/client/views/collections/CollectionView.tsx            |  5 +----
 src/client/views/collections/TabDocView.tsx                |  1 -
 .../collectionFreeForm/CollectionFreeFormView.tsx          | 11 +++++------
 .../views/collections/collectionFreeForm/MarqueeView.tsx   |  2 +-
 src/client/views/nodes/FilterBox.tsx                       |  2 --
 src/client/views/nodes/ImageBox.tsx                        |  2 +-
 src/client/views/nodes/LinkBox.tsx                         |  1 -
 src/client/views/nodes/PresBox.tsx                         |  1 -
 src/client/views/nodes/ScreenshotBox.tsx                   |  1 -
 src/client/views/nodes/VideoBox.tsx                        |  2 +-
 src/client/views/nodes/WebBox.scss                         |  4 +++-
 src/client/views/nodes/WebBox.tsx                          |  2 +-
 src/client/views/nodes/formattedText/FormattedTextBox.tsx  | 13 ++++++++-----
 src/client/views/pdf/PDFViewer.tsx                         |  4 ++--
 src/client/views/search/SearchBox.tsx                      |  1 -
 19 files changed, 31 insertions(+), 41 deletions(-)

(limited to 'src/client/views/pdf/PDFViewer.tsx')

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 9b3d5c6ae..2705d2c34 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -456,7 +456,6 @@ export class MainView extends React.Component {
                     DataDoc={undefined}
                     fieldKey={"data"}
                     dropAction={"alias"}
-                    annotationsKey={""}
                     parentActive={returnFalse}
                     styleProvider={TabDocView.styleProvider}
                     rootSelected={returnTrue}
diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx
index 9c5c70c60..203274681 100644
--- a/src/client/views/TemplateMenu.tsx
+++ b/src/client/views/TemplateMenu.tsx
@@ -152,7 +152,6 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
                 PanelWidth={this.return100}
                 PanelHeight={this.return100}
                 treeViewHideHeaderFields={true}
-                annotationsKey={""}
                 dontRegisterView={true}
                 fieldKey={"data"}
                 moveDocument={returnFalse}
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 83ac138f5..058536f69 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -352,8 +352,8 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
                     this.observer = new _global.ResizeObserver(action((entries: any) => {
                         if (this.layoutDoc._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) {
                             const height = Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), Math.max(...this.refList.map(r => NumCast(Doc.Layout(doc)._viewScale, 1) * Number(getComputedStyle(r).height.replace("px", "")))));
-                            if (this.props.annotationsKey) {
-                                doc[this.props.annotationsKey + "-height"] = height;
+                            if (this.props.isAnnotationOverlay) {
+                                doc[this.props.fieldKey + "-height"] = height;
                             } else {
                                 Doc.Layout(doc)._height = height * NumCast(Doc.Layout(doc)._viewScale, 1);
                             }
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 592d6ab87..38e461e46 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -67,14 +67,14 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
             // sets the dataDoc's data field to an empty list if the data field is undefined - prevents issues with addonly
             // setTimeout changes it outside of the @computed section
             setTimeout(() => {
-                if (!this.dataDoc[this.props.annotationsKey || this.props.fieldKey]) this.dataDoc[this.props.annotationsKey || this.props.fieldKey] = new List<Doc>();
+                if (!this.dataDoc[this.props.fieldKey]) this.dataDoc[this.props.fieldKey] = new List<Doc>();
             }, 1000);
-            return this.dataDoc[this.props.annotationsKey || this.props.fieldKey];
+            return this.dataDoc[this.props.fieldKey];
         }
 
         get childLayoutPairs(): { layout: Doc; data: Doc; }[] {
             const { Document, DataDoc } = this.props;
-            const validPairs = this.childDocs.map(doc => Doc.GetLayoutDataDocPair(Document, !this.props.annotationsKey ? DataDoc : undefined, doc)).
+            const validPairs = this.childDocs.map(doc => Doc.GetLayoutDataDocPair(Document, !this.props.isAnnotationOverlay ? DataDoc : undefined, doc)).
                 filter(pair => {  // filter out any documents that have a proto that we don't have permissions to (which we determine by not having any keys
                     return pair.layout && (!pair.layout.proto || (pair.layout.proto instanceof Doc && GetEffectiveAcl(pair.layout.proto) !== AclPrivate));// Object.keys(pair.layout.proto).length));
                 });
@@ -84,12 +84,10 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
             return Cast(this.dataField, listSpec(Doc));
         }
         docFilters = () => {
-            return this.props.ignoreFilters ? [] :
-                [...this.props.docFilters(), ...Cast(this.props.Document._docFilters, listSpec("string"), [])];
+            return [...this.props.docFilters(), ...Cast(this.props.Document._docFilters, listSpec("string"), [])];
         }
         docRangeFilters = () => {
-            return this.props.ignoreFilters ? [] :
-                [...this.props.docRangeFilters(), ...Cast(this.props.Document._docRangeFilters, listSpec("string"), [])];
+            return [...this.props.docRangeFilters(), ...Cast(this.props.Document._docRangeFilters, listSpec("string"), [])];
         }
         searchFilterDocs = () => {
             return [...this.props.searchFilterDocs(), ...DocListCast(this.props.Document._searchFilterDocs)];
@@ -104,7 +102,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
                 // For example, if an image doc is rendered with a slide template, the template will try to render the data field as a collection.
                 // Since the data field is actually an image, we set the list of documents to the singleton of root document's proto which will be an image.
                 const rootDoc = Cast(this.props.Document.rootDocument, Doc, null);
-                rawdocs = rootDoc && !this.props.annotationsKey ? [Doc.GetProto(rootDoc)] : [];
+                rawdocs = rootDoc && !this.props.isAnnotationOverlay ? [Doc.GetProto(rootDoc)] : [];
             }
 
             const docs = rawdocs.filter(d => !(d instanceof Promise) && GetEffectiveAcl(Doc.GetProto(d)) !== AclPrivate).map(d => d as Doc);
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index af03e4ceb..511fc723d 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -63,8 +63,6 @@ export enum CollectionViewType {
 }
 export interface CollectionViewProps extends FieldViewProps {
     isAnnotationOverlay?: boolean;  // is the collection an annotation overlay (eg an overlay on an image/video/etc)
-    annotationsKey: string;    // which data field on the collection stores the collection of annotation documents
-    ignoreFilters?: boolean;
     layoutEngine?: () => string;
     parentActive: (outsideReaction: boolean) => boolean;
     filterAddDocument?: (doc: Doc | Doc[]) => boolean;  // allows a document that renders a Collection view to filter or modify any documents added to the collection (see PresBox for an example)
@@ -72,11 +70,11 @@ export interface CollectionViewProps extends FieldViewProps {
     setPreviewCursor?: (func: (x: number, y: number, drag: boolean) => void) => void;
 
     // property overrides for child documents
+    children?: never | (() => JSX.Element[]) | React.ReactNode;
     childDocuments?: Doc[]; // used to override the documents shown by the sub collection to an explicit list (see LinkBox)
     childOpacity?: () => number;
     childLayoutTemplate?: () => (Doc | undefined);// specify a layout Doc template to use for children of the collection
     childLayoutString?: string;
-    children?: never | (() => JSX.Element[]) | React.ReactNode;
     childFreezeDimensions?: boolean; // used by TimeView to coerce documents to treat their width height as their native width/height
     childIgnoreNativeSize?: boolean;
     childClickScript?: ScriptField;
@@ -387,7 +385,6 @@ export class CollectionView extends Touchable<CollectionViewProps> {
             childLayoutString: this.childLayoutString,
             ScreenToLocalTransform: this.screenToLocalTransform,
             CollectionView: this,
-            annotationsKey: ""
         };
         const boxShadow = Doc.UserDoc().renderStyle === "comic" || this.props.Document.treeViewOutlineMode || this.collectionViewType === CollectionViewType.Linear ? undefined :
             this.props.styleProvider?.(this.props.Document, this.props, "boxShadow");
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 3c1aaae47..fd50c6273 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -346,7 +346,6 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                     dropAction={undefined}
                     isSelected={returnFalse}
                     dontRegisterView={true}
-                    annotationsKey={""}
                     fieldKey={Doc.LayoutFieldKey(this._document!)}
                     bringToFront={emptyFunction}
                     rootSelected={returnTrue}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 0f466fc16..e09abd017 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -47,7 +47,6 @@ import { MarqueeOptionsMenu } from "./MarqueeOptionsMenu";
 import { MarqueeView } from "./MarqueeView";
 import React = require("react");
 import { CurrentUserUtils } from "../../../util/CurrentUserUtils";
-import { isUndefined } from "lodash";
 
 export const panZoomSchema = createSchema({
     _panX: "number",
@@ -950,7 +949,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
             newState.initializers![this.Document[Id]] = { panX: newPanX, panY: newPanY };
             HistoryUtil.pushState(newState);
 
-            if (DocListCast(this.dataDoc[this.props.annotationsKey || this.props.fieldKey]).includes(doc)) {
+            if (DocListCast(this.dataDoc[this.props.fieldKey]).includes(doc)) {
                 // glr: freeform transform speed can be set by adjusting presTransition field - needs a way of knowing when presentation is not active...
                 if (!doc.z) this.setPan(newPanX, newPanY, doc.focusSpeed || doc.focusSpeed === 0 ? `transform ${doc.focusSpeed}ms` : "transform 500ms", true); // docs that are floating in their collection can't be panned to from their collection -- need to propagate the pan to a parent freeform somehow
             }
@@ -1193,7 +1192,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
         this._layoutComputeReaction = reaction(() => this.doLayoutComputation,
             (elements) => this._layoutElements = elements || [],
             { fireImmediately: true, name: "doLayout" });
-        if (!this.props.annotationsKey) {
+        if (!this.props.isAnnotationOverlay) {
             this._boundsReaction = reaction(() => this.contentBounds,
                 bounds => (!this.fitToContent && this._layoutElements?.length) && setTimeout(() => {
                     const rbounds = Cast(this.Document._renderContentBounds, listSpec("number"), [0, 0, 0, 0]);
@@ -1291,7 +1290,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
     private thumbIdentifier?: number;
 
     onContextMenu = (e: React.MouseEvent) => {
-        if (this.props.annotationsKey || this.props.Document.annotationOn || !ContextMenu.Instance) return;
+        if (this.props.isAnnotationOverlay || this.props.Document.annotationOn || !ContextMenu.Instance) return;
 
         const appearance = ContextMenu.Instance.findByDescription("Appearance...");
         const appearanceItems = appearance && "subitems" in appearance ? appearance.subitems : [];
@@ -1527,7 +1526,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
 
 
     @computed get contentScaling() {
-        if (this.props.annotationsKey && !this.props.forceScaling) return 0;
+        if (this.props.isAnnotationOverlay && !this.props.forceScaling) return 0;
         const nw = returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.Document));
         const nh = returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.Document));
         const hscale = nh ? this.props.PanelHeight() / nh : 1;
@@ -1555,7 +1554,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
                 width: this.contentScaling ? `${100 / this.contentScaling}%` : "",
                 height: this.contentScaling ? `${100 / this.contentScaling}%` : this.isAnnotationOverlay ? (this.props.Document.scrollHeight ? this.Document.scrollHeight : "100%") : this.props.PanelHeight()
             }}>
-            {this.Document._freeformLOD && !this.props.active() && !this.props.isAnnotationOverlay && !this.props.annotationsKey && this.props.renderDepth > 0 ?
+            {this.Document._freeformLOD && !this.props.active() && !this.props.isAnnotationOverlay && this.props.renderDepth > 0 ?
                 this.placeholder : this.marqueeView}
             {!this.props.noOverlay ? <CollectionFreeFormOverlayView elements={this.elementFunc} /> : (null)}
 
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 39df606f7..52310d628 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -634,7 +634,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
 
     render() {
         return <div className="marqueeView"
-            style={{ overflow: !this.props.ContainingCollectionView && this.props.annotationsKey ? "visible" : StrCast(this.props.Document._overflow), cursor: MarqueeView.DragMarquee && this ? "crosshair" : "hand" }}
+            style={{ overflow: !this.props.ContainingCollectionView && this.props.isAnnotationOverlay ? "visible" : StrCast(this.props.Document._overflow), cursor: MarqueeView.DragMarquee && this ? "crosshair" : "hand" }}
             onDragOver={e => e.preventDefault()}
             onScroll={(e) => e.currentTarget.scrollTop = e.currentTarget.scrollLeft = 0} onClick={this.onClick} onPointerDown={this.onPointerDown}>
             {this._visible ? this.marqueeDiv : null}
diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx
index b90bf9eb1..ffe1684d4 100644
--- a/src/client/views/nodes/FilterBox.tsx
+++ b/src/client/views/nodes/FilterBox.tsx
@@ -208,8 +208,6 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
                     focus={returnFalse}
                     treeViewHideHeaderFields={true}
                     onCheckedClick={this.scriptField}
-                    ignoreFilters={true} // otherwise, the filters would filter themselves out of the tree view
-                    annotationsKey={""}
                     dontRegisterView={true}
                     styleProvider={this.filterBackground}
                     moveDocument={returnFalse}
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 1c1a13061..44df00709 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -417,7 +417,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps, ImageD
                 forceScaling={true}
                 PanelHeight={this.props.PanelHeight}
                 PanelWidth={this.props.PanelWidth}
-                annotationsKey={this.annotationKey}
+                fieldKey={this.annotationKey}
                 isAnnotationOverlay={true}
                 focus={this.props.focus}
                 isSelected={this.props.isSelected}
diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx
index 50ad884ca..b3fd13a77 100644
--- a/src/client/views/nodes/LinkBox.tsx
+++ b/src/client/views/nodes/LinkBox.tsx
@@ -23,7 +23,6 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps, LinkDocument>(
                 ChromeHeight={returnZero}
                 childDocuments={[this.dataDoc]}
                 treeViewSkipFields={Cast(this.props.Document.linkBoxExcludedKeys, listSpec("string"), null)}
-                annotationsKey={""}
                 dontRegisterView={true}
                 renderDepth={this.props.renderDepth + 1}
                 CollectionView={undefined}
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index c2385cab8..da74edbe3 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -2412,7 +2412,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                 <div className="presBox-listCont">
                     {mode !== CollectionViewType.Invalid ?
                         <CollectionView {...this.props}
-                            annotationsKey={""}
                             ContainingCollectionDoc={this.props.Document}
                             PanelWidth={this.props.PanelWidth}
                             PanelHeight={this.panelHeight}
diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx
index f467fef12..713511a94 100644
--- a/src/client/views/nodes/ScreenshotBox.tsx
+++ b/src/client/views/nodes/ScreenshotBox.tsx
@@ -172,7 +172,6 @@ export class ScreenshotBox extends ViewBoxBaseComponent<FieldViewProps, Screensh
                 <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit}
                     PanelHeight={this.props.PanelHeight}
                     PanelWidth={this.props.PanelWidth}
-                    annotationsKey={""}
                     focus={this.props.focus}
                     isSelected={this.props.isSelected}
                     isAnnotationOverlay={true}
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index f64d80731..8d10768ff 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -429,7 +429,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
                     forceScaling={true}
                     PanelHeight={this.props.PanelHeight}
                     PanelWidth={this.props.PanelWidth}
-                    annotationsKey={this.annotationKey}
+                    fieldKey={this.annotationKey}
                     focus={this.props.focus}
                     isSelected={this.props.isSelected}
                     isAnnotationOverlay={true}
diff --git a/src/client/views/nodes/WebBox.scss b/src/client/views/nodes/WebBox.scss
index ea822f553..9d9c8a883 100644
--- a/src/client/views/nodes/WebBox.scss
+++ b/src/client/views/nodes/WebBox.scss
@@ -40,7 +40,6 @@
         .webBox-cont {
             pointer-events: none;
         }
-
         .webBox-cont,
         .webBox-cont-interactive {
             padding: 0vw;
@@ -73,6 +72,9 @@
             top: 0;
             left: 0;
             overflow: auto;
+            .webBox-innerContent {
+                position: relative;
+            }
         }
 
         div.webBox-outerContent::-webkit-scrollbar-thumb {
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 9a1ae336f..197ff20d5 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -699,7 +699,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
                         <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit}
                             PanelHeight={this.props.PanelHeight}
                             PanelWidth={this.props.PanelWidth}
-                            annotationsKey={this.annotationKey}
+                            fieldKey={this.annotationKey}
                             VisibleHeight={this.visibleHeight}
                             focus={this.props.focus}
                             setPreviewCursor={this.setPreviewCursor}
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 22e3ac1e9..33515e475 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -47,7 +47,7 @@ import { FootnoteView } from "./FootnoteView";
 import { schema } from "./schema_rts";
 import { SelectionManager } from "../../../util/SelectionManager";
 import { undoBatch, UndoManager } from "../../../util/UndoManager";
-import { CollectionFreeFormView } from '../../collections/collectionFreeForm/CollectionFreeFormView';
+import { CollectionFreeFormView, collectionFreeformViewProps } from '../../collections/collectionFreeForm/CollectionFreeFormView';
 import { ContextMenu } from '../../ContextMenu';
 import { ContextMenuProps } from '../../ContextMenuItem';
 import { ViewBoxAnnotatableComponent } from "../../DocComponent";
@@ -59,9 +59,10 @@ import { FormattedTextBoxComment, formattedTextBoxCommentPlugin, findLinkMark }
 import React = require("react");
 import { DocumentManager } from '../../../util/DocumentManager';
 import { CollectionStackingView } from '../../collections/CollectionStackingView';
-import { CollectionViewType } from '../../collections/CollectionView';
+import { CollectionViewType, CollectionViewProps } from '../../collections/CollectionView';
 import { SnappingManager } from '../../../util/SnappingManager';
 import { LinkDocPreview } from '../LinkDocPreview';
+import { SubCollectionViewProps } from '../../collections/CollectionSubView';
 
 export interface FormattedTextBoxProps {
     makeLink?: () => Opt<Doc>;  // bcz: hack: notifies the text document when the container has made a link.  allows the text doc to react and setup a hyeprlink for any selected text
@@ -1606,7 +1607,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
     sidebarContentScaling = () => this.props.ContentScaling() * NumCast(this.layoutDoc._viewScale, 1);
     @computed get sidebarCollection() {
         const fitToBox = this.props.Document._fitToBox;
-        const collectionProps = {
+        const collectionProps: SubCollectionViewProps & collectionFreeformViewProps = {
             ...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit,
             NativeWidth: returnZero,
             NativeHeight: returnZero,
@@ -1616,8 +1617,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
             yMargin: 0,
             chromeStatus: "enabled",
             scaleField: this.annotationKey + "-scale",
-            annotationsKey: this.annotationKey,
             isAnnotationOverlay: true,
+            fieldKey: this.annotationKey,
             fitToBox: fitToBox,
             focus: this.props.focus,
             isSelected: this.props.isSelected,
@@ -1636,7 +1637,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
         return !this.layoutDoc._showSidebar || this.sidebarWidthPercent === "0%" ? (null) :
             <div className={"formattedTextBox-sidebar" + (Doc.GetSelectedTool() !== InkTool.None ? "-inking" : "")}
                 style={{ width: `${this.sidebarWidthPercent}`, backgroundColor: `${this.sidebarColor}` }}>
-                {this.layoutDoc.sidebarViewType === CollectionViewType.Freeform ? <CollectionFreeFormView {...collectionProps} /> : <CollectionStackingView {...collectionProps} />}
+                {this.layoutDoc.sidebarViewType === CollectionViewType.Freeform ?
+                    <CollectionFreeFormView {...collectionProps} /> :
+                    <CollectionStackingView {...collectionProps} />}
             </div>;
     }
 
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 9b689eb6b..633a34c5e 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -736,7 +736,8 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
                 transform: `scale(${this._zoomed})`
             }}>
             <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit}
-                annotationsKey={this.annotationKey}
+                isAnnotationOverlay={true}
+                fieldKey={this.annotationKey}
                 setPreviewCursor={this.setPreviewCursor}
                 PanelHeight={this.panelWidth}
                 PanelWidth={this.panelHeight}
@@ -744,7 +745,6 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
                 VisibleHeight={this.visibleHeight}
                 focus={this.props.focus}
                 isSelected={this.props.isSelected}
-                isAnnotationOverlay={true}
                 select={emptyFunction}
                 active={this.annotationsActive}
                 ContentScaling={this.contentZoom}
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index 3adeb6133..d3fee85a7 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -559,7 +559,6 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
                             <div style={{ display: this.open ? "flex" : "none", overflow: "auto", position: "absolute" }}>
                                 <CollectionSchemaView {...this.props}
                                     CollectionView={undefined}
-                                    annotationsKey={""}
                                     addDocument={returnFalse}
                                     Document={this.props.Document}
                                     moveDocument={returnFalse}
-- 
cgit v1.2.3-70-g09d2


From d913740b994670b1b0eadd52069aeb69ef2b2380 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 10 Dec 2020 14:18:53 -0500
Subject: more cleanup/organization of 'props' .  removed VisibleHeight props
 and cleaned up PDF and other props

---
 src/client/util/CurrentUserUtils.ts                |  1 -
 .../util/Import & Export/DirectoryImportBox.tsx    |  1 -
 src/client/views/PropertiesView.tsx                |  2 +-
 .../views/collections/CollectionSchemaView.tsx     |  2 +-
 .../views/collections/CollectionStackingView.tsx   | 21 +++--
 .../views/collections/CollectionTimeView.tsx       |  7 +-
 src/client/views/collections/CollectionView.tsx    | 36 ++++----
 src/client/views/collections/SchemaTable.tsx       |  2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 16 ++--
 .../collectionGrid/CollectionGridView.tsx          |  2 +-
 .../CollectionMulticolumnView.tsx                  |  2 +-
 .../CollectionMultirowView.tsx                     |  2 +-
 .../views/nodes/CollectionFreeFormDocumentView.tsx |  2 +-
 .../views/nodes/ContentFittingDocumentView.tsx     |  2 +-
 src/client/views/nodes/DocumentView.tsx            |  4 +-
 src/client/views/nodes/KeyValueBox.tsx             |  1 -
 src/client/views/nodes/PDFBox.tsx                  | 96 +++++-----------------
 src/client/views/nodes/VideoBox.tsx                | 11 +--
 src/client/views/nodes/WebBox.tsx                  | 19 +----
 .../views/nodes/formattedText/FormattedTextBox.tsx |  3 -
 src/client/views/pdf/PDFViewer.tsx                 | 50 +++--------
 src/fields/documentSchemas.ts                      |  2 -
 22 files changed, 84 insertions(+), 200 deletions(-)

(limited to 'src/client/views/pdf/PDFViewer.tsx')

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 213bc3d88..676e7ce3e 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -801,7 +801,6 @@ export class CurrentUserUtils {
         }
     }
 
-
     static setupUserDoc(doc: Doc) {
         if (doc.myUserDoc === undefined) {
             doc.treeViewOpen = true;
diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx
index 7f01966b9..d9f010557 100644
--- a/src/client/util/Import & Export/DirectoryImportBox.tsx	
+++ b/src/client/util/Import & Export/DirectoryImportBox.tsx	
@@ -158,7 +158,6 @@ export class DirectoryImportBox extends React.Component<FieldViewProps> {
                 importContainer = Docs.Create.SchemaDocument(headers, docs, options);
             }
             runInAction(() => this.phase = 'External: uploading files to Google Photos...');
-            importContainer._columnsStack = false;
             await GooglePhotos.Export.CollectionToAlbum({ collection: importContainer });
             Doc.AddDocToList(Doc.GetProto(parent.props.Document), "data", importContainer);
             !this.persistent && this.props.removeDocument && this.props.removeDocument(doc);
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 08394cd97..233429f4d 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -272,7 +272,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                     treeViewDoc={undefined}
                     styleProvider={this.props.styleProvider}
                     fitToBox={true}
-                    FreezeDimensions={true}
+                    freezeDimensions={true}
                     dontCenter={"y"}
                     NativeWidth={layoutDoc.type === DocumentType.RTF ? this.rtfWidth : undefined}
                     NativeHeight={layoutDoc.type === DocumentType.RTF ? this.rtfHeight : undefined}
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index e22b8effe..c64048345 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -401,7 +401,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                     Document={this.previewDocument}
                     DataDoc={undefined}
                     fitToBox={true}
-                    FreezeDimensions={true}
+                    freezeDimensions={true}
                     dontCenter={"y"}
                     focus={emptyFunction}
                     renderDepth={this.props.renderDepth}
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 058536f69..b1c5dec84 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -3,7 +3,6 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { CursorProperty } from "csstype";
 import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx";
 import { observer } from "mobx-react";
-import Switch from 'rc-switch';
 import { DataSym, Doc, HeightSym, WidthSym } from "../../../fields/Doc";
 import { collectionSchema, documentSchema } from "../../../fields/documentSchemas";
 import { Id } from "../../../fields/FieldSymbols";
@@ -12,23 +11,23 @@ import { listSpec, makeInterface } from "../../../fields/Schema";
 import { SchemaHeaderField } from "../../../fields/SchemaHeaderField";
 import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from "../../../fields/Types";
 import { TraceMobx } from "../../../fields/util";
-import { emptyFunction, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils, smoothScroll, returnVal } from "../../../Utils";
+import { emptyFunction, returnFalse, returnOne, returnVal, returnZero, setupMoveUpEvents, smoothScroll, Utils } from "../../../Utils";
+import { DocUtils } from "../../documents/Documents";
 import { DragManager, dropActionType } from "../../util/DragManager";
+import { SnappingManager } from "../../util/SnappingManager";
 import { Transform } from "../../util/Transform";
 import { undoBatch } from "../../util/UndoManager";
 import { ContextMenu } from "../ContextMenu";
 import { ContextMenuProps } from "../ContextMenuItem";
 import { EditableView } from "../EditableView";
+import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView";
 import { ContentFittingDocumentView } from "../nodes/ContentFittingDocumentView";
+import { DocAfterFocusFunc } from "../nodes/DocumentView";
 import { CollectionMasonryViewFieldRow } from "./CollectionMasonryViewFieldRow";
 import "./CollectionStackingView.scss";
 import { CollectionStackingViewFieldColumn } from "./CollectionStackingViewFieldColumn";
 import { CollectionSubView } from "./CollectionSubView";
 import { CollectionViewType } from "./CollectionView";
-import { SnappingManager } from "../../util/SnappingManager";
-import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView";
-import { DocUtils } from "../../documents/Documents";
-import { DocAfterFocusFunc } from "../nodes/DocumentView";
 const _global = (window /* browser */ || global /* node */) as any;
 
 type StackingDocument = makeInterface<[typeof collectionSchema, typeof documentSchema]>;
@@ -56,7 +55,7 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
     @computed get xMargin() { return NumCast(this.layoutDoc._xMargin, 2 * Math.min(this.gridGap, .05 * this.props.PanelWidth())); }
     @computed get yMargin() { return Math.max(this.layoutDoc._showTitle && !this.layoutDoc._showTitleHover ? 30 : 0, this.props.yMargin || NumCast(this.layoutDoc._yMargin, 5)); } // 2 * this.gridGap)); }
     @computed get gridGap() { return NumCast(this.layoutDoc._gridGap, 10); }
-    @computed get isStackingView() { return BoolCast(this.layoutDoc._columnsStack, true); }
+    @computed get isStackingView() { return this.layoutDoc._viewType === CollectionViewType.Stacking; }
     @computed get numGroupColumns() { return this.isStackingView ? Math.max(1, this.Sections.size + (this.showAddAGroup ? 1 : 0)) : 1; }
     @computed get showAddAGroup() { return (this.pivotField && (this.chromeStatus !== 'view-mode' && this.chromeStatus !== 'disabled')); }
     @computed get columnWidth() {
@@ -192,13 +191,13 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
         return <ContentFittingDocumentView
             Document={doc}
             DataDoc={dataDoc || (!Doc.AreProtosEqual(doc[DataSym], doc) && doc[DataSym])}
-            styleProvider={this.props.styleProvider}
-            LayoutTemplate={this.props.childLayoutTemplate}
-            LayoutTemplateString={this.props.childLayoutString}
-            FreezeDimensions={this.props.childFreezeDimensions}
             renderDepth={this.props.renderDepth + 1}
             PanelWidth={width}
             PanelHeight={height}
+            styleProvider={this.props.styleProvider}
+            LayoutTemplate={this.props.childLayoutTemplate}
+            LayoutTemplateString={this.props.childLayoutString}
+            freezeDimensions={this.props.childFreezeDimensions}
             NativeWidth={this.props.childIgnoreNativeSize ? returnZero : undefined}  // explicitly ignore nativeWidth/height if childIgnoreNativeSize is set- used by PresBox
             NativeHeight={this.props.childIgnoreNativeSize ? returnZero : undefined}
             dontCenter={this.props.childIgnoreNativeSize ? "xy" : ""}
diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx
index e4a3c384c..c7a826669 100644
--- a/src/client/views/collections/CollectionTimeView.tsx
+++ b/src/client/views/collections/CollectionTimeView.tsx
@@ -85,7 +85,12 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) {
 
     @computed get contents() {
         return <div className="collectionTimeView-innards" key="timeline" style={{ width: "100%", pointerEvents: this.props.active() ? undefined : "none" }} onPointerDown={this.contentsDown}>
-            <CollectionFreeFormView {...this.props} childClickScript={this._childClickedScript} viewDefDivClick={this._viewDefDivClick} fitToBox={true} childFreezeDimensions={true} layoutEngine={this.layoutEngine} />
+            <CollectionFreeFormView {...this.props}
+                fitToBox={true}
+                childClickScript={this._childClickedScript}
+                viewDefDivClick={this._viewDefDivClick}
+                childFreezeDimensions={true}
+                layoutEngine={this.layoutEngine} />
         </div>;
     }
 
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 511fc723d..dbbb3e991 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -66,7 +66,6 @@ export interface CollectionViewProps extends FieldViewProps {
     layoutEngine?: () => string;
     parentActive: (outsideReaction: boolean) => boolean;
     filterAddDocument?: (doc: Doc | Doc[]) => boolean;  // allows a document that renders a Collection view to filter or modify any documents added to the collection (see PresBox for an example)
-    VisibleHeight?: () => number;
     setPreviewCursor?: (func: (x: number, y: number, drag: boolean) => void) => void;
 
     // property overrides for child documents
@@ -242,28 +241,27 @@ export class CollectionView extends Touchable<CollectionViewProps> {
     private SubView = (type: CollectionViewType, props: SubCollectionViewProps) => {
         TraceMobx();
         switch (type) {
-            case CollectionViewType.Schema: return (<CollectionSchemaView key="collview" {...props} />);
-            case CollectionViewType.Docking: return (<CollectionDockingView key="collview" {...props} />);
-            case CollectionViewType.Tree: return (<CollectionTreeView key="collview" {...props} />);
-            //case CollectionViewType.Staff: return (<CollectionStaffView key="collview" {...props} />);
-            case CollectionViewType.Multicolumn: return (<CollectionMulticolumnView key="collview" {...props} />);
-            case CollectionViewType.Multirow: return (<CollectionMultirowView key="rpwview" {...props} />);
-            case CollectionViewType.Linear: { return (<CollectionLinearView key="collview" {...props} />); }
-            case CollectionViewType.Pile: { return (<CollectionPileView key="collview" {...props} />); }
-            case CollectionViewType.Carousel: { return (<CollectionCarouselView key="collview" {...props} />); }
-            case CollectionViewType.Carousel3D: { return (<CollectionCarousel3DView key="collview" {...props} />); }
-            case CollectionViewType.Stacking: { this.props.Document._columnsStack = true; return (<CollectionStackingView key="collview" {...props} />); }
-            case CollectionViewType.Masonry: { this.props.Document._columnsStack = false; return (<CollectionStackingView key="collview" {...props} />); }
-            case CollectionViewType.Time: { return (<CollectionTimeView key="collview" {...props} />); }
-            case CollectionViewType.Map: return (<CollectionMapView key="collview" {...props} />);
-            case CollectionViewType.Grid: return (<CollectionGridView key="gridview" {...props} />);
-            case CollectionViewType.Freeform:
-            default: { this.props.Document._freeformLayoutEngine = undefined; return (<CollectionFreeFormView key="collview" {...props} />); }
+            default:
+            case CollectionViewType.Freeform: return <CollectionFreeFormView key="collview" {...props} />;
+            case CollectionViewType.Schema: return <CollectionSchemaView key="collview" {...props} />;
+            case CollectionViewType.Docking: return <CollectionDockingView key="collview" {...props} />;
+            case CollectionViewType.Tree: return <CollectionTreeView key="collview" {...props} />;
+            case CollectionViewType.Multicolumn: return <CollectionMulticolumnView key="collview" {...props} />;
+            case CollectionViewType.Multirow: return <CollectionMultirowView key="collview" {...props} />;
+            case CollectionViewType.Linear: return <CollectionLinearView key="collview" {...props} />;
+            case CollectionViewType.Pile: return <CollectionPileView key="collview" {...props} />;
+            case CollectionViewType.Carousel: return <CollectionCarouselView key="collview" {...props} />;
+            case CollectionViewType.Carousel3D: return <CollectionCarousel3DView key="collview" {...props} />;
+            case CollectionViewType.Stacking: return <CollectionStackingView key="collview" {...props} />;
+            case CollectionViewType.Masonry: return <CollectionStackingView key="collview" {...props} />;
+            case CollectionViewType.Time: return <CollectionTimeView key="collview" {...props} />;
+            case CollectionViewType.Map: return <CollectionMapView key="collview" {...props} />;
+            case CollectionViewType.Grid: return <CollectionGridView key="collview" {...props} />;
+            //case CollectionViewType.Staff: return <CollectionStaffView key="collview" {...props} />;
         }
     }
 
     setupViewTypes(category: string, func: (viewType: CollectionViewType) => Doc, addExtras: boolean) {
-
         const subItems: ContextMenuProps[] = [];
         subItems.push({ description: "Freeform", event: () => func(CollectionViewType.Freeform), icon: "signature" });
         if (addExtras && CollectionView._safeMode) {
diff --git a/src/client/views/collections/SchemaTable.tsx b/src/client/views/collections/SchemaTable.tsx
index b532d3302..24a67faaf 100644
--- a/src/client/views/collections/SchemaTable.tsx
+++ b/src/client/views/collections/SchemaTable.tsx
@@ -571,7 +571,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
                         Document={this._showDoc}
                         DataDoc={this._showDataDoc}
                         fitToBox={true}
-                        FreezeDimensions={true}
+                        freezeDimensions={true}
                         focus={emptyFunction}
                         renderDepth={this.props.renderDepth}
                         rootSelected={() => false}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index e09abd017..94de40bc8 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -918,7 +918,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
                 !dontCenter && this.props.focus(doc);
                 afterFocus && setTimeout(afterFocus, delay);
             } else {
-                const contextHgt = Doc.AreProtosEqual(annotOn, this.props.Document) && this.props.VisibleHeight ? this.props.VisibleHeight() : NumCast(annotOn._height);
+                const contextHgt = NumCast(annotOn._height);
                 const curScroll = NumCast(this.props.Document._scrollTop);
                 let scrollTo = curScroll;
                 if (curScroll + contextHgt < NumCast(doc.y)) {
@@ -998,30 +998,30 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
             fitToBox: false,
             DataDoc: childData,
             Document: childLayout,
+            ContainingCollectionView: this.props.CollectionView,
+            ContainingCollectionDoc: this.props.Document,
             LayoutTemplate: childLayout.z ? undefined : this.props.childLayoutTemplate,
             LayoutTemplateString: childLayout.z ? undefined : this.props.childLayoutString,
-            FreezeDimensions: this.props.childFreezeDimensions,
             setupDragLines: this.setupDragLines,
-            dontRegisterView: this.props.dontRegisterView,
             rootSelected: childData ? this.rootSelected : returnFalse,
-            dropAction: StrCast(this.props.Document.childDropAction) as dropActionType,
             onClick: this.onChildClickHandler,
             onDoubleClick: this.onChildDoubleClickHandler,
             ScreenToLocalTransform: childLayout.z ? this.getTransformOverlay : this.getTransform,
-            renderDepth: this.props.renderDepth + 1,
             PanelWidth: childLayout[WidthSym],
             PanelHeight: childLayout[HeightSym],
             ContentScaling: returnOne,
-            ContainingCollectionView: this.props.CollectionView,
-            ContainingCollectionDoc: this.props.Document,
             docFilters: this.docFilters,
             docRangeFilters: this.docRangeFilters,
             searchFilterDocs: this.searchFilterDocs,
             focus: this.focusDocument,
             styleProvider: this.getClusterColor,
             backgroundHalo: this.backgroundHalo,
+            freezeDimensions: this.props.childFreezeDimensions,
+            dropAction: StrCast(this.props.Document.childDropAction) as dropActionType,
             bringToFront: this.bringToFront,
             addDocTab: this.addDocTab,
+            renderDepth: this.props.renderDepth + 1,
+            dontRegisterView: this.props.dontRegisterView,
         };
     }
 
@@ -1172,7 +1172,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
                     jitterRotation={NumCast(this.props.Document._jitterRotation) || ((Doc.UserDoc().renderStyle === "comic" ? 10 : 0))}
                     //fitToBox={this.props.fitToBox || BoolCast(this.props.freezeChildDimensions)} // bcz: check this
                     fitToBox={BoolCast(this.props.childFreezeDimensions)} // bcz: check this
-                    FreezeDimensions={BoolCast(this.props.childFreezeDimensions)}
+                    freezeDimensions={BoolCast(this.props.childFreezeDimensions)}
                 />,
                 bounds: this.childDataProvider(entry[1].pair.layout, entry[1].replica)
             }));
diff --git a/src/client/views/collections/collectionGrid/CollectionGridView.tsx b/src/client/views/collections/collectionGrid/CollectionGridView.tsx
index f3e385746..bef197bee 100644
--- a/src/client/views/collections/collectionGrid/CollectionGridView.tsx
+++ b/src/client/views/collections/collectionGrid/CollectionGridView.tsx
@@ -170,7 +170,7 @@ export class CollectionGridView extends CollectionSubView(GridSchema) {
             PanelWidth={width}
             PanelHeight={height}
             ContentScaling={returnOne}
-            FreezeDimensions={true}
+            freezeDimensions={true}
             fitToBox={true}
             ScreenToLocalTransform={dxf}
             onClick={this.onChildClickHandler}
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
index 586c5d1df..d4913a5ed 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
@@ -219,7 +219,7 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu
             styleProvider={this.props.styleProvider}
             LayoutTemplate={this.props.childLayoutTemplate}
             LayoutTemplateString={this.props.childLayoutString}
-            FreezeDimensions={this.props.childFreezeDimensions}
+            freezeDimensions={this.props.childFreezeDimensions}
             renderDepth={this.props.renderDepth + 1}
             PanelWidth={width}
             PanelHeight={height}
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
index 87c56de6f..9039090d1 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
@@ -219,7 +219,7 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument)
             styleProvider={this.props.styleProvider}
             LayoutTemplate={this.props.childLayoutTemplate}
             LayoutTemplateString={this.props.childLayoutString}
-            FreezeDimensions={this.props.childFreezeDimensions}
+            freezeDimensions={this.props.childFreezeDimensions}
             renderDepth={this.props.renderDepth + 1}
             PanelWidth={width}
             PanelHeight={height}
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index b4b887617..d68184da6 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -52,7 +52,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
         const hgt = this.props.sizeProvider && this.sizeProvider ? this.sizeProvider.height : this.layoutDoc[HeightSym]();
         return (hgt === undefined && this.nativeWidth && this.nativeHeight) ? this.width * this.nativeHeight / this.nativeWidth : hgt;
     }
-    @computed get freezeDimensions() { return this.props.FreezeDimensions; }
+    @computed get freezeDimensions() { return this.props.freezeDimensions; }
     @computed get dataProvider() { return this.props.dataProvider?.(this.props.Document, this.props.replica); }
     @computed get sizeProvider() { return this.props.sizeProvider?.(this.props.Document, this.props.replica); }
     @computed get nativeWidth() { return returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, undefined, this.freezeDimensions)); }
diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx
index 74d7cb24e..7b767a10a 100644
--- a/src/client/views/nodes/ContentFittingDocumentView.tsx
+++ b/src/client/views/nodes/ContentFittingDocumentView.tsx
@@ -22,7 +22,7 @@ export class ContentFittingDocumentView extends React.Component<DocumentViewProp
             (this.props.layoutKey && Doc.Layout(this.props.Document, Cast(this.props.Document[this.props.layoutKey], Doc, null))) ||
             Doc.Layout(this.props.Document);
     }
-    @computed get freezeDimensions() { return this.props.FreezeDimensions; }
+    @computed get freezeDimensions() { return this.props.freezeDimensions; }
     @computed get nativeWidth() { return !this.layoutDoc._fitWidth && returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.DataDoc, this.freezeDimensions)); }
     @computed get nativeHeight() { return returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, this.freezeDimensions) || 0); }
     @computed get nativeScaling() {
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index dc048843f..595c3a950 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -84,7 +84,7 @@ export interface DocumentViewSharedProps {
 }
 export interface DocumentViewProps extends DocumentViewSharedProps {
     // properties specific to DocumentViews but not to FieldView
-    FreezeDimensions?: boolean;
+    freezeDimensions?: boolean;
     fitToBox?: boolean;
     treeViewDoc?: Doc;
     dragDivName?: string;
@@ -133,7 +133,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 undefined);
     }
     @computed get topMost() { return this.props.renderDepth === 0; }
-    @computed get freezeDimensions() { return this.props.FreezeDimensions; }
+    @computed get freezeDimensions() { return this.props.freezeDimensions; }
     @computed get nativeWidth() { return returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.dataDoc, this.freezeDimensions)); }
     @computed get nativeHeight() { return returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.dataDoc, this.freezeDimensions)); }
     @computed get onClickHandler() { return this.props.onClick?.() ?? Cast(this.Document.onClick, ScriptField, Cast(this.layoutDoc.onClick, ScriptField, null)); }
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index 4ac932c24..8acf4081c 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -169,7 +169,6 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
 
     getTemplate = async () => {
         const parent = Docs.Create.StackingDocument([], { _width: 800, _height: 800, title: "Template" });
-        parent._columnsStack = false;
         parent._columnWidth = 100;
         for (const row of this.rows.filter(row => row.isChecked)) {
             await this.createTemplateField(parent, row);
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 42b24f6f6..a2f3fb2d1 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -1,28 +1,27 @@
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, observable, runInAction, reaction, IReactionDisposer, trace, untracked, computed } from 'mobx';
+import { action, computed, IReactionDisposer, observable, reaction, runInAction } from 'mobx';
 import { observer } from "mobx-react";
 import * as Pdfjs from "pdfjs-dist";
 import "pdfjs-dist/web/pdf_viewer.css";
-import { Opt, WidthSym, Doc, HeightSym } from "../../../fields/Doc";
+import { Doc, Opt, WidthSym } from "../../../fields/Doc";
+import { documentSchema } from '../../../fields/documentSchemas';
 import { makeInterface } from "../../../fields/Schema";
-import { ScriptField } from '../../../fields/ScriptField';
-import { Cast, NumCast, StrCast } from "../../../fields/Types";
-import { PdfField, URLField } from "../../../fields/URLField";
+import { Cast, NumCast } from "../../../fields/Types";
+import { PdfField } from "../../../fields/URLField";
+import { TraceMobx } from '../../../fields/util';
 import { Utils } from '../../../Utils';
+import { KeyCodes } from '../../util/KeyCodes';
 import { undoBatch } from '../../util/UndoManager';
 import { panZoomSchema } from '../collections/collectionFreeForm/CollectionFreeFormView';
+import { CollectionViewType } from '../collections/CollectionView';
 import { ContextMenu } from '../ContextMenu';
 import { ContextMenuProps } from '../ContextMenuItem';
 import { ViewBoxAnnotatableComponent } from "../DocComponent";
 import { PDFViewer } from "../pdf/PDFViewer";
 import { FieldView, FieldViewProps } from './FieldView';
 import { pageSchema } from "./ImageBox";
-import { KeyCodes } from '../../util/KeyCodes';
 import "./PDFBox.scss";
 import React = require("react");
-import { documentSchema } from '../../../fields/documentSchemas';
-import { CollectionViewType } from '../collections/CollectionView';
-import { TraceMobx } from '../../../fields/util';
 
 type PdfDocument = makeInterface<[typeof documentSchema, typeof panZoomSchema, typeof pageSchema]>;
 const PdfDocument = makeInterface(documentSchema, panZoomSchema, pageSchema);
@@ -30,17 +29,11 @@ const PdfDocument = makeInterface(documentSchema, panZoomSchema, pageSchema);
 @observer
 export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocument>(PdfDocument) {
     public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PDFBox, fieldKey); }
-    private _keyValue: string = "";
-    private _valueValue: string = "";
-    private _scriptValue: string = "";
     private _searchString: string = "";
     private _initialScale: number = 0;  // the initial scale of the PDF when first rendered which determines whether the document will be live on startup or not.  Getting bigger after startup won't make it automatically be live.
     private _displayPdfLive = false; // has this box ever had its contents activated -- if so, stop drawing the overlay title
     private _pdfViewer: PDFViewer | undefined;
     private _searchRef = React.createRef<HTMLInputElement>();
-    private _keyRef = React.createRef<HTMLInputElement>();
-    private _valueRef = React.createRef<HTMLInputElement>();
-    private _scriptRef = React.createRef<HTMLInputElement>();
     private _selectReactionDisposer: IReactionDisposer | undefined;
 
     @observable private _searching: boolean = false;
@@ -130,25 +123,6 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum
         }
     });
 
-    @undoBatch
-    @action
-    private applyFilter = () => {
-        const scriptText = this._scriptValue ? this._scriptValue :
-            this._keyValue && this._valueValue ? `this.${this._keyValue} === ${this._valueValue}` : "true";
-        this.props.Document.filterScript = ScriptField.MakeFunction(scriptText);
-    }
-
-    private resetFilters = () => {
-        this._keyValue = this._valueValue = this._scriptValue = "";
-        this._keyRef.current && (this._keyRef.current.value = "");
-        this._valueRef.current && (this._valueRef.current.value = "");
-        this._scriptRef.current && (this._scriptRef.current.value = "");
-        this.applyFilter();
-    }
-    private newKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => this._keyValue = e.currentTarget.value;
-    private newValueChange = (e: React.ChangeEvent<HTMLInputElement>) => this._valueValue = e.currentTarget.value;
-    private newScriptChange = (e: React.ChangeEvent<HTMLInputElement>) => this._scriptValue = e.currentTarget.value;
-
     whenActiveChanged = action((isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive));
     setPdfViewer = (pdfViewer: PDFViewer) => { this._pdfViewer = pdfViewer; };
     searchStringChanged = (e: React.ChangeEvent<HTMLInputElement>) => this._searchString = e.currentTarget.value;
@@ -197,36 +171,6 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum
                         onClick={action(() => this._pageControls = !this._pageControls)} />
                     {this._pageControls ? pageBtns : (null)}
                 </div>
-                {/* <div className="pdfBox-settingsCont" key="settings" onPointerDown={(e) => e.stopPropagation()}>
-                    <button className="pdfBox-settingsButton" onClick={action(() => this._flyout = !this._flyout)} title="Open Annotation Settings" >
-                        <div className="pdfBox-settingsButton-arrow" style={{ transform: `scaleX(${this._flyout ? -1 : 1})` }} />
-                        <div className="pdfBox-settingsButton-iconCont">
-                            <FontAwesomeIcon style={{ color: "white" }} icon="cog" size="lg" />
-                        </div>
-                    </button>
-                    <div className="pdfBox-settingsFlyout" style={{ right: `${this._flyout ? 20 : -1000}px` }} >
-                        <div className="pdfBox-settingsFlyout-title">
-                            Annotation View Settings
-                        </div>
-                        <div className="pdfBox-settingsFlyout-kvpInput">
-                            <input placeholder="Key" className="pdfBox-settingsFlyout-input" onChange={this.newKeyChange} style={{ gridColumn: 1 }} ref={this._keyRef} />
-                            <input placeholder="Value" className="pdfBox-settingsFlyout-input" onChange={this.newValueChange} style={{ gridColumn: 3 }} ref={this._valueRef} />
-                        </div>
-                        <div className="pdfBox-settingsFlyout-kvpInput">
-                            <input placeholder="Custom Script" onChange={this.newScriptChange} style={{ gridColumn: "1 / 4" }} ref={this._scriptRef} />
-                        </div>
-                        <div className="pdfBox-settingsFlyout-kvpInput">
-                            <button style={{ gridColumn: 1 }} onClick={this.resetFilters}>
-                                <FontAwesomeIcon style={{ color: "white" }} icon="trash" size="lg" />
-                                &nbsp; Reset Filters
-                            </button>
-                            <button style={{ gridColumn: 3 }} onClick={this.applyFilter}>
-                                <FontAwesomeIcon style={{ color: "white" }} icon="check" size="lg" />
-                                &nbsp; Apply
-                            </button>
-                        </div>
-                    </div>
-                </div> */}
             </div>);
     }
 
@@ -253,19 +197,19 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum
     @computed get renderPdfView() {
         TraceMobx();
         const pdfUrl = Cast(this.dataDoc[this.props.fieldKey], PdfField);
-        return <div className={"pdfBox"} onContextMenu={this.specificContextMenu} style={{ height: this.props.Document._scrollTop && !this.Document._fitWidth && (window.screen.width > 600) ? NumCast(this.Document._height) * this.props.PanelWidth() / NumCast(this.Document._width) : undefined }}>
-            <div className="pdfBox-background"></div>
-            <PDFViewer {...this.props} pdf={this._pdf!} url={pdfUrl!.url.pathname} active={this.props.active} loaded={!Doc.NativeAspect(this.dataDoc) ? this.loaded : undefined}
-                setPdfViewer={this.setPdfViewer} ContainingCollectionView={this.props.ContainingCollectionView}
-                renderDepth={this.props.renderDepth} PanelHeight={this.props.PanelHeight} PanelWidth={this.props.PanelWidth}
-                addDocTab={this.props.addDocTab} focus={this.props.focus} searchFilterDocs={this.props.searchFilterDocs}
-                docFilters={this.props.docFilters} docRangeFilters={this.props.docRangeFilters}
-                pinToPres={this.props.pinToPres} addDocument={this.addDocument}
-                Document={this.props.Document} DataDoc={this.dataDoc} ContentScaling={this.props.ContentScaling}
-                ScreenToLocalTransform={this.props.ScreenToLocalTransform} select={this.props.select}
-                isSelected={this.props.isSelected} whenActiveChanged={this.whenActiveChanged}
+        return <div className={"pdfBox"} onContextMenu={this.specificContextMenu}
+            style={{ height: this.props.Document._scrollTop && !this.Document._fitWidth && (window.screen.width > 600) ? NumCast(this.Document._height) * this.props.PanelWidth() / NumCast(this.Document._width) : undefined }}>
+            <div className="pdfBox-background" />
+            <PDFViewer {...this.props}
+                pdf={this._pdf!}
+                url={pdfUrl!.url.pathname}
+                loaded={!Doc.NativeAspect(this.dataDoc) ? this.loaded : undefined}
+                setPdfViewer={this.setPdfViewer}
+                addDocument={this.addDocument}
+                whenActiveChanged={this.whenActiveChanged}
                 isChildActive={this.isChildActive}
-                fieldKey={this.props.fieldKey} startupLive={true} />
+                startupLive={true}
+            />
             {this.settingsPanel()}
         </div>;
     }
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 8d10768ff..90a5dee23 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -427,11 +427,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
             <div className="videoBox-viewer" >
                 <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit}
                     forceScaling={true}
-                    PanelHeight={this.props.PanelHeight}
-                    PanelWidth={this.props.PanelWidth}
                     fieldKey={this.annotationKey}
-                    focus={this.props.focus}
-                    isSelected={this.props.isSelected}
                     isAnnotationOverlay={true}
                     select={emptyFunction}
                     active={this.annotationsActive}
@@ -441,12 +437,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
                     moveDocument={this.moveDocument}
                     addDocument={this.addDocumentWithTimestamp}
                     CollectionView={undefined}
-                    ScreenToLocalTransform={this.props.ScreenToLocalTransform}
-                    renderDepth={this.props.renderDepth + 1}
-                    docFilters={this.props.docFilters}
-                    docRangeFilters={this.props.docRangeFilters}
-                    searchFilterDocs={this.props.searchFilterDocs}
-                    ContainingCollectionDoc={this.props.ContainingCollectionDoc}>
+                    renderDepth={this.props.renderDepth + 1}>
                     {this.contentFunc}
                 </CollectionFreeFormView>
             </div>
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 197ff20d5..47464d794 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -646,14 +646,6 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
     marqueeX = () => this._marqueeX;
     marqueeY = () => this._marqueeY;
     marqueeing = () => this._marqueeing;
-    visibleHeight = () => {
-        if (this._mainCont.current) {
-            const boundingRect = this._mainCont.current.getBoundingClientRect();
-            const scaling = (Doc.NativeWidth(this.Document) || 0) / boundingRect.width;
-            return Math.min(boundingRect.height * scaling, this.props.PanelHeight() * scaling);
-        }
-        return this.props.PanelHeight();
-    }
     scrollXf = () => this.props.ScreenToLocalTransform().translate(NumCast(this.layoutDoc._scrollLeft), NumCast(this.layoutDoc._scrollTop));
     render() {
         const scaling = Number.isFinite(this.props.ContentScaling()) ? this.props.ContentScaling() || 1 : 1;
@@ -697,13 +689,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
                         pointerEvents: this.props.layerProvider?.(this.layoutDoc) === false ? "none" : undefined
                     }}>
                         <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit}
-                            PanelHeight={this.props.PanelHeight}
-                            PanelWidth={this.props.PanelWidth}
                             fieldKey={this.annotationKey}
-                            VisibleHeight={this.visibleHeight}
-                            focus={this.props.focus}
                             setPreviewCursor={this.setPreviewCursor}
-                            isSelected={this.props.isSelected}
                             isAnnotationOverlay={true}
                             select={emptyFunction}
                             active={this.active}
@@ -714,11 +701,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
                             addDocument={this.addDocument}
                             CollectionView={undefined}
                             ScreenToLocalTransform={this.scrollXf}
-                            renderDepth={this.props.renderDepth + 1}
-                            docFilters={this.props.docFilters}
-                            docRangeFilters={this.props.docRangeFilters}
-                            searchFilterDocs={this.props.searchFilterDocs}
-                            ContainingCollectionDoc={this.props.ContainingCollectionDoc}>
+                            renderDepth={this.props.renderDepth + 1}>
                         </CollectionFreeFormView>
                     </div>
                 </div>
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 33515e475..bfbd7805d 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1620,8 +1620,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
             isAnnotationOverlay: true,
             fieldKey: this.annotationKey,
             fitToBox: fitToBox,
-            focus: this.props.focus,
-            isSelected: this.props.isSelected,
             select: emptyFunction,
             active: this.annotationsActive,
             ContentScaling: this.sidebarContentScaling,
@@ -1632,7 +1630,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
             CollectionView: undefined,
             ScreenToLocalTransform: this.sidebarScreenToLocal,
             renderDepth: this.props.renderDepth + 1,
-            ContainingCollectionDoc: this.props.ContainingCollectionDoc,
         };
         return !this.layoutDoc._showSidebar || this.sidebarWidthPercent === "0%" ? (null) :
             <div className={"formattedTextBox-sidebar" + (Doc.GetSelectedTool() !== InkTool.None ? "-inking" : "")}
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 633a34c5e..199b77408 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -3,7 +3,7 @@ import { observer } from "mobx-react";
 import * as Pdfjs from "pdfjs-dist";
 import "pdfjs-dist/web/pdf_viewer.css";
 import { Dictionary } from "typescript-collections";
-import { AclAddonly, AclAdmin, AclEdit, DataSym, Doc, DocListCast, HeightSym, Opt, WidthSym, Field } from "../../../fields/Doc";
+import { AclAddonly, AclAdmin, AclEdit, DataSym, Doc, DocListCast, Field, HeightSym, Opt, WidthSym } from "../../../fields/Doc";
 import { documentSchema } from "../../../fields/documentSchemas";
 import { Id } from "../../../fields/FieldSymbols";
 import { InkTool } from "../../../fields/InkField";
@@ -13,29 +13,30 @@ import { ScriptField } from "../../../fields/ScriptField";
 import { Cast, NumCast, StrCast } from "../../../fields/Types";
 import { PdfField } from "../../../fields/URLField";
 import { GetEffectiveAcl, TraceMobx } from "../../../fields/util";
-import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, emptyPath, intersectRect, returnZero, smoothScroll, Utils, OmitKeys } from "../../../Utils";
+import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, OmitKeys, smoothScroll, Utils } from "../../../Utils";
 import { Docs, DocUtils } from "../../documents/Documents";
 import { DocumentType } from "../../documents/DocumentTypes";
 import { Networking } from "../../Network";
+import { CurrentUserUtils } from "../../util/CurrentUserUtils";
 import { DragManager } from "../../util/DragManager";
 import { CompiledScript, CompileScript } from "../../util/Scripting";
 import { SelectionManager } from "../../util/SelectionManager";
+import { SharingManager } from "../../util/SharingManager";
 import { SnappingManager } from "../../util/SnappingManager";
 import { Transform } from "../../util/Transform";
 import { undoBatch } from "../../util/UndoManager";
 import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView";
 import { CollectionView } from "../collections/CollectionView";
 import { ViewBoxAnnotatableComponent } from "../DocComponent";
+import { FormattedTextBox } from "../nodes/formattedText/FormattedTextBox";
+import { FormattedTextBoxComment } from "../nodes/formattedText/FormattedTextBoxComment";
+import { LinkDocPreview } from "../nodes/LinkDocPreview";
 import { Annotation } from "./Annotation";
 import { PDFMenu } from "./PDFMenu";
 import "./PDFViewer.scss";
 const pdfjs = require('pdfjs-dist/es5/build/pdf.js');
 import React = require("react");
-import { LinkDocPreview } from "../nodes/LinkDocPreview";
-import { FormattedTextBoxComment } from "../nodes/formattedText/FormattedTextBoxComment";
-import { CurrentUserUtils } from "../../util/CurrentUserUtils";
-import { SharingManager } from "../../util/SharingManager";
-import { FormattedTextBox } from "../nodes/formattedText/FormattedTextBox";
+import { FieldViewProps } from "../nodes/FieldView";
 const PDFJSViewer = require("pdfjs-dist/web/pdf_viewer");
 const pdfjsLib = require("pdfjs-dist");
 const _global = (window /* browser */ || global /* node */) as any;
@@ -54,34 +55,13 @@ pdfjsLib.GlobalWorkerOptions.workerSrc = "https://unpkg.com/pdfjs-dist@2.4.456/b
 type PdfDocument = makeInterface<[typeof documentSchema, typeof pageSchema]>;
 const PdfDocument = makeInterface(documentSchema, pageSchema);
 
-interface IViewerProps {
+interface IViewerProps extends FieldViewProps {
     pdf: Pdfjs.PDFDocumentProxy;
     url: string;
-    fieldKey: string;
-    Document: Doc;
-    DataDoc?: Doc;
-    searchFilterDocs: () => Doc[];
-    ContainingCollectionView: Opt<CollectionView>;
-    docFilters: () => string[];
-    docRangeFilters: () => string[];
-    PanelWidth: () => number;
-    PanelHeight: () => number;
-    ContentScaling: () => number;
-    select: (isCtrlPressed: boolean) => void;
-    rootSelected: (outsideReaction?: boolean) => boolean;
     startupLive: boolean;
-    renderDepth: number;
-    focus: (doc: Doc) => void;
-    isSelected: (outsideReaction?: boolean) => boolean;
     loaded?: (nw: number, nh: number, np: number) => void;
-    active: (outsideReaction?: boolean) => boolean;
     isChildActive: (outsideReaction?: boolean) => boolean;
-    addDocTab: (document: Doc, where: string) => boolean;
-    pinToPres: (document: Doc, unpin?: boolean) => void;
-    addDocument?: (doc: Doc) => boolean;
     setPdfViewer: (view: PDFViewer) => void;
-    ScreenToLocalTransform: () => Transform;
-    whenActiveChanged: (isActive: boolean) => void;
 }
 
 /**
@@ -392,13 +372,12 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
     @action
     scrollToAnnotation = (scrollToAnnotation: Doc) => {
         if (scrollToAnnotation) {
-            const offset = this.visibleHeight() / 2;
+            const offset = (this.props.PanelHeight() / this.props.ContentScaling()) / 2;
             this._mainCont.current && smoothScroll(500, this._mainCont.current, NumCast(scrollToAnnotation.y) - offset);
             Doc.linkFollowHighlight(scrollToAnnotation);
         }
     }
 
-
     pageDelay: any;
     @action
     onScroll = (e: React.UIEvent<HTMLElement>) => {
@@ -742,9 +721,6 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
                 PanelHeight={this.panelWidth}
                 PanelWidth={this.panelHeight}
                 dropAction={"alias"}
-                VisibleHeight={this.visibleHeight}
-                focus={this.props.focus}
-                isSelected={this.props.isSelected}
                 select={emptyFunction}
                 active={this.annotationsActive}
                 ContentScaling={this.contentZoom}
@@ -754,12 +730,9 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
                 removeDocument={this.removeDocument}
                 moveDocument={this.moveDocument}
                 addDocument={this.addDocument}
-                docFilters={this.props.docFilters}
-                docRangeFilters={this.props.docRangeFilters}
                 CollectionView={undefined}
                 ScreenToLocalTransform={this.overlayTransform}
-                renderDepth={this.props.renderDepth + 1}
-                ContainingCollectionDoc={this.props.ContainingCollectionView?.props.Document}>
+                renderDepth={this.props.renderDepth + 1}>
             </CollectionFreeFormView>
         </div>;
     }
@@ -778,7 +751,6 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
     marqueeX = () => this._marqueeX;
     marqueeY = () => this._marqueeY;
     marqueeing = () => this._marqueeing;
-    visibleHeight = () => this.props.PanelHeight() / this.props.ContentScaling();
     contentZoom = () => this._zoomed;
     render() {
         TraceMobx();
diff --git a/src/fields/documentSchemas.ts b/src/fields/documentSchemas.ts
index 979238767..67df56015 100644
--- a/src/fields/documentSchemas.ts
+++ b/src/fields/documentSchemas.ts
@@ -49,14 +49,12 @@ export const documentSchema = createSchema({
     _showTitle: "string",       // the fieldkey whose contents should be displayed at the top of the document
     _showTitleHover: "string",  // the showTitle should be shown only on hover
     _showAudio: "boolean",      // whether to show the audio record icon on documents
-    _freeformLayoutEngine: "string",// the string ID for the layout engine to use to layout freeform view documents
     _freeformLOD: "boolean",    // whether to enable LOD switching for CollectionFreeFormViews
     _pivotField: "string",      // specifies which field key should be used as the timeline/pivot axis
     _replacedChrome: "string",  // what the default chrome is replaced with. Currently only supports the value of 'replaced' for PresBox's.
     _chromeStatus: "string",    // determines the state of the collection chrome. values allowed are 'replaced', 'enabled', 'disabled', 'collapsed'
     _columnsFill: "boolean",    // whether documents in a stacking view column should be sized to fill the column
     _columnsSort: "string",     // how a document should be sorted "ascending", "descending", undefined (none)   
-    _columnsStack: "boolean",   // whether a stacking document stacks vertically (as opposed to masonry horizontal)
     _columnsHideIfEmpty: "boolean",   // whether empty stacking view column headings should be hidden
     _columnHeaders: listSpec(SchemaHeaderField), // header descriptions for stacking/masonry
     _schemaHeaders: listSpec(SchemaHeaderField), // header descriptions for schema views
-- 
cgit v1.2.3-70-g09d2


From f3f93e61f3914bd9fd6e8098a99e552f7860bc5f Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Sat, 12 Dec 2020 16:56:14 -0500
Subject: fixed displaying items (images,et) in treeViews to indent properly. 
 Fixed bounds of contentfittingviews in treeViews to be correct.

---
 .../views/collections/CollectionTreeView.scss      |  4 ++
 src/client/views/collections/TreeView.scss         |  9 ----
 src/client/views/collections/TreeView.tsx          | 60 ++++++++++------------
 src/client/views/pdf/PDFViewer.tsx                 |  4 +-
 4 files changed, 33 insertions(+), 44 deletions(-)

(limited to 'src/client/views/pdf/PDFViewer.tsx')

diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss
index c5add7cfb..650fb019d 100644
--- a/src/client/views/collections/CollectionTreeView.scss
+++ b/src/client/views/collections/CollectionTreeView.scss
@@ -23,6 +23,10 @@
         list-style: none;
         padding-left: 20px;
         margin-bottom: 1px; // otherwise vertical scrollbars may pop up for no apparent reason....
+        .contentFittingDocumentView  {
+            width: unset;
+            height: unset;
+        }
     }
 
 
diff --git a/src/client/views/collections/TreeView.scss b/src/client/views/collections/TreeView.scss
index cc6267f45..816dc0ffa 100644
--- a/src/client/views/collections/TreeView.scss
+++ b/src/client/views/collections/TreeView.scss
@@ -65,15 +65,6 @@
     cursor: pointer;
 }
 
-.treeView-borderoutline {
-    ul {
-        .contentFittingDocumentView  {
-            width: unset;
-            height: unset;
-        }
-    }
-}
-
 .treeView-borderoutline,
 .treeView-border {
     display: flex;
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 5982934ff..843bec6de 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -409,12 +409,13 @@ export class TreeView extends React.Component<TreeViewProps> {
                         [...this.props.renderedIds, this.doc[Id]], this.props.onCheckedClick, this.props.onChildClick, this.props.skipFields, false, this.props.whenActiveChanged, this.props.dontRegisterView)}
             </ul >;
         } else if (this.treeViewExpandedView === "fields") {
-            return <ul key={this.doc[Id] + this.doc.title}><div style={{ display: "inline-block" }} >
-                {this.expandedField}
-            </div></ul>;
-        } else {
-            return this.renderEmbeddedDocument(false);
+            return <ul key={this.doc[Id] + this.doc.title}>
+                <div style={{ display: "inline-block" }} >
+                    {this.expandedField}
+                </div>
+            </ul>;
         }
+        return <ul>{this.renderEmbeddedDocument(false)}</ul>;
     }
 
     get onCheckedClick() { return this.doc.type === DocumentType.COL ? undefined : this.props.onCheckedClick?.() ?? ScriptCast(this.doc.onCheckedClick); }
@@ -583,15 +584,18 @@ export class TreeView extends React.Component<TreeViewProps> {
     }
 
     renderBulletHeader = (contents: JSX.Element) => {
-        return <div className={`treeView-header` + (this._editMaxWidth ? "-editing" : "")} key="titleheader"
-            ref={this._header}
-            style={{ maxWidth: this._editMaxWidth }}
-            onClick={this.ignoreEvent}
-            onPointerDown={this.ignoreEvent}
-            onPointerEnter={this.onPointerEnter}
-            onPointerLeave={this.onPointerLeave}>
-            {contents}
-        </div>;
+        return <>
+            <div className={`treeView-header` + (this._editMaxWidth ? "-editing" : "")} key="titleheader"
+                ref={this._header}
+                style={{ maxWidth: this._editMaxWidth }}
+                onClick={this.ignoreEvent}
+                onPointerDown={this.ignoreEvent}
+                onPointerEnter={this.onPointerEnter}
+                onPointerLeave={this.onPointerLeave}>
+                {contents}
+            </div>
+            {this.renderBorder}
+        </>;
     }
 
     // renders the text version of a document as the header (e.g., useful for Slide views where the "")
@@ -668,24 +672,16 @@ export class TreeView extends React.Component<TreeViewProps> {
         else this._editMaxWidth = "";
 
         const hideTitle = this.doc.treeViewHideHeader || this.outlineMode;
-        return hideTitle && !StrCast(Doc.LayoutField(this.doc)).includes("CollectionView") ?
-            this.renderContent
-            :
-            <div className={`treeView-container${this._dref?.docView?.contentsActive() ? "-active" : ""}`}
-                ref={this.createTreeDropTarget}
-                onPointerDown={e => this.props.active(true) && SelectionManager.DeselectAll()}
-                onKeyDown={this.onKeyDown}>
-                {hideTitle ?
-                    <li className="collection-child">
-                        {this.renderBulletHeader(this.renderDocumentAsHeader)}
-                        {this.renderBorder}
-                    </li> :
-                    <li className="collection-child">
-                        {this.renderBulletHeader(this.renderTitleAsHeader)}
-                        {this.renderBorder}
-                    </li>
-                }
-            </div>;
+        return <div className={`treeView-container${this._dref?.docView?.contentsActive() ? "-active" : ""}`}
+            ref={this.createTreeDropTarget}
+            onPointerDown={e => this.props.active(true) && SelectionManager.DeselectAll()}
+            onKeyDown={this.onKeyDown}>
+            <li className="collection-child">
+                {hideTitle && this.doc.type !== DocumentType.RTF ?
+                    this.renderEmbeddedDocument(false) :
+                    this.renderBulletHeader(hideTitle ? this.renderDocumentAsHeader : this.renderTitleAsHeader)}
+            </li>
+        </div>;
     }
 
     public static sortDocs(childDocs: Doc[], criterion: string | undefined) {
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 199b77408..6b7a93747 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -23,11 +23,10 @@ import { CompiledScript, CompileScript } from "../../util/Scripting";
 import { SelectionManager } from "../../util/SelectionManager";
 import { SharingManager } from "../../util/SharingManager";
 import { SnappingManager } from "../../util/SnappingManager";
-import { Transform } from "../../util/Transform";
 import { undoBatch } from "../../util/UndoManager";
 import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView";
-import { CollectionView } from "../collections/CollectionView";
 import { ViewBoxAnnotatableComponent } from "../DocComponent";
+import { FieldViewProps } from "../nodes/FieldView";
 import { FormattedTextBox } from "../nodes/formattedText/FormattedTextBox";
 import { FormattedTextBoxComment } from "../nodes/formattedText/FormattedTextBoxComment";
 import { LinkDocPreview } from "../nodes/LinkDocPreview";
@@ -36,7 +35,6 @@ import { PDFMenu } from "./PDFMenu";
 import "./PDFViewer.scss";
 const pdfjs = require('pdfjs-dist/es5/build/pdf.js');
 import React = require("react");
-import { FieldViewProps } from "../nodes/FieldView";
 const PDFJSViewer = require("pdfjs-dist/web/pdf_viewer");
 const pdfjsLib = require("pdfjs-dist");
 const _global = (window /* browser */ || global /* node */) as any;
-- 
cgit v1.2.3-70-g09d2


From 890dd1c3d8d6a00cf3111972c20f7b5b9cb09085 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Sat, 12 Dec 2020 22:52:26 -0500
Subject: made conentScaling a DocumentView-only prop

---
 src/client/views/MainView.tsx                                |  4 ----
 src/client/views/StyleProvider.tsx                           | 12 ++++++++++--
 src/client/views/TemplateMenu.tsx                            |  1 -
 src/client/views/collections/CollectionStackingView.tsx      |  5 +++--
 src/client/views/collections/TabDocView.tsx                  |  4 ++--
 src/client/views/collections/TreeView.tsx                    |  9 +++++----
 .../collectionFreeForm/CollectionFreeFormView.tsx            |  7 ++++---
 src/client/views/nodes/AudioBox.tsx                          |  3 ++-
 src/client/views/nodes/CollectionFreeFormDocumentView.tsx    |  3 ++-
 src/client/views/nodes/ColorBox.tsx                          |  2 +-
 src/client/views/nodes/ContentFittingDocumentView.tsx        |  9 ++++-----
 src/client/views/nodes/DocumentView.tsx                      |  7 ++++---
 src/client/views/nodes/ImageBox.tsx                          |  2 +-
 src/client/views/nodes/KeyValuePair.tsx                      |  1 -
 src/client/views/nodes/LinkAnchorBox.tsx                     |  2 +-
 src/client/views/nodes/PDFBox.tsx                            |  2 +-
 src/client/views/nodes/ScreenshotBox.tsx                     |  2 +-
 src/client/views/nodes/VideoBox.tsx                          |  2 +-
 src/client/views/nodes/WebBox.tsx                            | 10 ++++------
 src/client/views/nodes/formattedText/FormattedTextBox.tsx    |  8 ++++----
 src/client/views/pdf/PDFViewer.tsx                           |  5 ++---
 src/client/views/presentationview/PresElementBox.tsx         |  2 +-
 22 files changed, 53 insertions(+), 49 deletions(-)

(limited to 'src/client/views/pdf/PDFViewer.tsx')

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index d55d43623..b8c7a1a73 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -465,7 +465,6 @@ export class MainView extends React.Component {
                     removeDocument={this.remButtonDoc}
                     onClick={undefined}
                     ScreenToLocalTransform={this.buttonBarXf}
-                    ContentScaling={returnOne}
                     PanelWidth={this.flyoutWidthFunc}
                     PanelHeight={this.getContentsHeight}
                     renderDepth={0}
@@ -529,7 +528,6 @@ export class MainView extends React.Component {
                 styleProvider={DefaultStyleProvider}
                 removeDocument={undefined}
                 ScreenToLocalTransform={Transform.Identity}
-                ContentScaling={returnOne}
                 PanelWidth={this.getPWidth}
                 PanelHeight={this.getPHeight}
                 renderDepth={0}
@@ -568,7 +566,6 @@ export class MainView extends React.Component {
                     focus={returnFalse}
                     PanelWidth={() => 500}
                     PanelHeight={() => 800}
-                    ContentScaling={returnOne}
                     docFilters={returnEmptyFilter}
                     docRangeFilters={returnEmptyFilter}
                     searchFilterDocs={returnEmptyDoclist}
@@ -634,7 +631,6 @@ export class MainView extends React.Component {
                             focus={returnFalse}
                             PanelWidth={() => 500}
                             PanelHeight={() => 800}
-                            ContentScaling={returnOne}
                             docFilters={returnEmptyFilter}
                             docRangeFilters={returnEmptyFilter}
                             searchFilterDocs={returnEmptyDoclist}
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 6a534a979..128c3cb96 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -16,6 +16,7 @@ import React = require("react");
 import Color = require('color');
 import { listSpec } from '../../fields/Schema';
 import { MainView } from './MainView';
+import { FieldViewProps } from './nodes/FieldView';
 
 export enum StyleLayers {
     Background = "background"
@@ -59,10 +60,17 @@ function toggleBackground(doc: Doc) {
     }), "toggleBackground");
 }
 
+export function testDocProps(toBeDetermined: any): toBeDetermined is DocumentViewProps {
+    if (toBeDetermined.ContentScaling) {
+        return true;
+    }
+    return false;
+}
+
 //
 // a preliminary implementation of a dash style sheet for setting rendering properties of documents nested within a Tab
 // 
-export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string): any {
+export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps | DocumentViewProps>, property: string): any {
     switch (property.split(":")[0]) {
         case StyleProp.DocContents: return undefined;
         case StyleProp.WidgetColor: return darkScheme() ? "lightgrey" : "dimgrey";
@@ -121,7 +129,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
                     `${darkScheme() ? "rgb(30, 32, 31) " : "#9c9396 "} ${StrCast(doc.boxShadow, "0.2vw 0.2vw 0.8vw")}`;
                 default:
                     return doc.z ? `#9c9396  ${StrCast(doc?.boxShadow, "10px 10px 0.9vw")}` :  // if it's a floating doc, give it a big shadow
-                        backgroundHalo(doc) && doc.type !== DocumentType.INK ? (`${props?.styleProvider?.(doc, props, StyleProp.BackgroundColor)} ${StrCast(doc.boxShadow, `0vw 0vw ${(isBackground() ? 100 : 50) / (props?.ContentScaling() || 1)}px`)}`) :  // if it's just in a cluster, make the shadown roughly match the cluster border extent
+                        backgroundHalo(doc) && doc.type !== DocumentType.INK ? (`${props?.styleProvider?.(doc, props, StyleProp.BackgroundColor)} ${StrCast(doc.boxShadow, `0vw 0vw ${(isBackground() ? 100 : 50) / ((testDocProps(props) && props?.ContentScaling()) || 1)}px`)}`) :  // if it's just in a cluster, make the shadown roughly match the cluster border extent
                             isBackground() ? undefined :  // if it's a background & has a cluster color, make the shadow spread really big
                                 StrCast(doc.boxShadow, "");
             }
diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx
index 203274681..ddba71dd2 100644
--- a/src/client/views/TemplateMenu.tsx
+++ b/src/client/views/TemplateMenu.tsx
@@ -139,7 +139,6 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
                 dropAction={undefined}
                 active={returnTrue}
                 parentActive={returnFalse}
-                ContentScaling={returnOne}
                 bringToFront={emptyFunction}
                 focus={emptyFunction}
                 whenActiveChanged={emptyFunction}
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index e8165f673..510e47b20 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -29,6 +29,7 @@ import { CollectionStackingViewFieldColumn } from "./CollectionStackingViewField
 import { CollectionSubView } from "./CollectionSubView";
 import { CollectionViewType } from "./CollectionView";
 import { StyleProp } from "../StyleProvider";
+import { FieldViewProps } from "../nodes/FieldView";
 const _global = (window /* browser */ || global /* node */) as any;
 
 type StackingDocument = makeInterface<[typeof collectionSchema, typeof documentSchema]>;
@@ -61,7 +62,7 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
     @computed get numGroupColumns() { return this.isStackingView ? Math.max(1, this.Sections.size + (this.showAddAGroup ? 1 : 0)) : 1; }
     @computed get showAddAGroup() { return (this.pivotField && (this.chromeStatus !== 'view-mode' && this.chromeStatus !== 'disabled')); }
     @computed get columnWidth() {
-        return Math.min(this.props.PanelWidth() / this.props.ContentScaling() /* / NumCast(this.layoutDoc._viewScale, 1)*/ - 2 * this.xMargin,
+        return Math.min(this.props.PanelWidth() /* / NumCast(this.layoutDoc._viewScale, 1)*/ - 2 * this.xMargin,
             this.isStackingView ? Number.MAX_VALUE : this.layoutDoc._columnWidth === -1 ? this.props.PanelWidth() - 2 * this.xMargin : NumCast(this.layoutDoc._columnWidth, 250));
     }
     @computed get NodeWidth() { return this.props.PanelWidth() - this.gridGap; }
@@ -189,7 +190,7 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
     getDisplayDoc(doc: Doc, dxf: () => Transform, width: () => number) {
         const dataDoc = (!doc.isTemplateDoc && !doc.isTemplateForField && !doc.PARAMS) ? undefined : this.props.DataDoc;
         const height = () => this.getDocHeight(doc);
-        const styleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, property: string) => {
+        const styleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps | FieldViewProps>, property: string) => {
             if (property === StyleProp.Opacity && doc) {
                 if (this.props.childOpacity) {
                     return this.props.childOpacity();
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 8b5143013..fe929abc5 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -33,6 +33,7 @@ import { List } from '../../../fields/List';
 import { DocumentType } from '../../documents/DocumentTypes';
 import Color = require('color');
 import { StyleProp, DefaultStyleProvider, DefaultLayerProvider, StyleLayers } from '../StyleProvider';
+import { FieldViewProps } from '../nodes/FieldView';
 const _global = (window /* browser */ || global /* node */) as any;
 
 interface TabDocViewProps {
@@ -352,7 +353,6 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                     addDocument={returnFalse}
                     moveDocument={returnFalse}
                     removeDocument={returnFalse}
-                    ContentScaling={returnOne}
                     PanelWidth={this.returnMiniSize}
                     PanelHeight={this.returnMiniSize}
                     ScreenToLocalTransform={this.ScreenToLocalTransform}
@@ -389,7 +389,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
     active = () => this._isActive;
 
 
-    public static miniStyleProvider = (doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string): any => {
+    public static miniStyleProvider = (doc: Opt<Doc>, props: Opt<DocumentViewProps | FieldViewProps>, property: string): any => {
         if (doc) {
             switch (property.split(":")[0]) {
                 default: return DefaultStyleProvider(doc, props, property);
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 843bec6de..11ff4ca3b 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -29,7 +29,8 @@ import { CollectionTreeView } from './CollectionTreeView';
 import { CollectionView, CollectionViewType } from './CollectionView';
 import "./TreeView.scss";
 import React = require("react");
-import { StyleProp } from '../StyleProvider';
+import { StyleProp, testDocProps } from '../StyleProvider';
+import { FieldViewProps } from '../nodes/FieldView';
 
 export interface TreeViewProps {
     document: Doc;
@@ -497,13 +498,13 @@ export class TreeView extends React.Component<TreeViewProps> {
             e.preventDefault();
         }
     }
-    titleStyleProvider = (doc: (Doc | undefined), props: Opt<DocumentViewProps>, property: string): any => {
+    titleStyleProvider = (doc: (Doc | undefined), props: Opt<DocumentViewProps | FieldViewProps>, property: string): any => {
         if (!doc || doc !== this.doc) return this.props?.treeView?.props.styleProvider?.(doc, props, property); // properties are inherited from the CollectionTreeView, not the hierarchical parent in the treeView
 
         switch (property.split(":")[0]) {
             case StyleProp.Opacity: return this.outlineMode ? undefined : 1;
             case StyleProp.BackgroundColor: return StrCast(doc._backgroundColor, StrCast(doc.backgroundColor));
-            case StyleProp.DocContents: return !props?.treeViewDoc ? (null) :
+            case StyleProp.DocContents: return testDocProps(props) && !props?.treeViewDoc ? (null) :
                 <div className="treeView-label" style={{    // just render a title for a tree view label (identified by treeViewDoc being set in 'props')
                     maxWidth: props?.PanelWidth() || undefined,
                     background: props?.styleProvider?.(doc, props, StyleProp.BackgroundColor),
@@ -513,7 +514,7 @@ export class TreeView extends React.Component<TreeViewProps> {
             case StyleProp.Decorations: return (null);
         }
     }
-    embeddedStyleProvider = (doc: (Doc | undefined), props: Opt<DocumentViewProps>, property: string): any => {
+    embeddedStyleProvider = (doc: (Doc | undefined), props: Opt<DocumentViewProps | FieldViewProps>, property: string): any => {
         if (property.startsWith(StyleProp.Decorations)) return (null);
         return this.props?.treeView?.props.styleProvider?.(doc, props, property); // properties are inherited from the CollectionTreeView, not the hierarchical parent in the treeView
     }
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index b8576681d..3f7eb24f8 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -49,6 +49,7 @@ import React = require("react");
 import { CurrentUserUtils } from "../../../util/CurrentUserUtils";
 import { StyleProp, StyleLayers } from "../../StyleProvider";
 import { DocumentDecorations } from "../../DocumentDecorations";
+import { FieldViewProps } from "../../nodes/FieldView";
 
 export const panZoomSchema = createSchema({
     _panX: "number",
@@ -116,7 +117,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
     @computed get backgroundActive() { return this.props.layerProvider?.(this.layoutDoc) === false && (this.props.ContainingCollectionView?.active() || this.props.active()); }
     @computed get fitToContentScaling() { return this.fitToContent ? NumCast(this.layoutDoc.fitToContentScaling, 1) : 1; }
     @computed get fitToContent() { return (this.props.fitToBox || this.Document._fitToBox) && !this.isAnnotationOverlay; }
-    @computed get parentScaling() { return this.props.ContentScaling && this.fitToContent ? this.props.ContentScaling() : 1; }
+    @computed get parentScaling() { return 1; }
     @computed get contentBounds() { return aggregateBounds(this._layoutElements.filter(e => e.bounds && !e.bounds.z).map(e => e.bounds!), NumCast(this.layoutDoc._xPadding, 10), NumCast(this.layoutDoc._yPadding, 10)); }
     @computed get nativeWidth() { return this.fitToContent ? 0 : returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.Document)); }
     @computed get nativeHeight() { return this.fitToContent ? 0 : returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.Document)); }
@@ -405,7 +406,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
         }
     }
 
-    getClusterColor = (doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string) => {
+    getClusterColor = (doc: Opt<Doc>, props: Opt<DocumentViewProps | FieldViewProps>, property: string) => {
         let styleProp = this.props.styleProvider?.(doc, props, property);  // bcz: check 'props'  used to be renderDepth + 1
         if (property !== StyleProp.BackgroundColor) return styleProp;
         const cluster = NumCast(doc?.cluster);
@@ -1277,7 +1278,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
     @undoBatch
     @action
     toggleNativeDimensions = () => {
-        Doc.toggleNativeDimensions(this.layoutDoc, this.props.ContentScaling(), this.props.NativeWidth?.() || 0, this.props.NativeHeight?.() || 0);
+        Doc.toggleNativeDimensions(this.layoutDoc, 1, this.props.NativeWidth?.() || 0, this.props.NativeHeight?.() || 0);
     }
 
     @undoBatch
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index b495cdd1b..7b721786f 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -539,7 +539,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD
 
     rangeScript = () => AudioBox.RangeScript;
     labelScript = () => AudioBox.LabelScript;
-    static audioStyleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, property: string) => {
+    static audioStyleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps | FieldViewProps>, property: string) => {
         if (property === StyleProp.BackgroundColor) return "transparent";
         if (property === StyleProp.PointerEvents) return "none";
     }
@@ -554,6 +554,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD
                 rootSelected={returnFalse}
                 LayoutTemplate={undefined}
                 ContainingCollectionDoc={this.props.Document}
+                ContentScaling={returnOne}
                 removeDocument={this.removeDocument}
                 parentActive={returnTrue}
                 onClick={this.layoutDoc.playOnClick ? script : undefined}
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 1b47f4551..3f473460f 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -17,6 +17,7 @@ import { ContentFittingDocumentView } from "./ContentFittingDocumentView";
 import { DocumentView, DocumentViewProps } from "./DocumentView";
 import React = require("react");
 import { StyleProp } from "../StyleProvider";
+import { FieldViewProps } from "./FieldView";
 
 export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
     dataProvider?: (doc: Doc, replica: string) => { x: number, y: number, zIndex?: number, opacity?: number, highlight?: boolean, z: number, transition?: string } | undefined;
@@ -59,7 +60,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
     @computed get nativeWidth() { return returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, undefined, this.freezeDimensions)); }
     @computed get nativeHeight() { return returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, undefined, this.freezeDimensions)); }
 
-    styleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, property: string) => {
+    styleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps | FieldViewProps>, property: string) => {
         if (property === StyleProp.Opacity && doc === this.layoutDoc) return this.Opacity; // only change the opacity for this specific document, not its children
         return this.props.styleProvider?.(doc, props, property);
     }
diff --git a/src/client/views/nodes/ColorBox.tsx b/src/client/views/nodes/ColorBox.tsx
index 4fb350b55..52236a648 100644
--- a/src/client/views/nodes/ColorBox.tsx
+++ b/src/client/views/nodes/ColorBox.tsx
@@ -57,7 +57,7 @@ export class ColorBox extends ViewBoxBaseComponent<FieldViewProps, ColorDocument
         const selDoc = SelectionManager.SelectedDocuments()?.[0]?.rootDoc;
         return <div className={`colorBox-container${this.active() ? "-interactive" : ""}`}
             onPointerDown={e => e.button === 0 && !e.ctrlKey && e.stopPropagation()} onClick={e => { (e.nativeEvent as any).stuff = true; e.stopPropagation(); }}
-            style={{ transform: `scale(${this.props.ContentScaling()})`, width: `${100 / this.props.ContentScaling()}%`, height: `${100 / this.props.ContentScaling()}%` }} >
+            style={{ width: `${100}%`, height: `${100}%` }} >
 
             <SketchPicker onChange={ColorBox.switchColor} presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', '#FFFFFF', '#f1efeb', 'transparent']}
                 color={StrCast(ActiveInkPen()?.backgroundColor,
diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx
index 122231f47..f2540dfa7 100644
--- a/src/client/views/nodes/ContentFittingDocumentView.tsx
+++ b/src/client/views/nodes/ContentFittingDocumentView.tsx
@@ -1,13 +1,12 @@
 import React = require("react");
-import { computed, observable, action } from "mobx";
+import { action, computed, observable } from "mobx";
 import { observer } from "mobx-react";
-import { Doc, WidthSym, HeightSym } from "../../../fields/Doc";
+import { Doc } from "../../../fields/Doc";
 import { TraceMobx } from "../../../fields/util";
-import { emptyFunction, OmitKeys, returnVal, returnOne } from "../../../Utils";
+import { emptyFunction, OmitKeys, returnOne, returnVal } from "../../../Utils";
 import { DocumentView, DocumentViewProps } from "../nodes/DocumentView";
-import "./ContentFittingDocumentView.scss";
 import { StyleProp } from "../StyleProvider";
-import { StrCast } from "../../../fields/Types";
+import "./ContentFittingDocumentView.scss";
 
 interface ContentFittingDocumentViewProps {
     dontCenter?: "x" | "y" | "xy";
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index c1ba1c73a..10b406fd4 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -43,10 +43,11 @@ import { TaskCompletionBox } from './TaskCompletedBox';
 import React = require("react");
 import { CollectionFreeFormDocumentView } from "./CollectionFreeFormDocumentView";
 import { StyleProp, StyleLayers } from "../StyleProvider";
+import { FieldViewProps } from "./FieldView";
 
 export type DocAfterFocusFunc = (notFocused: boolean) => boolean;
 export type DocFocusFunc = (doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: DocAfterFocusFunc, dontCenter?: boolean, focused?: boolean) => void;
-export type StyleProviderFunc = (doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string) => any;
+export type StyleProviderFunc = (doc: Opt<Doc>, props: Opt<DocumentViewProps | FieldViewProps>, property: string) => any;
 export interface DocumentViewSharedProps {
     renderDepth: number;
     Document: Doc;
@@ -58,7 +59,6 @@ export interface DocumentViewSharedProps {
     PanelHeight: () => number;
     NativeWidth?: () => number;
     NativeHeight?: () => number;
-    ContentScaling: () => number; // scaling the DocumentView does to transform its contents into its panel & needed by ScreenToLocal
     layerProvider?: (doc: Doc, assign?: boolean) => boolean;
     styleProvider?: StyleProviderFunc;
     focus: DocFocusFunc;
@@ -93,6 +93,7 @@ export interface DocumentViewProps extends DocumentViewSharedProps {
     dragDivName?: string;
     contentPointerEvents?: string;
     radialMenu?: String[];
+    ContentScaling: () => number; // scaling the DocumentView does to transform its contents into its panel & needed by ScreenToLocal
     contentFittingScaling?: () => number;// scaling done outside the document view (eg in ContentFittingDocumentView) to fit contents into panel (needed for ScreenToLocal but not needed by DocumentView to scale its content)
     LayoutTemplate?: () => Opt<Doc>;
     contextMenuItems?: () => { script: ScriptField, label: string }[];
@@ -972,7 +973,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     hideLinkAnchor = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg: boolean, doc) => flg && (doc.hidden = true), true)
     anchorPanelWidth = () => this.props.PanelWidth() || 1;
     anchorPanelHeight = () => this.props.PanelHeight() || 1;
-    anchorStyleProvider = (doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string): any => {
+    anchorStyleProvider = (doc: Opt<Doc>, props: Opt<DocumentViewProps | FieldViewProps>, property: string): any => {
         switch (property.split(":")[0]) {
             case StyleProp.BackgroundColor: return "transparent";
             case StyleProp.HideLinkButton: return true;
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 44df00709..374f964e3 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -67,7 +67,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps, ImageD
     @observable static _showControls: boolean;
     @observable uploadIcon = uploadIcons.idle;
 
-    @computed get contentScaling() { return this.props.ContentScaling(); }
+    @computed get contentScaling() { return 1; }
 
     protected createDropTarget = (ele: HTMLDivElement) => {
         this._dropDisposer?.();
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index aaf544c50..3c10cc5fe 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -76,7 +76,6 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
             PanelHeight: this.props.PanelHeight,
             addDocTab: returnFalse,
             pinToPres: returnZero,
-            ContentScaling: returnOne
         };
         const contents = <FieldView {...props} />;
         // let fieldKey = Object.keys(props.Document).indexOf(props.fieldKey) !== -1 ? props.fieldKey : "(" + props.fieldKey + ")";
diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx
index abefc6561..d0048c67b 100644
--- a/src/client/views/nodes/LinkAnchorBox.tsx
+++ b/src/client/views/nodes/LinkAnchorBox.tsx
@@ -146,7 +146,7 @@ export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps, LinkAnch
                 background,
                 left: `calc(${x}% - ${small ? 2.5 : 7.5}px)`,
                 top: `calc(${y}% - ${small ? 2.5 : 7.5}px)`,
-                transform: `scale(${anchorScale / this.props.ContentScaling()})`
+                transform: `scale(${anchorScale})`
             }} >
             {!this._editing && !this._forceOpen ? (null) :
                 <Flyout anchorPoint={anchorPoints.LEFT_TOP} content={flyout} open={this._forceOpen ? true : undefined} onOpen={() => this._isOpen = true} onClose={action(() => this._isOpen = this._forceOpen = this._editing = false)}>
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index a2f3fb2d1..b34c7966b 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -183,7 +183,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum
         ContextMenu.Instance.addItem({ description: "Options...", subitems: funcs, icon: "asterisk" });
     }
 
-    @computed get contentScaling() { return this.props.ContentScaling(); }
+    @computed get contentScaling() { return 1; }
     @computed get renderTitleBox() {
         const classname = "pdfBox" + (this.active() ? "-interactive" : "");
         return <div className={classname} >
diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx
index 713511a94..456de7ede 100644
--- a/src/client/views/nodes/ScreenshotBox.tsx
+++ b/src/client/views/nodes/ScreenshotBox.tsx
@@ -167,7 +167,7 @@ export class ScreenshotBox extends ViewBoxBaseComponent<FieldViewProps, Screensh
     contentFunc = () => [this.content];
     render() {
         return (<div className="videoBox" onContextMenu={this.specificContextMenu}
-            style={{ transform: `scale(${this.props.ContentScaling()})`, width: `${100 / this.props.ContentScaling()}%`, height: `${100 / this.props.ContentScaling()}%` }} >
+            style={{ width: `${100}%`, height: `${100}%` }} >
             <div className="videoBox-viewer" >
                 <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit}
                     PanelHeight={this.props.PanelHeight}
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 90a5dee23..893236857 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -413,7 +413,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
         return this.addDocument(doc);
     }
 
-    @computed get contentScaling() { return this.props.ContentScaling(); }
+    @computed get contentScaling() { return 1; }
     contentFunc = () => [this.youtubeVideoId ? this.youtubeContent : this.content];
     render() {
         return (<div className="videoBox" onContextMenu={this.specificContextMenu}
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 47464d794..511e8f537 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -457,7 +457,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
 
         return (<>
             <div className={"webBox-cont" + (this.props.isSelected() && Doc.GetSelectedTool() === InkTool.None && !DocumentDecorations.Instance?.Interacting ? "-interactive" : "")}
-                style={{ width: NumCast(this.layoutDoc[this.fieldKey + "-contentWidth"]) || (Number.isFinite(this.props.ContentScaling()) ? `${Math.max(100, 100 / this.props.ContentScaling())}% ` : "100%") }}
+                style={{ width: "100%" }}
                 onWheel={this.onPostWheel} onPointerDown={this.onPostPointer} onPointerMove={this.onPostPointer} onPointerUp={this.onPostPointer}>
                 {view}
             </div>
@@ -648,14 +648,12 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
     marqueeing = () => this._marqueeing;
     scrollXf = () => this.props.ScreenToLocalTransform().translate(NumCast(this.layoutDoc._scrollLeft), NumCast(this.layoutDoc._scrollTop));
     render() {
-        const scaling = Number.isFinite(this.props.ContentScaling()) ? this.props.ContentScaling() || 1 : 1;
         return (<div className="webBox" ref={this._mainCont} >
             <div className={`webBox-container`}
                 style={{
                     position: undefined,
-                    transform: `scale(${scaling})`,
-                    width: `${100 / scaling}% `,
-                    height: `${100 / scaling}% `,
+                    width: `${100}% `,
+                    height: `${100}% `,
                     pointerEvents: this.props.layerProvider?.(this.layoutDoc) === false ? "none" : undefined
                 }}
                 onContextMenu={this.specificContextMenu}>
@@ -663,7 +661,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
                 {this.content}
                 <div className={"webBox-outerContent"} ref={this._outerRef}
                     style={{
-                        width: `${Math.max(100, 100 / scaling)}% `,
+                        width: `${100}% `,
                         pointerEvents: this.layoutDoc.isAnnotating && this.props.layerProvider?.(this.layoutDoc) !== false ? "all" : "none"
                     }}
                     onWheel={e => {
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 0beea2bcd..feb5e63b2 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -581,7 +581,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
     @undoBatch
     @action
     toggleNativeDimensions = () => {
-        Doc.toggleNativeDimensions(this.layoutDoc, this.props.ContentScaling(), this.props.NativeWidth?.() || 0, this.props.NativeHeight?.() || 0);
+        Doc.toggleNativeDimensions(this.layoutDoc, 1, this.props.NativeWidth?.() || 0, this.props.NativeHeight?.() || 0);
     }
 
     public static get DefaultLayout(): Doc | string | undefined {
@@ -1609,7 +1609,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
             />;
     }
 
-    sidebarContentScaling = () => this.props.ContentScaling() * NumCast(this.layoutDoc._viewScale, 1);
+    sidebarContentScaling = () => NumCast(this.layoutDoc._viewScale, 1);
     @computed get sidebarCollection() {
         const fitToBox = this.props.Document._fitToBox;
         const collectionProps: SubCollectionViewProps & collectionFreeformViewProps = {
@@ -1647,13 +1647,13 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
 
     @computed get sidebarWidthPercent() { return StrCast(this.layoutDoc._sidebarWidthPercent, "0%"); }
     sidebarWidth = () => Number(this.sidebarWidthPercent.substring(0, this.sidebarWidthPercent.length - 1)) / 100 * this.props.PanelWidth();
-    sidebarScreenToLocal = () => this.props.ScreenToLocalTransform().translate(-(this.props.PanelWidth() - this.sidebarWidth()) / this.props.ContentScaling(), 0).scale(1 / NumCast(this.layoutDoc._viewScale, 1));
+    sidebarScreenToLocal = () => this.props.ScreenToLocalTransform().translate(-(this.props.PanelWidth() - this.sidebarWidth()), 0).scale(1 / NumCast(this.layoutDoc._viewScale, 1));
     @computed get sidebarColor() { return StrCast(this.layoutDoc.sidebarColor, StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], "#e4e4e4")); }
     render() {
         TraceMobx();
         const selected = this.props.isSelected();
         const active = this.active();
-        const scale = this.props.hideOnLeave ? 1 : this.props.ContentScaling() * NumCast(this.layoutDoc._viewScale, 1);
+        const scale = this.props.hideOnLeave ? 1 : NumCast(this.layoutDoc._viewScale, 1);
         const rounded = StrCast(this.layoutDoc.borderRounding) === "100%" ? "-rounded" : "";
         const interactive = (Doc.GetSelectedTool() === InkTool.None || SnappingManager.GetIsDragging()) && (this.layoutDoc.z || this.props.layerProvider?.(this.layoutDoc) !== false);
         if (!selected && FormattedTextBoxComment.textBox === this) setTimeout(() => FormattedTextBoxComment.Hide());
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 6b7a93747..fc547c60f 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -370,7 +370,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
     @action
     scrollToAnnotation = (scrollToAnnotation: Doc) => {
         if (scrollToAnnotation) {
-            const offset = (this.props.PanelHeight() / this.props.ContentScaling()) / 2;
+            const offset = this.props.PanelHeight() / 2;
             this._mainCont.current && smoothScroll(500, this._mainCont.current, NumCast(scrollToAnnotation.y) - offset);
             Doc.linkFollowHighlight(scrollToAnnotation);
         }
@@ -737,7 +737,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
     @computed get pdfViewerDiv() {
         return <div className={"pdfViewerDash-text" + ((this.props.isSelected() || this.props.isChildActive()) ? "-selected" : "")} ref={this._viewer} />;
     }
-    @computed get contentScaling() { return this.props.ContentScaling(); }
+    @computed get contentScaling() { return 1; }
     @computed get standinViews() {
         return <>
             {this._showCover ? this.getCoverImage() : (null)}
@@ -758,7 +758,6 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
                 overflowX: this._zoomed !== 1 ? "scroll" : undefined,
                 width: !this.props.Document._fitWidth && (window.screen.width > 600) ? Doc.NativeWidth(this.props.Document) : `${100 / this.contentScaling}%`,
                 height: !this.props.Document._fitWidth && (window.screen.width > 600) ? Doc.NativeHeight(this.props.Document) : `${100 / this.contentScaling}%`,
-                transform: `scale(${this.props.ContentScaling()})`
             }}  >
             {this.pdfViewerDiv}
             {this.annotationLayer}
diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx
index 3b6b0259d..8615ba81d 100644
--- a/src/client/views/presentationview/PresElementBox.tsx
+++ b/src/client/views/presentationview/PresElementBox.tsx
@@ -78,7 +78,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
     // embedWidth = () => this.props.PanelWidth();
     // embedHeight = () => Math.min(this.props.PanelWidth() - 20, this.props.PanelHeight() - this.collapsedHeight);
     embedWidth = (): number => this.props.PanelWidth() - 35;
-    styleProvider = (doc: (Doc | undefined), props: Opt<DocumentViewProps>, property: string): any => {
+    styleProvider = (doc: (Doc | undefined), props: Opt<DocumentViewProps | FieldViewProps>, property: string): any => {
         if (property === StyleProp.Opacity) return 1;
         return this.props.styleProvider?.(doc, props, property);
     }
-- 
cgit v1.2.3-70-g09d2


From 898227ac1cecb3cd8d4be4ed00ab4190713f006a Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Sun, 13 Dec 2020 14:25:33 -0500
Subject: adding documentView as a fieldView prop to make contetnScaling
 available in PDFview

---
 src/client/views/nodes/DocumentView.tsx | 2 ++
 src/client/views/nodes/PDFBox.tsx       | 5 +++--
 src/client/views/pdf/PDFViewer.tsx      | 6 ++++--
 3 files changed, 9 insertions(+), 4 deletions(-)

(limited to 'src/client/views/pdf/PDFViewer.tsx')

diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index f766976d0..6ca3ffbee 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -52,6 +52,7 @@ export interface DocumentViewSharedProps {
     renderDepth: number;
     Document: Doc;
     DataDoc?: Doc;
+    DocumentView?: DocumentView;
     ContainingCollectionView: Opt<CollectionView>;
     ContainingCollectionDoc: Opt<Doc>;
     CollectionFreeFormDocumentView?: () => CollectionFreeFormDocumentView;
@@ -913,6 +914,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             }}>
             <DocumentContentsView key={1}
                 renderDepth={this.props.renderDepth}
+                DocumentView={this}
                 Document={this.props.Document}
                 DataDoc={this.props.DataDoc}
                 ContainingCollectionView={this.props.ContainingCollectionView}
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index b34c7966b..18ded4f3b 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -9,7 +9,7 @@ import { makeInterface } from "../../../fields/Schema";
 import { Cast, NumCast } from "../../../fields/Types";
 import { PdfField } from "../../../fields/URLField";
 import { TraceMobx } from '../../../fields/util';
-import { Utils } from '../../../Utils';
+import { Utils, returnOne } from '../../../Utils';
 import { KeyCodes } from '../../util/KeyCodes';
 import { undoBatch } from '../../util/UndoManager';
 import { panZoomSchema } from '../collections/collectionFreeForm/CollectionFreeFormView';
@@ -183,7 +183,6 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum
         ContextMenu.Instance.addItem({ description: "Options...", subitems: funcs, icon: "asterisk" });
     }
 
-    @computed get contentScaling() { return 1; }
     @computed get renderTitleBox() {
         const classname = "pdfBox" + (this.active() ? "-interactive" : "");
         return <div className={classname} >
@@ -193,6 +192,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum
         </div>;
     }
 
+    contentScaling = () => this.props.DocumentView?.props.ContentScaling() || 1;
     isChildActive = (outsideReaction?: boolean) => this._isChildActive;
     @computed get renderPdfView() {
         TraceMobx();
@@ -209,6 +209,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum
                 whenActiveChanged={this.whenActiveChanged}
                 isChildActive={this.isChildActive}
                 startupLive={true}
+                ContentScaling={this.contentScaling}
             />
             {this.settingsPanel()}
         </div>;
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index fc547c60f..7696167a7 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -60,6 +60,7 @@ interface IViewerProps extends FieldViewProps {
     loaded?: (nw: number, nh: number, np: number) => void;
     isChildActive: (outsideReaction?: boolean) => boolean;
     setPdfViewer: (view: PDFViewer) => void;
+    ContentScaling: () => number;
 }
 
 /**
@@ -370,7 +371,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
     @action
     scrollToAnnotation = (scrollToAnnotation: Doc) => {
         if (scrollToAnnotation) {
-            const offset = this.props.PanelHeight() / 2;
+            const offset = (this.props.PanelHeight() / this.props.ContentScaling()) / 2;
             this._mainCont.current && smoothScroll(500, this._mainCont.current, NumCast(scrollToAnnotation.y) - offset);
             Doc.linkFollowHighlight(scrollToAnnotation);
         }
@@ -737,7 +738,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
     @computed get pdfViewerDiv() {
         return <div className={"pdfViewerDash-text" + ((this.props.isSelected() || this.props.isChildActive()) ? "-selected" : "")} ref={this._viewer} />;
     }
-    @computed get contentScaling() { return 1; }
+    @computed get contentScaling() { return this.props.ContentScaling(); }
     @computed get standinViews() {
         return <>
             {this._showCover ? this.getCoverImage() : (null)}
@@ -758,6 +759,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
                 overflowX: this._zoomed !== 1 ? "scroll" : undefined,
                 width: !this.props.Document._fitWidth && (window.screen.width > 600) ? Doc.NativeWidth(this.props.Document) : `${100 / this.contentScaling}%`,
                 height: !this.props.Document._fitWidth && (window.screen.width > 600) ? Doc.NativeHeight(this.props.Document) : `${100 / this.contentScaling}%`,
+                transform: `scale(${this.props.ContentScaling()})`
             }}  >
             {this.pdfViewerDiv}
             {this.annotationLayer}
-- 
cgit v1.2.3-70-g09d2


From f9f0d6ca06e850e0ea68d7b7b701de46d9449169 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Sun, 13 Dec 2020 20:49:48 -0500
Subject: trying to fix PDFs for fitWidth and otherwise in ContentFitting and
 CollectionFreeFormDoc containers.

---
 src/client/views/collections/TabDocView.tsx          |  2 --
 .../views/nodes/CollectionFreeFormDocumentView.tsx   | 17 +++++++++++------
 .../views/nodes/ContentFittingDocumentView.tsx       | 20 +++++++++++++++-----
 src/client/views/nodes/DocumentView.tsx              |  7 ++++++-
 src/client/views/nodes/PDFBox.tsx                    |  3 +--
 src/client/views/nodes/VideoBox.tsx                  |  7 +++++--
 src/client/views/pdf/PDFViewer.tsx                   |  8 ++++----
 7 files changed, 42 insertions(+), 22 deletions(-)

(limited to 'src/client/views/pdf/PDFViewer.tsx')

diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 40e7bc7ce..65b793adb 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -373,7 +373,6 @@ export class TabDocView extends React.Component<TabDocViewProps> {
     @computed get layerProvider() { return this._document && DefaultLayerProvider(this._document); }
     @computed get docView() {
         TraceMobx();
-        console.log("" + this._document?.title + " " + (!this._activated || !this._document || this._document._viewType === CollectionViewType.Docking))
         return !this._activated || !this._document || this._document._viewType === CollectionViewType.Docking ? (null) :
             <><ContentFittingDocumentView key={this._document[Id]} ref={action((r: ContentFittingDocumentView) => console.log(this._view = r))}
                 renderDepth={0}
@@ -411,7 +410,6 @@ export class TabDocView extends React.Component<TabDocViewProps> {
     }
 
     render() {
-        console.log("tab", this._document)
         return (
             <div className="collectionDockingView-content" style={{ height: "100%", width: "100%" }} ref={ref => {
                 if (this._mainCont = ref) {
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index b148fad12..0e790d8db 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -58,6 +58,10 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
     @computed get sizeProvider() { return this.props.sizeProvider?.(this.props.Document, this.props.replica); }
     @computed get nativeWidth() { return returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, undefined, this.props.freezeDimensions)); }
     @computed get nativeHeight() { return returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, undefined, this.props.freezeDimensions)); }
+    @computed get pointerEvents() {
+        if (this.props.pointerEvents === "none") return "none";
+        return this.props.styleProvider?.(this.Document, this.props, StyleProp.PointerEvents + (!this._contentView?.docView?.isSelected() ? ":selected" : ""));
+    }
 
     styleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps | FieldViewProps>, property: string) => {
         if (property === StyleProp.Opacity && doc === this.layoutDoc) return this.Opacity; // only change the opacity for this specific document, not its children
@@ -140,15 +144,12 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
     }
     panelWidth = () => (this.sizeProvider?.width || this.props.PanelWidth?.());
     panelHeight = () => (this.sizeProvider?.height || this.props.PanelHeight?.());
-    getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.X, -this.Y);
+    screenToLocalTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.X, -this.Y).scale(1 / this.Scaling());
     focusDoc = (doc: Doc) => this.props.focus(doc, false);
     NativeWidth = () => this.nativeWidth;
     NativeHeight = () => this.nativeHeight;
     returnThis = () => this;
-    @computed get pointerEvents() {
-        if (this.props.pointerEvents === "none") return "none";
-        return this.props.styleProvider?.(this.Document, this.props, StyleProp.PointerEvents + (!this._contentView?.docView?.isSelected() ? ":selected" : ""));
-    }
+    Scaling = () => this.Document._fitWidth ? this.props.PanelWidth() / this.NativeWidth() : 1;
     render() {
         TraceMobx();
         const backgroundColor = this.props.styleProvider?.(this.Document, this.props, StyleProp.BackgroundColor);
@@ -159,12 +160,16 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
             CollectionFreeFormDocumentView: this.returnThis,
             dragDivName: "collectionFreeFormDocumentView-container",
             styleProvider: this.styleProvider,
-            ScreenToLocalTransform: this.getTransform,
+            ScreenToLocalTransform: this.screenToLocalTransform,
+            ContentScaling: this.Scaling,
             NativeHeight: this.NativeHeight,
             NativeWidth: this.NativeWidth,
             PanelWidth: this.panelWidth,
             PanelHeight: this.panelHeight
         };
+        if (this.props.Document.type === DocumentType.PDF) {
+            console.log(divProps.NativeWidth?.());
+        }
         return <div className="collectionFreeFormDocumentView-container"
             style={{
                 boxShadow,
diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx
index 098e422b8..a673725dd 100644
--- a/src/client/views/nodes/ContentFittingDocumentView.tsx
+++ b/src/client/views/nodes/ContentFittingDocumentView.tsx
@@ -7,6 +7,8 @@ import { emptyFunction, OmitKeys, returnOne, returnVal } from "../../../Utils";
 import { DocumentView, DocumentViewProps } from "../nodes/DocumentView";
 import { StyleProp } from "../StyleProvider";
 import "./ContentFittingDocumentView.scss";
+import { DocumentType } from "../../documents/DocumentTypes";
+import { NumCast } from "../../../fields/Types";
 interface ContentFittingDocumentViewProps {
     dontCenter?: "x" | "y" | "xy";
 }
@@ -36,8 +38,9 @@ export class ContentFittingDocumentView extends React.Component<DocumentViewProp
     @computed get panelWidth() { return this.nativeWidth ? this.nativeWidth * this.nativeScaling : this.props.PanelWidth(); }
     @computed get panelHeight() {
         if (this.nativeHeight) {
-            if (this.props.Document._fitWidth)
-                return Math.min(this.props.PanelHeight(), this.panelWidth / Doc.NativeAspect(this.layoutDoc, this.props.DataDoc, this.props.freezeDimensions) || 1);
+            if (this.props.Document._fitWidth) {
+                return Math.min(this.props.PanelHeight(), NumCast(this.props.Document.scrollHeight, this.props.PanelHeight()));
+            }
             else return Math.min(this.props.PanelHeight(), this.nativeHeight * this.nativeScaling);
         }
         return this.props.PanelHeight();
@@ -46,29 +49,36 @@ export class ContentFittingDocumentView extends React.Component<DocumentViewProp
     @computed get Xshift() { return this.nativeWidth ? (this.props.PanelWidth() - this.nativeWidth * this.nativeScaling) / 2 : 0; }
     @computed get YShift() { return this.nativeWidth && this.nativeHeight && Math.abs(this.Xshift) < 0.001 ? (this.props.PanelHeight() - this.nativeHeight * this.nativeScaling) / 2 : 0; }
     @computed get centeringX() { return this.props.dontCenter?.includes("x") ? 0 : this.Xshift; }
-    @computed get centeringY() { return this.props.dontCenter?.includes("y") ? 0 : this.YShift; }
+    @computed get centeringY() { return this.props.Document._fitWidth || this.props.dontCenter?.includes("y") ? 0 : this.YShift; }
 
+    NativeWidth = () => this.nativeWidth;
+    NativeHeight = () => this.nativeHeight;
     PanelWidth = () => this.panelWidth;
     PanelHeight = () => this.panelHeight;
     NativeScaling = () => this.nativeScaling;
-    screenToLocalTransform = () => this.props.ScreenToLocalTransform().translate(-this.centeringX, -this.centeringY).scale(1 / this.nativeScaling);
+    screenToLocalTransform = () => this.props.ScreenToLocalTransform().scale(1 / this.nativeScaling);
 
     render() {
         TraceMobx();
+        if (this.props.Document.type === DocumentType.PDF) {
+            console.log("PanelHeight = " + this.panelHeight);
+        }
         return (<div className="contentFittingDocumentView">
             {!this.props.Document || !this.props.PanelWidth() ? (null) : (
                 <div className="contentFittingDocumentView-previewDoc" ref={this.ContentRef}
                     style={{
                         transform: `translate(${this.centeringX}px, ${this.centeringY}px)`,
                         borderRadius: this.props.styleProvider?.(this.props.Document, this.props, StyleProp.PointerEvents),
-                        height: Math.abs(this.YShift) > 0.001 ? `${100 * this.nativeHeight / this.nativeWidth * this.props.PanelWidth() / this.props.PanelHeight()}%` : this.props.PanelHeight(),
                         width: Math.abs(this.Xshift) > 0.001 ? `${100 * (this.props.PanelWidth() - this.Xshift * 2) / this.props.PanelWidth()}%` : this.props.PanelWidth(),
+                        height: Math.abs(this.YShift) > 0.001 ? this.props.Document._fitWidth ? `${this.panelHeight}px` : `${100 * this.nativeHeight / this.nativeWidth * this.props.PanelWidth() / this.props.PanelHeight()}%` : this.props.PanelHeight(),
                     }}>
                     <DocumentView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit}
                         ref={action((r: DocumentView | null) => this.docView = r)}
                         LayoutTemplate={this.props.LayoutTemplate}
                         PanelWidth={this.PanelWidth}
                         PanelHeight={this.PanelHeight}
+                        NativeWidth={this.NativeWidth}
+                        NativeHeight={this.NativeHeight}
                         ContentScaling={this.NativeScaling}
                         ScreenToLocalTransform={this.screenToLocalTransform}
                         focus={this.props.focus || emptyFunction}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index ec730dbf6..147740ae3 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -902,8 +902,13 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     @action setContentsActive = (setActive: () => boolean) => this.contentsActive = setActive;
     parentActive = (outsideReaction: boolean) => this.props.layerProvider?.(this.layoutDoc) === false ? this.props.parentActive(outsideReaction) : false;
     screenToLocal = () => this.props.ScreenToLocalTransform().translate(0, -this.headerMargin);
+    contentScaling = () => !this.props.Document._fitWidth ? this.props.PanelWidth() / (this.props.NativeWidth?.() || this.props.PanelWidth()) : this.LocalScaling;
+
     @computed get contents() {
         TraceMobx();
+        if (this.props.Document.type === DocumentType.PDF) {
+            console.log("Scaling = " + this.contentScaling());
+        }
         return (<div className="documentView-contentsView"
             style={{
                 pointerEvents: this.props.contentPointerEvents as any,
@@ -920,7 +925,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 NativeHeight={this.NativeHeight}
                 PanelWidth={this.props.PanelWidth}
                 PanelHeight={this.props.PanelHeight}
-                scaling={this.props.ContentScaling || returnOne}
+                scaling={this.contentScaling}
                 layerProvider={this.props.layerProvider}
                 styleProvider={this.props.styleProvider}
                 LayoutTemplateString={this.props.LayoutTemplateString}
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 262e61c9b..ec9a75302 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -192,7 +192,6 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum
         </div>;
     }
 
-    contentScaling = () => this.props.scaling?.() || 1;
     isChildActive = (outsideReaction?: boolean) => this._isChildActive;
     @computed get renderPdfView() {
         TraceMobx();
@@ -209,7 +208,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum
                 whenActiveChanged={this.whenActiveChanged}
                 isChildActive={this.isChildActive}
                 startupLive={true}
-                ContentScaling={this.contentScaling}
+                ContentScaling={this.props.scaling}
             />
             {this.settingsPanel()}
         </div>;
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 893236857..b446dab22 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -23,6 +23,7 @@ import { SnappingManager } from "../../util/SnappingManager";
 import { SelectionManager } from "../../util/SelectionManager";
 import { LinkDocPreview } from "./LinkDocPreview";
 import { FormattedTextBoxComment } from "./formattedText/FormattedTextBoxComment";
+import { Transform } from "../../util/Transform";
 const path = require('path');
 
 export const timeSchema = createSchema({
@@ -413,7 +414,8 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
         return this.addDocument(doc);
     }
 
-    @computed get contentScaling() { return 1; }
+    @computed get contentScaling() { return this.props.scaling?.() || 1 }
+    scaling = () => this.contentScaling;
     contentFunc = () => [this.youtubeVideoId ? this.youtubeContent : this.content];
     render() {
         return (<div className="videoBox" onContextMenu={this.specificContextMenu}
@@ -431,7 +433,8 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
                     isAnnotationOverlay={true}
                     select={emptyFunction}
                     active={this.annotationsActive}
-                    ContentScaling={returnOne}
+                    ContentScaling={this.scaling}
+                    ScreenToLocalTransform={Transform.Identity}
                     whenActiveChanged={this.whenActiveChanged}
                     removeDocument={this.removeDocument}
                     moveDocument={this.moveDocument}
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 7696167a7..be64754af 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -60,7 +60,7 @@ interface IViewerProps extends FieldViewProps {
     loaded?: (nw: number, nh: number, np: number) => void;
     isChildActive: (outsideReaction?: boolean) => boolean;
     setPdfViewer: (view: PDFViewer) => void;
-    ContentScaling: () => number;
+    ContentScaling?: () => number;
 }
 
 /**
@@ -371,7 +371,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
     @action
     scrollToAnnotation = (scrollToAnnotation: Doc) => {
         if (scrollToAnnotation) {
-            const offset = (this.props.PanelHeight() / this.props.ContentScaling()) / 2;
+            const offset = (this.props.PanelHeight() / this.contentScaling) / 2;
             this._mainCont.current && smoothScroll(500, this._mainCont.current, NumCast(scrollToAnnotation.y) - offset);
             Doc.linkFollowHighlight(scrollToAnnotation);
         }
@@ -738,7 +738,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
     @computed get pdfViewerDiv() {
         return <div className={"pdfViewerDash-text" + ((this.props.isSelected() || this.props.isChildActive()) ? "-selected" : "")} ref={this._viewer} />;
     }
-    @computed get contentScaling() { return this.props.ContentScaling(); }
+    @computed get contentScaling() { return this.props.ContentScaling?.() || 1; }
     @computed get standinViews() {
         return <>
             {this._showCover ? this.getCoverImage() : (null)}
@@ -759,7 +759,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
                 overflowX: this._zoomed !== 1 ? "scroll" : undefined,
                 width: !this.props.Document._fitWidth && (window.screen.width > 600) ? Doc.NativeWidth(this.props.Document) : `${100 / this.contentScaling}%`,
                 height: !this.props.Document._fitWidth && (window.screen.width > 600) ? Doc.NativeHeight(this.props.Document) : `${100 / this.contentScaling}%`,
-                transform: `scale(${this.props.ContentScaling()})`
+                transform: `scale(${this.contentScaling})`
             }}  >
             {this.pdfViewerDiv}
             {this.annotationLayer}
-- 
cgit v1.2.3-70-g09d2


From 7b82359d68bf2fbc91d8851e2eb80c8b22930fd2 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 15 Dec 2020 13:01:18 -0500
Subject: simplifying dragging to make links by moving linkDocument to event,
 instead of dragData.  moved link anchor and caption styling to default style
 provider.  CURRENTLY, typing text, brushing doc highlights along with a bunch
 of other things ARE BROKEN ..

---
 src/client/documents/Documents.ts                  |  34 +-
 src/client/util/DragManager.ts                     |   7 +-
 src/client/views/StyleProvider.tsx                 |   9 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |   2 +-
 src/client/views/nodes/DocumentLinksButton.tsx     |   9 +-
 src/client/views/nodes/DocumentView.tsx            | 386 ++++++++-------------
 src/client/views/nodes/WebBox.tsx                  |   4 +-
 .../views/nodes/formattedText/FormattedTextBox.tsx |   9 +-
 src/client/views/pdf/PDFViewer.tsx                 |   6 +-
 9 files changed, 197 insertions(+), 269 deletions(-)

(limited to 'src/client/views/pdf/PDFViewer.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 95daecc64..8fd906dc7 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -1,4 +1,4 @@
-import { runInAction } from "mobx";
+import { runInAction, action } from "mobx";
 import { basename, extname } from "path";
 import { DateField } from "../../fields/DateField";
 import { Doc, DocListCast, DocListCastAsync, Field, HeightSym, Opt, WidthSym } from "../../fields/Doc";
@@ -53,6 +53,8 @@ import { PresElementBox } from "../views/presentationview/PresElementBox";
 import { SearchBox } from "../views/search/SearchBox";
 import { DashWebRTCVideo } from "../views/webcam/DashWebRTCVideo";
 import { DocumentType } from "./DocumentTypes";
+import { TaskCompletionBox } from "../views/nodes/TaskCompletedBox";
+import { LinkDescriptionPopup } from "../views/nodes/LinkDescriptionPopup";
 const path = require('path');
 
 const defaultNativeImageDim = Number(DFLT_IMAGE_NATIVE_DIM.replace("px", ""));
@@ -1011,11 +1013,37 @@ export namespace DocUtils {
         DocUtils.ActiveRecordings.map(d => DocUtils.MakeLink({ doc: doc }, { doc: d }, "audio link", "audio timeline"));
     }
 
-    export function MakeLink(source: { doc: Doc }, target: { doc: Doc }, linkRelationship: string = "", description: string = "", id?: string, allowParCollectionLink?: boolean) {
+    export function MakeLink(source: { doc: Doc }, target: { doc: Doc }, linkRelationship: string = "", description: string = "", id?: string, allowParCollectionLink?: boolean, showPopup?: number[]) {
         const sv = DocumentManager.Instance.getDocumentView(source.doc);
         if (!allowParCollectionLink && sv?.props.ContainingCollectionDoc === target.doc) return;
         if (target.doc === Doc.UserDoc()) return undefined;
 
+
+        const makeLink = action((linkDoc: Doc, showPopup: number[]) => {
+            LinkManager.currentLink = linkDoc;
+
+            TaskCompletionBox.textDisplayed = "Link Created";
+            TaskCompletionBox.popupX = showPopup[0];
+            TaskCompletionBox.popupY = showPopup[1] - 33;
+            TaskCompletionBox.taskCompleted = true;
+
+            LinkDescriptionPopup.popupX = showPopup[0];
+            LinkDescriptionPopup.popupY = showPopup[1];
+            LinkDescriptionPopup.descriptionPopup = true;
+
+            const rect = document.body.getBoundingClientRect();
+            if (LinkDescriptionPopup.popupX + 200 > rect.width) {
+                LinkDescriptionPopup.popupX -= 190;
+                TaskCompletionBox.popupX -= 40;
+            }
+            if (LinkDescriptionPopup.popupY + 100 > rect.height) {
+                LinkDescriptionPopup.popupY -= 40;
+                TaskCompletionBox.popupY -= 40;
+            }
+
+            setTimeout(action(() => TaskCompletionBox.taskCompleted = false), 2500);
+        });
+
         const linkDoc = Docs.Create.LinkDocument(source, target, { linkRelationship, layoutKey: "layout_linkView", description }, id);
         Doc.GetProto(linkDoc)["anchor1-useLinkSmallAnchor"] = source.doc.useLinkSmallAnchor;
         Doc.GetProto(linkDoc)["anchor2-useLinkSmallAnchor"] = target.doc.useLinkSmallAnchor;
@@ -1024,7 +1052,7 @@ export namespace DocUtils {
         Doc.GetProto(linkDoc)["acl-Public"] = linkDoc["acl-Public"] = SharingPermissions.Add;
         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');
-
+        showPopup && makeLink(linkDoc, showPopup);
         return linkDoc;
     }
 
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 4704d9e71..1a58b4bf1 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -109,6 +109,7 @@ export namespace DragManager {
             this.linkDragData = dragData instanceof LinkDragData ? dragData : undefined;
             this.columnDragData = dragData instanceof ColumnDragData ? dragData : undefined;
         }
+        linkDocument?: Doc;
         aborted: boolean;
         docDragData?: DocumentDragData;
         annoDragData?: PdfAnnoDragData;
@@ -143,8 +144,7 @@ export namespace DragManager {
         droppedDocuments: Doc[] = [];
         linkSourceDocument: Doc;
         dontClearTextBox?: boolean;
-        linkDocument?: Doc;
-        linkDropCallback?: (data: { linkDocument?: Doc }) => void;
+        linkDropCallback?: (data: { linkDocument: Doc }) => void;
     }
     export class ColumnDragData {
         constructor(colKey: SchemaHeaderField) {
@@ -161,7 +161,6 @@ export namespace DragManager {
             this.annotationDocument = annotationDoc;
             this.offset = [0, 0];
         }
-        linkDocument?: Doc;
         targetContext: Doc | undefined;
         dragDocument: Doc;
         annotationDocument: Doc;
@@ -169,7 +168,7 @@ export namespace DragManager {
         offset: number[];
         dropAction: dropActionType;
         userDropAction: dropActionType;
-        linkDropCallback?: (data: { linkDocument?: Doc }) => void;
+        linkDropCallback?: (data: { linkDocument: Doc }) => void;
     }
 
     export function MakeDropTarget(
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index f2569edbd..912d718cf 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -70,20 +70,24 @@ export function testDocProps(toBeDetermined: any): toBeDetermined is DocumentVie
 export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps | DocumentViewProps>, property: string): any {
     const docProps = testDocProps(props) ? props : undefined;
     const selected = property.includes(":selected");
+    const isCaption = property.includes(":caption");
+    const isAnchor = property.includes(":anchor");
     const isBackground = () => StrListCast(doc?.layers).includes(StyleLayers.Background);
     const backgroundCol = () => props?.styleProvider?.(doc, props, StyleProp.BackgroundColor);
     const opacity = () => props?.styleProvider?.(doc, props, StyleProp.Opacity);
 
     switch (property.split(":")[0]) {
         case StyleProp.DocContents: return undefined;
+        case StyleProp.LinkSource: return isAnchor && docProps?.Document; // pass the LinkSource to the LinkAnchorBox
         case StyleProp.WidgetColor: return darkScheme() ? "lightgrey" : "dimgrey";
         case StyleProp.Opacity: return Cast(doc?._opacity, "number", Cast(doc?.opacity, "number", null));
-        case StyleProp.HideLinkButton: return props?.dontRegisterView || (!selected && (doc?.isLinkButton || doc?.hideLinkButton));
+        case StyleProp.HideLinkButton: return isAnchor || props?.dontRegisterView || (!selected && (doc?.isLinkButton || doc?.hideLinkButton));
         case StyleProp.ShowTitle: return doc && !doc.presentationTargetDoc && StrCast(doc._showTitle,
             !Doc.IsSystem(doc) && doc.type === DocumentType.RTF ?
                 (doc.author === Doc.CurrentUserEmail ? StrCast(Doc.UserDoc().showTitle) : "author;creationDate") :
                 undefined);
         case StyleProp.Color:
+            if (isCaption) return "white";
             const backColor = backgroundCol() || "black";
             const col = Color(backColor).rgb();
             const colsum = (col.red() + col.green() + col.blue());
@@ -93,6 +97,8 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps |
         case StyleProp.BorderRounding: return StrCast(doc?._borderRounding, StrCast(doc?.borderRounding));
         case StyleProp.HeaderMargin: return ([CollectionViewType.Stacking, CollectionViewType.Masonry].includes(doc?._viewType as any) || doc?.type === DocumentType.RTF) && doc?._showTitle && !doc?._showTitleHover ? 15 : 0;
         case StyleProp.BackgroundColor: {
+            if (isAnchor && docProps) return "transparent";
+            if (isCaption) return "rgba(0,0,0 ,0.4)";
             if (Doc.UserDoc().renderStyle === "comic") return "transparent";
             let docColor: Opt<string> = StrCast(doc?._backgroundColor, StrCast(doc?.backgroundColor));
             if (!docProps) {
@@ -144,6 +150,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps |
             }
         }
         case StyleProp.PointerEvents:
+            if (isAnchor && docProps) return "none";
             if (props?.pointerEvents === "none") return "none";
             const layer = doc && props?.layerProvider?.(doc);
             if (opacity() === 0 || doc?.type === DocumentType.INK || doc?.isInkMask) return "none";
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 67ad2b769..d17e87db4 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -280,7 +280,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
         } else {
             const source = Docs.Create.TextDocument("", { _width: 200, _height: 75, x: xp, y: yp, title: "dropped annotation" });
             this.props.addDocument?.(source);
-            linkDragData.linkDocument = DocUtils.MakeLink({ doc: source }, { doc: linkDragData.linkSourceDocument }, "doc annotation", ""); // TODODO this is where in text links get passed
+            de.complete.linkDocument = DocUtils.MakeLink({ doc: source }, { doc: linkDragData.linkSourceDocument }, "doc annotation", ""); // TODODO this is where in text links get passed
             e.stopPropagation();
             return true;
         }
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 06aa852cc..e7a94580a 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -50,16 +50,15 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
                 const linkDrag = UndoManager.StartBatch("Drag Link");
                 this.props.View && DragManager.StartLinkDrag(this._linkButton.current, this.props.View.props.Document, e.pageX, e.pageY, {
                     dragComplete: dropEv => {
-                        const linkDoc = dropEv.linkDragData?.linkDocument as Doc; // equivalent to !dropEve.aborted since linkDocument is only assigned on a completed drop
-                        if (this.props.View && linkDoc) {
-                            !linkDoc.linkRelationship && (Doc.GetProto(linkDoc).linkRelationship = "hyperlink");
+                        if (this.props.View && dropEv.linkDocument) {// dropEv.linkDocument equivalent to !dropEve.aborted since linkDocument is only assigned on a completed drop
+                            !dropEv.linkDocument.linkRelationship && (Doc.GetProto(dropEv.linkDocument).linkRelationship = "hyperlink");
 
                             // we want to allow specific views to handle the link creation in their own way (e.g., rich text makes text hyperlinks)
                             // the dragged view can regiser a linkDropCallback to be notified that the link was made and to update their data structures
                             // however, the dropped document isn't so accessible.  What we do is set the newly created link document on the documentView
                             // The documentView passes a function prop returning this link doc to its descendants who can react to changes to it.
-                            dropEv.linkDragData?.linkDropCallback?.(dropEv.linkDragData);
-                            runInAction(() => this.props.View.LinkBeingCreated = linkDoc);
+                            dropEv.linkDragData?.linkDropCallback?.(dropEv as { linkDocument: Doc }); // bcz: typescript can't figure out that this is valid even though we tested dropEv.linkDocument above
+                            runInAction(() => this.props.View.LinkBeingCreated = dropEv.linkDocument);
                             setTimeout(action(() => this.props.View.LinkBeingCreated = undefined), 0);
                         }
                         linkDrag?.end();
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index a005a5db4..da10f2a69 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -153,6 +153,25 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
         super(props);
     }
 
+    componentDidMount() { this.componentDidUpdate(); }
+    componentDidUpdate() {
+        this.componentWillUnmount();
+        if (this._mainCont.current) {
+            this._dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, this.drop.bind(this), this.props.Document);
+            this._gestureEventDisposer = GestureUtils.MakeGestureTarget(this._mainCont.current, this.onGesture.bind(this));
+            this._multiTouchDisposer = InteractionUtils.MakeMultiTouchTarget(this._mainCont.current, this.onTouchStart.bind(this));
+            this._holdDisposer = InteractionUtils.MakeHoldTouchTarget(this._mainCont.current, this.handle1PointerHoldStart.bind(this));
+        }
+    }
+    componentWillUnmount() {
+        this._dropDisposer?.();
+        this._gestureEventDisposer?.();
+        this._multiTouchDisposer?.();
+        this._holdDisposer?.();
+        Doc.UnBrushDoc(this.props.Document);
+    }
+
+
     handle1PointerHoldStart = (e: Event, me: InteractionUtils.MultiTouchEvent<React.TouchEvent>): any => {
         this.removeMoveListeners();
         this.removeEndListeners();
@@ -194,6 +213,113 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
         }
     }
 
+    handle2PointersDown = (e: React.TouchEvent, me: InteractionUtils.MultiTouchEvent<React.TouchEvent>) => {
+        if (!e.nativeEvent.cancelBubble && !this.props.isSelected()) {
+            e.stopPropagation();
+            e.preventDefault();
+
+            this.removeMoveListeners();
+            this.addMoveListeners();
+            this.removeEndListeners();
+            this.addEndListeners();
+        }
+    }
+
+    handle1PointerDown = (e: React.TouchEvent, me: InteractionUtils.MultiTouchEvent<React.TouchEvent>) => {
+        SelectionManager.DeselectAll();
+        if (this.Document.onPointerDown) return;
+        const touch = me.touchEvent.changedTouches.item(0);
+        if (touch) {
+            this._downX = touch.clientX;
+            this._downY = touch.clientY;
+            if (!e.nativeEvent.cancelBubble) {
+                if ((this.active || this.layoutDoc.onDragStart || this.onClickHandler) && !e.ctrlKey && !this.layoutDoc.lockedPosition && !CurrentUserUtils.OverlayDocs.includes(this.layoutDoc)) e.stopPropagation();
+                this.removeMoveListeners();
+                this.addMoveListeners();
+                this.removeEndListeners();
+                this.addEndListeners();
+                e.stopPropagation();
+            }
+        }
+    }
+
+    handle1PointerMove = (e: TouchEvent, me: InteractionUtils.MultiTouchEvent<TouchEvent>) => {
+        if ((e as any).formattedHandled) { e.stopPropagation; return; }
+        if (e.cancelBubble && this.active) {
+            this.removeMoveListeners();
+        }
+        else if (!e.cancelBubble && (this.props.isSelected(true) || this.props.parentActive(true) || this.layoutDoc.onDragStart || this.onClickHandler) && !this.layoutDoc.lockedPosition && !CurrentUserUtils.OverlayDocs.includes(this.layoutDoc)) {
+            const touch = me.touchEvent.changedTouches.item(0);
+            if (touch && (Math.abs(this._downX - touch.clientX) > 3 || Math.abs(this._downY - touch.clientY) > 3)) {
+                if (!e.altKey && (!this.topMost || this.layoutDoc.onDragStart || this.onClickHandler)) {
+                    this.cleanUpInteractions();
+                    this.startDragging(this._downX, this._downY, this.Document.dropAction ? this.Document.dropAction as any : e.ctrlKey || e.altKey ? "alias" : undefined);
+                }
+            }
+            e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document'  however it does mark the event as cancelBubble=true which we test for in the move event handlers
+            e.preventDefault();
+        }
+    }
+
+    @action
+    handle2PointersMove = (e: TouchEvent, me: InteractionUtils.MultiTouchEvent<TouchEvent>) => {
+        const myTouches = InteractionUtils.GetMyTargetTouches(me, this.prevPoints, true);
+        const pt1 = myTouches[0];
+        const pt2 = myTouches[1];
+        const oldPoint1 = this.prevPoints.get(pt1.identifier);
+        const oldPoint2 = this.prevPoints.get(pt2.identifier);
+        const pinching = InteractionUtils.Pinning(pt1, pt2, oldPoint1!, oldPoint2!);
+        if (pinching !== 0 && oldPoint1 && oldPoint2) {
+            const dW = (Math.abs(pt1.clientX - pt2.clientX) - Math.abs(oldPoint1.clientX - oldPoint2.clientX));
+            const dH = (Math.abs(pt1.clientY - pt2.clientY) - Math.abs(oldPoint1.clientY - oldPoint2.clientY));
+            const dX = -1 * Math.sign(dW);
+            const dY = -1 * Math.sign(dH);
+
+            if (dX !== 0 || dY !== 0 || dW !== 0 || dH !== 0) {
+                const doc = Document(this.props.Document);
+                const layoutDoc = Document(Doc.Layout(this.props.Document));
+                let nwidth = Doc.NativeWidth(layoutDoc);
+                let nheight = Doc.NativeHeight(layoutDoc);
+                const width = (layoutDoc._width || 0);
+                const height = (layoutDoc._height || (nheight / nwidth * width));
+                const scale = this.props.ScreenToLocalTransform().Scale * this.ContentScale;
+                const actualdW = Math.max(width + (dW * scale), 20);
+                const actualdH = Math.max(height + (dH * scale), 20);
+                doc.x = (doc.x || 0) + dX * (actualdW - width);
+                doc.y = (doc.y || 0) + dY * (actualdH - height);
+                const fixedAspect = e.ctrlKey || (nwidth && nheight);
+                if (fixedAspect && (!nwidth || !nheight)) {
+                    Doc.SetNativeWidth(layoutDoc, nwidth = layoutDoc._width || 0);
+                    Doc.SetNativeHeight(layoutDoc, nheight = layoutDoc._height || 0);
+                }
+                if (nwidth > 0 && nheight > 0) {
+                    if (Math.abs(dW) > Math.abs(dH)) {
+                        if (!fixedAspect) {
+                            Doc.SetNativeWidth(layoutDoc, actualdW / (layoutDoc._width || 1) * Doc.NativeWidth(layoutDoc));
+                        }
+                        layoutDoc._width = actualdW;
+                        if (fixedAspect && !layoutDoc._fitWidth) layoutDoc._height = nheight / nwidth * layoutDoc._width;
+                        else layoutDoc._height = actualdH;
+                    }
+                    else {
+                        if (!fixedAspect) {
+                            Doc.SetNativeHeight(layoutDoc, actualdH / (layoutDoc._height || 1) * Doc.NativeHeight(doc));
+                        }
+                        layoutDoc._height = actualdH;
+                        if (fixedAspect && !layoutDoc._fitWidth) layoutDoc._width = nwidth / nheight * layoutDoc._height;
+                        else layoutDoc._width = actualdW;
+                    }
+                } else {
+                    dW && (layoutDoc._width = actualdW);
+                    dH && (layoutDoc._height = actualdH);
+                    dH && layoutDoc._autoHeight && (layoutDoc._autoHeight = false);
+                }
+            }
+            e.stopPropagation();
+            e.preventDefault();
+        }
+    }
+
     @action
     onRadialMenu = (e: Event, me: InteractionUtils.MultiTouchEvent<React.TouchEvent>): void => {
         const pt = me.touchEvent.touches[me.touchEvent.touches.length - 1];
@@ -209,43 +335,15 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
         SelectionManager.DeselectAll();
     }
 
-    @action
-    componentDidMount() {
-        this.componentDidUpdate();
-    }
-
-    @action
-    componentDidUpdate() {
-        this._dropDisposer?.();
-        this._gestureEventDisposer?.();
-        this._multiTouchDisposer?.();
-        this._holdDisposer?.();
-        if (this._mainCont.current) {
-            this._dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, this.drop.bind(this), this.props.Document);
-            this._gestureEventDisposer = GestureUtils.MakeGestureTarget(this._mainCont.current, this.onGesture.bind(this));
-            this._multiTouchDisposer = InteractionUtils.MakeMultiTouchTarget(this._mainCont.current, this.onTouchStart.bind(this));
-            this._holdDisposer = InteractionUtils.MakeHoldTouchTarget(this._mainCont.current, this.handle1PointerHoldStart.bind(this));
-        }
-    }
-
-    @action
-    componentWillUnmount() {
-        this._dropDisposer?.();
-        this._gestureEventDisposer?.();
-        this._multiTouchDisposer?.();
-        this._holdDisposer?.();
-        Doc.UnBrushDoc(this.props.Document);
-    }
-
     startDragging(x: number, y: number, dropAction: dropActionType) {
         if (this._mainCont.current) {
             const dragData = new DragManager.DocumentDragData([this.props.Document]);
             const [left, top] = this.props.ScreenToLocalTransform().scale(this.ContentScale).inverse().transformPoint(0, 0);
             dragData.offset = this.props.ScreenToLocalTransform().scale(this.ContentScale).transformDirection(x - left, y - top);
             dragData.dropAction = dropAction;
+            dragData.treeViewDoc = this.props.treeViewDoc;
             dragData.removeDocument = this.props.removeDocument;
             dragData.moveDocument = this.props.moveDocument;
-            dragData.treeViewDoc = this.props.treeViewDoc;
             DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, { hideSource: !dropAction && !this.layoutDoc.onDragStart });
         }
     }
@@ -334,116 +432,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
             stopPropagate && e.stopPropagation();
             preventDefault && e.preventDefault();
         }
-    }).bind(this);
-
-    handle1PointerDown = (e: React.TouchEvent, me: InteractionUtils.MultiTouchEvent<React.TouchEvent>) => {
-        SelectionManager.DeselectAll();
-        if (this.Document.onPointerDown) return;
-        const touch = me.touchEvent.changedTouches.item(0);
-        if (touch) {
-            this._downX = touch.clientX;
-            this._downY = touch.clientY;
-            if (!e.nativeEvent.cancelBubble) {
-                if ((this.active || this.layoutDoc.onDragStart || this.onClickHandler) && !e.ctrlKey && !this.layoutDoc.lockedPosition && !CurrentUserUtils.OverlayDocs.includes(this.layoutDoc)) e.stopPropagation();
-                this.removeMoveListeners();
-                this.addMoveListeners();
-                this.removeEndListeners();
-                this.addEndListeners();
-                e.stopPropagation();
-            }
-        }
-    }
-
-    handle1PointerMove = (e: TouchEvent, me: InteractionUtils.MultiTouchEvent<TouchEvent>) => {
-        if ((e as any).formattedHandled) { e.stopPropagation; return; }
-        if (e.cancelBubble && this.active) {
-            this.removeMoveListeners();
-        }
-        else if (!e.cancelBubble && (this.props.isSelected(true) || this.props.parentActive(true) || this.layoutDoc.onDragStart || this.onClickHandler) && !this.layoutDoc.lockedPosition && !CurrentUserUtils.OverlayDocs.includes(this.layoutDoc)) {
-
-            const touch = me.touchEvent.changedTouches.item(0);
-            if (touch && (Math.abs(this._downX - touch.clientX) > 3 || Math.abs(this._downY - touch.clientY) > 3)) {
-                if (!e.altKey && (!this.topMost || this.layoutDoc.onDragStart || this.onClickHandler)) {
-                    this.cleanUpInteractions();
-                    this.startDragging(this._downX, this._downY, this.Document.dropAction ? this.Document.dropAction as any : e.ctrlKey || e.altKey ? "alias" : undefined);
-                }
-            }
-            e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document'  however it does mark the event as cancelBubble=true which we test for in the move event handlers
-            e.preventDefault();
-        }
-    }
-
-    handle2PointersDown = (e: React.TouchEvent, me: InteractionUtils.MultiTouchEvent<React.TouchEvent>) => {
-        if (!e.nativeEvent.cancelBubble && !this.props.isSelected()) {
-            e.stopPropagation();
-            e.preventDefault();
-
-            this.removeMoveListeners();
-            this.addMoveListeners();
-            this.removeEndListeners();
-            this.addEndListeners();
-        }
-    }
-
-
-    @action
-    handle2PointersMove = (e: TouchEvent, me: InteractionUtils.MultiTouchEvent<TouchEvent>) => {
-        const myTouches = InteractionUtils.GetMyTargetTouches(me, this.prevPoints, true);
-        const pt1 = myTouches[0];
-        const pt2 = myTouches[1];
-        const oldPoint1 = this.prevPoints.get(pt1.identifier);
-        const oldPoint2 = this.prevPoints.get(pt2.identifier);
-        const pinching = InteractionUtils.Pinning(pt1, pt2, oldPoint1!, oldPoint2!);
-        if (pinching !== 0 && oldPoint1 && oldPoint2) {
-            const dW = (Math.abs(pt1.clientX - pt2.clientX) - Math.abs(oldPoint1.clientX - oldPoint2.clientX));
-            const dH = (Math.abs(pt1.clientY - pt2.clientY) - Math.abs(oldPoint1.clientY - oldPoint2.clientY));
-            const dX = -1 * Math.sign(dW);
-            const dY = -1 * Math.sign(dH);
-
-            if (dX !== 0 || dY !== 0 || dW !== 0 || dH !== 0) {
-                const doc = Document(this.props.Document);
-                const layoutDoc = Document(Doc.Layout(this.props.Document));
-                let nwidth = Doc.NativeWidth(layoutDoc);
-                let nheight = Doc.NativeHeight(layoutDoc);
-                const width = (layoutDoc._width || 0);
-                const height = (layoutDoc._height || (nheight / nwidth * width));
-                const scale = this.props.ScreenToLocalTransform().Scale * this.ContentScale;
-                const actualdW = Math.max(width + (dW * scale), 20);
-                const actualdH = Math.max(height + (dH * scale), 20);
-                doc.x = (doc.x || 0) + dX * (actualdW - width);
-                doc.y = (doc.y || 0) + dY * (actualdH - height);
-                const fixedAspect = e.ctrlKey || (nwidth && nheight);
-                if (fixedAspect && (!nwidth || !nheight)) {
-                    Doc.SetNativeWidth(layoutDoc, nwidth = layoutDoc._width || 0);
-                    Doc.SetNativeHeight(layoutDoc, nheight = layoutDoc._height || 0);
-                }
-                if (nwidth > 0 && nheight > 0) {
-                    if (Math.abs(dW) > Math.abs(dH)) {
-                        if (!fixedAspect) {
-                            Doc.SetNativeWidth(layoutDoc, actualdW / (layoutDoc._width || 1) * Doc.NativeWidth(layoutDoc));
-                        }
-                        layoutDoc._width = actualdW;
-                        if (fixedAspect && !layoutDoc._fitWidth) layoutDoc._height = nheight / nwidth * layoutDoc._width;
-                        else layoutDoc._height = actualdH;
-                    }
-                    else {
-                        if (!fixedAspect) {
-                            Doc.SetNativeHeight(layoutDoc, actualdH / (layoutDoc._height || 1) * Doc.NativeHeight(doc));
-                        }
-                        layoutDoc._height = actualdH;
-                        if (fixedAspect && !layoutDoc._fitWidth) layoutDoc._width = nwidth / nheight * layoutDoc._height;
-                        else layoutDoc._width = actualdW;
-                    }
-                } else {
-                    dW && (layoutDoc._width = actualdW);
-                    dH && (layoutDoc._height = actualdH);
-                    dH && layoutDoc._autoHeight && (layoutDoc._autoHeight = false);
-                }
-            }
-            e.stopPropagation();
-            e.preventDefault();
-        }
-    }
+    })
 
     onPointerDown = (e: React.PointerEvent): void => {
         // continue if the event hasn't been canceled AND we are using a moues or this is has an onClick or onDragStart function (meaning it is a button document)
@@ -526,11 +515,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
         }
     }
 
-    @undoBatch @action
-    toggleRaiseWhenDragged = () => {
-        this.rootDoc._raiseWhenDragged = this.rootDoc._raiseWhenDragged === undefined ? false : undefined;
-    }
-
     @undoBatch @action
     toggleFollowLink = (location: Opt<string>, zoom: boolean, setPushpin: boolean): void => {
         this.Document.ignoreClick = false;
@@ -564,7 +548,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
         this.Document.isPushpin = false;
         this.Document.onClick = this.layoutDoc.onClick = undefined;
     }
-
     @undoBatch
     noOnClick = (): void => {
         this.Document.ignoreClick = false;
@@ -585,45 +568,10 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                 "linking to document tabs not yet supported.  Drop link on document content.");
             return;
         }
-        const makeLink = action((linkDoc: Doc) => {
-            LinkManager.currentLink = linkDoc;
-
-            TaskCompletionBox.textDisplayed = "Link Created";
-            TaskCompletionBox.popupX = de.x;
-            TaskCompletionBox.popupY = de.y - 33;
-            TaskCompletionBox.taskCompleted = true;
-
-            LinkDescriptionPopup.popupX = de.x;
-            LinkDescriptionPopup.popupY = de.y;
-            LinkDescriptionPopup.descriptionPopup = true;
-
-            const rect = document.body.getBoundingClientRect();
-            if (LinkDescriptionPopup.popupX + 200 > rect.width) {
-                LinkDescriptionPopup.popupX -= 190;
-                TaskCompletionBox.popupX -= 40;
-            }
-            if (LinkDescriptionPopup.popupY + 100 > rect.height) {
-                LinkDescriptionPopup.popupY -= 40;
-                TaskCompletionBox.popupY -= 40;
-            }
-
-            setTimeout(action(() => TaskCompletionBox.taskCompleted = false), 2500);
-        });
-        if (de.complete.annoDragData) {
-            /// this whole section for handling PDF annotations looks weird.  Need to rethink this to make it cleaner
-            e.stopPropagation();
-            de.complete.annoDragData.linkDocument = DocUtils.MakeLink({ doc: de.complete.annoDragData.annotationDocument }, { doc: this.props.Document }, "link");
-            de.complete.annoDragData.linkDocument && makeLink(de.complete.annoDragData.linkDocument);
-        }
-        if (de.complete.linkDragData) {
+        const linkSource = de.complete.annoDragData ? de.complete.annoDragData.annotationDocument : de.complete.linkDragData ? de.complete.linkDragData.linkSourceDocument : undefined;
+        if (linkSource && linkSource !== this.props.Document) {
             e.stopPropagation();
-            const linkSource = de.complete.linkDragData.linkSourceDocument;
-            if (linkSource !== this.props.Document) {
-                const linkDoc = DocUtils.MakeLink({ doc: linkSource }, { doc: this.props.Document }, `link`);
-                linkSource !== this.props.Document && (de.complete.linkDragData.linkDocument = linkDoc); // TODODO this is where in text links get passed
-                linkDoc && makeLink(linkDoc);
-            }
-
+            de.complete.linkDocument = DocUtils.MakeLink({ doc: linkSource }, { doc: this.props.Document }, "link", undefined, undefined, undefined, [de.x, de.y]);
         }
     }
 
@@ -707,7 +655,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
             const zorderItems: ContextMenuProps[] = zorders && "subitems" in zorders ? zorders.subitems : [];
             zorderItems.push({ description: "Bring to Front", event: () => SelectionManager.SelectedDocuments().forEach(dv => dv.props.bringToFront(dv.rootDoc, false)), icon: "expand-arrows-alt" });
             zorderItems.push({ description: "Send to Back", event: () => SelectionManager.SelectedDocuments().forEach(dv => dv.props.bringToFront(dv.rootDoc, true)), icon: "expand-arrows-alt" });
-            zorderItems.push({ description: this.rootDoc._raiseWhenDragged !== false ? "Keep ZIndex when dragged" : "Allow ZIndex to change when dragged", event: this.toggleRaiseWhenDragged, icon: "expand-arrows-alt" });
+            zorderItems.push({ description: this.rootDoc._raiseWhenDragged !== false ? "Keep ZIndex when dragged" : "Allow ZIndex to change when dragged", event: undoBatch(action(() => this.rootDoc._raiseWhenDragged = this.rootDoc._raiseWhenDragged === undefined ? false : undefined)), icon: "expand-arrows-alt" });
             !zorders && cm.addItem({ description: "ZOrder...", subitems: zorderItems, icon: "compass" });
 
             onClicks.push({ description: "Enter Portal", event: this.makeIntoPortal, icon: "window-restore" });
@@ -784,17 +732,13 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
         });
     }
 
-    rootSelected = (outsideReaction?: boolean) => {
-        return this.props.isSelected(outsideReaction) || (this.props.Document.rootDocument && this.props.rootSelected?.(outsideReaction)) || false;
-    }
-
+    rootSelected = (outsideReaction?: boolean) => { return this.props.isSelected(outsideReaction) || (this.props.Document.rootDocument && this.props.rootSelected?.(outsideReaction)) || false; }
     panelHeight = () => this.props.PanelHeight() - this.headerMargin;
     parentActive = (outsideReaction: boolean) => this.props.layerProvider?.(this.layoutDoc) === false ? this.props.parentActive(outsideReaction) : false;
     screenToLocal = () => this.props.ScreenToLocalTransform().translate(0, -this.headerMargin);
     contentScaling = () => this.ContentScale;
     onClickFunc = () => this.onClickHandler;
-    onDoubleClickFunc = () => this.onDoubleClickHandler;
-
+    makeLink = () => this.props.DocumentView._link; // pass the link placeholde to child views so they can react to make a specialized anchor.  This is essentially a function call to the descendants since the value of the _link variable will immediately get set back to undefined.
     @observable contentsActive: () => boolean = returnFalse;
     @action setContentsActive = (setActive: () => boolean) => this.contentsActive = setActive;
 
@@ -805,41 +749,14 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                 pointerEvents: this.props.contentPointerEvents as any,
                 height: this.headerMargin ? `calc(100% - ${this.headerMargin}px)` : undefined,
             }}>
-            <DocumentContentsView key={1}
-                renderDepth={this.props.renderDepth}
-                Document={this.props.Document}
-                DataDoc={this.props.DataDoc}
-                fitContentsToDoc={this.props.fitContentsToDoc}
-                ContainingCollectionView={this.props.ContainingCollectionView}
-                ContainingCollectionDoc={this.props.ContainingCollectionDoc}
-                PanelWidth={this.props.PanelWidth}
-                PanelHeight={this.props.PanelHeight}
+            <DocumentContentsView key={1} {...this.props}
                 scaling={this.contentScaling}
-                layerProvider={this.props.layerProvider}
-                styleProvider={this.props.styleProvider}
-                LayoutTemplateString={this.props.LayoutTemplateString}
-                LayoutTemplate={this.props.LayoutTemplate}
-                docFilters={this.props.docFilters}
-                docRangeFilters={this.props.docRangeFilters}
-                searchFilterDocs={this.props.searchFilterDocs}
+                PanelHeight={this.panelHeight}
                 contentsActive={this.setContentsActive}
                 parentActive={this.parentActive}
-                whenActiveChanged={this.props.whenActiveChanged}
-                makeLink={this.makeLink}
-                focus={this.props.focus}
-                dontRegisterView={this.props.dontRegisterView}
-                addDocument={this.props.addDocument}
-                removeDocument={this.props.removeDocument}
-                moveDocument={this.props.moveDocument}
-                addDocTab={this.props.addDocTab}
-                pinToPres={this.props.pinToPres}
                 ScreenToLocalTransform={this.screenToLocal}
-                ignoreAutoHeight={this.props.ignoreAutoHeight}
-                bringToFront={this.props.bringToFront}
-                isSelected={this.props.isSelected}
-                select={this.props.select}
+                makeLink={this.makeLink}
                 rootSelected={this.rootSelected}
-                scriptContext={this.props.scriptContext}
                 onClick={this.onClickFunc}
                 layoutKey={this.finalLayoutKey} />
             {this.layoutDoc.hideAllLinks ? (null) : this.allAnchors}
@@ -859,26 +776,11 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
         return anchor.type === DocumentType.AUDIO && NumCast(ept) ? false : true;
     }
 
-    makeLink = () => this.props.DocumentView._link; // pass the link placeholde to child views so they can react to make a specialized anchor.  This is essentially a function call to the descendants since the value of the _link variable will immediately get set back to undefined.
-
     @undoBatch
     hideLinkAnchor = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && (doc.hidden = true), true)
     anchorPanelWidth = () => this.props.PanelWidth() || 1;
     anchorPanelHeight = () => this.props.PanelHeight() || 1;
-    anchorStyleProvider = (doc: Opt<Doc>, props: Opt<DocumentViewProps | FieldViewProps>, property: string): any => {
-        if (testDocProps(props)) {
-            switch (property.split(":")[0]) {
-                case StyleProp.BackgroundColor: return "transparent"; // background of linkanchor documentView is transparent since it covers the whole document
-                case StyleProp.HideLinkButton: return true; // don't want linkAnchor documentview to show its own link button
-                case StyleProp.PointerEvents: return "none"; // don't want linkAnchor documentView to handle events (since it covers the whole document).  However, the linkAnchorBox itself is set to pointerEvent all
-            }
-        } else {
-            switch (property.split(":")[0]) {
-                case StyleProp.LinkSource: return this.props.Document; // pass the LinkSource to the LinkAnchorBox
-            }
-        }
-        return this.props.styleProvider?.(doc, props, property);
-    }
+    anchorStyleProvider = (doc: Opt<Doc>, props: Opt<DocumentViewProps | FieldViewProps>, property: string): any => this.props.styleProvider?.(doc, props, property + ":anchor");
 
     @computed get directLinks() { TraceMobx(); return LinkManager.Instance.getAllDirectLinks(this.rootDoc); }
     @computed get allLinks() { TraceMobx(); return LinkManager.Instance.getAllRelatedLinks(this.rootDoc); }
@@ -904,11 +806,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                     LayoutTemplateString={LinkAnchorBox.LayoutString(`anchor${Doc.LinkEndpoint(d, this.props.Document)}`)} />
             </div >);
     }
-    captionStyleProvider = (doc: Doc | undefined, props: Opt<DocumentViewInternalProps>, property: string) => {
-        if (property === StyleProp.Color) return "white";
-        if (property === StyleProp.BackgroundColor) return "rgba(0,0,0 ,0.4)";
-        return this.props?.styleProvider?.(doc, props, property);
-    }
+    captionStyleProvider = (doc: Opt<Doc>, props: Opt<DocumentViewInternalProps>, property: string) => this.props?.styleProvider?.(doc, props, property + ":caption");
     @computed get innards() {
         TraceMobx();
         const showTitle = this.ShowTitle;
@@ -938,9 +836,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                     display={"block"}
                     fontSize={10}
                     GetValue={() => Field.toString((this.dataDoc || this.props.Document)[showTitle.split(";")[0]] as any as Field)}
-                    SetValue={undoBatch((value: string) => {
-                        showTitle.includes("Date") ? true : (Doc.GetProto(this.dataDoc || this.props.Document)[showTitle] = value) ? true : true;
-                    })}
+                    SetValue={undoBatch((value) => showTitle.includes("Date") ? true : (Doc.GetProto(this.dataDoc || this.props.Document)[showTitle] = value) ? true : true)}
                 />
             </div>);
         return this.props.hideTitle || (!showTitle && !showCaption) ?
@@ -988,7 +884,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
             onContextMenu={this.onContextMenu}
             onKeyDown={this.onKeyDown}
             onPointerDown={this.onPointerDown}
-            onClick={this.onClick.bind(this)}
+            onClick={this.onClick}
             onPointerEnter={action(e => !SnappingManager.GetIsDragging() && Doc.BrushDoc(this.props.Document))}
             onPointerLeave={action(e => {
                 let entered = false;
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 125bf62f0..8e824a447 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -546,8 +546,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
         if (annotationDoc) {
             DragManager.StartPdfAnnoDrag([ele], new DragManager.PdfAnnoDragData(this.props.Document, annotationDoc, targetDoc), e.pageX, e.pageY, {
                 dragComplete: e => {
-                    if (!e.aborted && e.annoDragData && !e.annoDragData.linkDocument) {
-                        e.annoDragData.linkDocument = DocUtils.MakeLink({ doc: annotationDoc }, { doc: e.annoDragData.dropDocument }, "Annotation");
+                    if (!e.aborted && e.annoDragData && !e.linkDocument) {
+                        e.linkDocument = DocUtils.MakeLink({ doc: annotationDoc }, { doc: e.annoDragData.dropDocument }, "Annotation");
                         annotationDoc.isLinkButton = true;
                         annotationDoc.isPushpin = e.annoDragData?.dropDocument.annotationOn === this.props.Document;
                     }
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index f82e533ad..0bb483b41 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -478,11 +478,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
             de.complete.annoDragData.linkDropCallback = this.linkDrop;
         }
     }
-    linkDrop = (data: { linkDocument?: Doc }) => {
-        const linkDoc = data.linkDocument!;
-        const anchor1Title = linkDoc.anchor1 instanceof Doc ? StrCast(linkDoc.anchor1.title) : "-untitled-";
-        const anchor1Id = linkDoc.anchor1 instanceof Doc ? linkDoc.anchor1[Id] : "";
-        this.makeLinkToSelection(linkDoc[Id], anchor1Title, "add:right", anchor1Id);
+    linkDrop = (data: { linkDocument: Doc }) => {
+        const anchor1Title = data.linkDocument.anchor1 instanceof Doc ? StrCast(data.linkDocument.anchor1.title) : "-untitled-";
+        const anchor1Id = data.linkDocument.anchor1 instanceof Doc ? data.linkDocument.anchor1[Id] : "";
+        this.makeLinkToSelection(data.linkDocument[Id], anchor1Title, "add:right", anchor1Id);
     }
 
     getNodeEndpoints(context: Node, node: Node): { from: number, to: number } | null {
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index be64754af..d6d500702 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -633,12 +633,12 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
         if (annotationDoc) {
             DragManager.StartPdfAnnoDrag([ele], new DragManager.PdfAnnoDragData(this.props.Document, annotationDoc, targetDoc), e.pageX, e.pageY, {
                 dragComplete: e => {
-                    if (!e.aborted && e.annoDragData && !e.annoDragData.linkDocument) {
-                        e.annoDragData.linkDocument = DocUtils.MakeLink({ doc: annotationDoc }, { doc: e.annoDragData.dropDocument }, "Annotation");
+                    if (!e.aborted && e.annoDragData && !e.linkDocument) {
+                        e.linkDocument = DocUtils.MakeLink({ doc: annotationDoc }, { doc: e.annoDragData.dropDocument }, "Annotation");
                     }
                     annotationDoc.isLinkButton = true; // prevents link button fro showing up --- maybe not a good thing?
                     annotationDoc.isPushpin = e.annoDragData?.dropDocument.annotationOn === this.props.Document;
-                    e.annoDragData && e.annoDragData.linkDocument && e.annoDragData?.linkDropCallback?.({ linkDocument: e.annoDragData.linkDocument });
+                    e.linkDocument && e.annoDragData?.linkDropCallback?.(e as { linkDocument: Doc });// bcz: typescript can't figure out that this is valid even though we tested e.linkDocument above
                 }
             });
         }
-- 
cgit v1.2.3-70-g09d2


From 0426828be40e077a2d5d30597076db53a26bb81f Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 16 Dec 2020 12:02:52 -0500
Subject: fixed treeView layouts to pass good values for panelWidth/height to
 DocumentView.   renamed Selectionmanager methods to be views not documents.

---
 src/client/util/CurrentUserUtils.ts                |  2 +-
 src/client/util/DictationManager.ts                |  2 +-
 src/client/util/DocumentManager.ts                 |  4 +-
 src/client/util/HypothesisUtils.ts                 |  2 +-
 src/client/util/SelectionManager.ts                | 52 ++++++++---------
 src/client/util/SharingManager.tsx                 | 12 ++--
 src/client/views/DocumentButtonBar.tsx             |  4 +-
 src/client/views/DocumentDecorations.tsx           | 68 +++++++++++-----------
 src/client/views/GlobalKeyHandler.ts               | 42 ++++++-------
 src/client/views/InkStrokeProperties.ts            |  6 +-
 src/client/views/PropertiesButtons.tsx             | 22 +++----
 src/client/views/PropertiesView.tsx                | 24 ++++----
 src/client/views/StyleProvider.tsx                 |  2 +-
 src/client/views/collections/CollectionMenu.tsx    |  8 +--
 .../views/collections/CollectionSchemaView.tsx     |  2 +-
 src/client/views/collections/CollectionSubView.tsx |  6 +-
 .../views/collections/CollectionTreeView.scss      |  2 +-
 .../views/collections/CollectionTreeView.tsx       |  3 +-
 src/client/views/collections/TabDocView.tsx        |  6 +-
 src/client/views/collections/TreeView.scss         |  2 +-
 src/client/views/collections/TreeView.tsx          | 22 ++++---
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  2 +-
 .../collections/collectionFreeForm/MarqueeView.tsx |  2 +-
 src/client/views/globalCssVariables.scss           |  2 +
 src/client/views/globalCssVariables.scss.d.ts      |  1 +
 src/client/views/nodes/AudioBox.tsx                |  2 +-
 src/client/views/nodes/ColorBox.tsx                |  6 +-
 src/client/views/nodes/DocumentView.tsx            | 14 ++---
 src/client/views/nodes/PresBox.tsx                 |  8 +--
 .../views/nodes/formattedText/RichTextMenu.tsx     |  8 +--
 src/client/views/pdf/PDFViewer.tsx                 |  2 +-
 src/fields/Doc.ts                                  |  2 +-
 32 files changed, 176 insertions(+), 166 deletions(-)

(limited to 'src/client/views/pdf/PDFViewer.tsx')

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 82750bd53..00ee0f4b9 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -1203,7 +1203,7 @@ Scripting.addGlobal(function openDragFactory(dragFactory: Doc) {
     if (copy) {
         CollectionDockingView.AddSplit(copy, "right");
         const view = DocumentManager.Instance.getFirstDocumentView(copy);
-        view && SelectionManager.SelectDoc(view, false);
+        view && SelectionManager.SelectView(view, false);
     }
 });
 Scripting.addGlobal(function snapshotDashboard() { CurrentUserUtils.snapshotDashboard(Doc.UserDoc()); },
diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts
index 34e274699..c6b654dda 100644
--- a/src/client/util/DictationManager.ts
+++ b/src/client/util/DictationManager.ts
@@ -235,7 +235,7 @@ export namespace DictationManager {
 
         export const execute = async (phrase: string) => {
             return UndoManager.RunInBatch(async () => {
-                const targets = SelectionManager.SelectedDocuments();
+                const targets = SelectionManager.Views();
                 if (!targets || !targets.length) {
                     return;
                 }
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 6258cc0ab..1c81cf26c 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -46,12 +46,12 @@ export class DocumentManager {
         });
         this.DocumentViews.push(view);
     }
-    public RemoveView = (view: DocumentView) => {
+    public RemoveView = action((view: DocumentView) => {
         const index = this.DocumentViews.indexOf(view);
         index !== -1 && this.DocumentViews.splice(index, 1);
 
         this.LinkedDocumentViews.slice().forEach(action((pair, i) => pair.a === view || pair.b === view ? this.LinkedDocumentViews.splice(i, 1) : null));
-    }
+    })
 
     //gets all views
     public getDocumentViewsById(id: string) {
diff --git a/src/client/util/HypothesisUtils.ts b/src/client/util/HypothesisUtils.ts
index f4cf336e2..7a449b882 100644
--- a/src/client/util/HypothesisUtils.ts
+++ b/src/client/util/HypothesisUtils.ts
@@ -29,7 +29,7 @@ export namespace Hypothesis {
      * Search for a WebDocument whose url field matches the given uri, return undefined if not found
      */
     export const findWebDoc = async (uri: string) => {
-        const currentDoc = SelectionManager.SelectedDocuments().length && SelectionManager.SelectedDocuments()[0].props.Document;
+        const currentDoc = SelectionManager.Views().length && SelectionManager.Views()[0].props.Document;
         if (currentDoc && Cast(currentDoc.data, WebField)?.url.href === uri) return currentDoc; // always check first whether the currently selected doc is the annotation's source, only use Search otherwise
 
         const results: Doc[] = [];
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 728a4bce1..f657e5b40 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -10,38 +10,38 @@ export namespace SelectionManager {
     class Manager {
 
         @observable IsDragging: boolean = false;
-        SelectedDocuments: ObservableMap<DocumentView, boolean> = new ObservableMap();
+        SelectedViews: ObservableMap<DocumentView, boolean> = new ObservableMap();
         @observable SelectedSchemaDocument: Doc | undefined;
         @observable SelectedSchemaCollection: CollectionSchemaView | undefined;
 
         @action
-        SelectSchemaDoc(collectionView: Opt<CollectionSchemaView>, doc: Opt<Doc>) {
+        SelectSchemaView(collectionView: Opt<CollectionSchemaView>, doc: Opt<Doc>) {
             manager.SelectedSchemaDocument = doc;
             manager.SelectedSchemaCollection = collectionView;
         }
         @action
-        SelectDoc(docView: DocumentView, ctrlPressed: boolean): void {
+        SelectView(docView: DocumentView, ctrlPressed: boolean): void {
             // if doc is not in SelectedDocuments, add it
-            if (!manager.SelectedDocuments.get(docView)) {
+            if (!manager.SelectedViews.get(docView)) {
                 if (!ctrlPressed) {
                     this.DeselectAll();
                 }
 
-                manager.SelectedDocuments.set(docView, true);
+                manager.SelectedViews.set(docView, true);
                 docView.props.whenActiveChanged(true);
-            } else if (!ctrlPressed && Array.from(manager.SelectedDocuments.entries()).length > 1) {
-                Array.from(manager.SelectedDocuments.keys()).map(dv => dv !== docView && dv.props.whenActiveChanged(false));
+            } else if (!ctrlPressed && Array.from(manager.SelectedViews.entries()).length > 1) {
+                Array.from(manager.SelectedViews.keys()).map(dv => dv !== docView && dv.props.whenActiveChanged(false));
                 manager.SelectedSchemaDocument = undefined;
                 manager.SelectedSchemaCollection = undefined;
-                manager.SelectedDocuments.clear();
-                manager.SelectedDocuments.set(docView, true);
+                manager.SelectedViews.clear();
+                manager.SelectedViews.set(docView, true);
             }
         }
         @action
-        DeselectDoc(docView: DocumentView): void {
+        DeselectView(docView: DocumentView): void {
 
-            if (manager.SelectedDocuments.get(docView)) {
-                manager.SelectedDocuments.delete(docView);
+            if (manager.SelectedViews.get(docView)) {
+                manager.SelectedViews.delete(docView);
                 docView.props.whenActiveChanged(false);
             }
         }
@@ -49,49 +49,49 @@ export namespace SelectionManager {
         DeselectAll(): void {
             manager.SelectedSchemaCollection = undefined;
             manager.SelectedSchemaDocument = undefined;
-            Array.from(manager.SelectedDocuments.keys()).map(dv => dv.props.whenActiveChanged(false));
-            manager.SelectedDocuments.clear();
+            Array.from(manager.SelectedViews.keys()).map(dv => dv.props.whenActiveChanged(false));
+            manager.SelectedViews.clear();
         }
     }
 
     const manager = new Manager();
 
-    export function DeselectDoc(docView: DocumentView): void {
-        manager.DeselectDoc(docView);
+    export function DeselectView(docView: DocumentView): void {
+        manager.DeselectView(docView);
     }
-    export function SelectDoc(docView: DocumentView, ctrlPressed: boolean): void {
-        manager.SelectDoc(docView, ctrlPressed);
+    export function SelectView(docView: DocumentView, ctrlPressed: boolean): void {
+        manager.SelectView(docView, ctrlPressed);
     }
-    export function SelectSchemaDoc(colSchema: Opt<CollectionSchemaView>, document: Opt<Doc>): void {
-        manager.SelectSchemaDoc(colSchema, document);
+    export function SelectSchemaView(colSchema: Opt<CollectionSchemaView>, document: Opt<Doc>): void {
+        manager.SelectSchemaView(colSchema, document);
     }
 
     const IsSelectedCache = computedFn(function isSelected(doc: DocumentView) {  // wraapping get() in a computedFn only generates mobx() invalidations when the return value of the function for the specific get parameters has changed
-        return manager.SelectedDocuments.get(doc) ? true : false;
+        return manager.SelectedViews.get(doc) ? true : false;
     });
     // computed functions, such as used in IsSelected generate errors if they're called outside of a
     // reaction context.  Specifying the context with 'outsideReaction' allows an efficiency feature
     // to avoid unnecessary mobx invalidations when running inside a reaction.
     export function IsSelected(doc: DocumentView | undefined, outsideReaction?: boolean): boolean {
         return !doc ? false : outsideReaction ?
-            manager.SelectedDocuments.get(doc) ? true : false : // get() accesses a hashtable -- setting anything in the hashtable generates a mobx invalidation for every get()
+            manager.SelectedViews.get(doc) ? true : false : // get() accesses a hashtable -- setting anything in the hashtable generates a mobx invalidation for every get()
             IsSelectedCache(doc);
     }
 
     export function DeselectAll(except?: Doc): void {
         let found: DocumentView | undefined = undefined;
         if (except) {
-            for (const view of Array.from(manager.SelectedDocuments.keys())) {
+            for (const view of Array.from(manager.SelectedViews.keys())) {
                 if (view.props.Document === except) found = view;
             }
         }
 
         manager.DeselectAll();
-        if (found) manager.SelectDoc(found, false);
+        if (found) manager.SelectView(found, false);
     }
 
-    export function SelectedDocuments(): Array<DocumentView> {
-        return Array.from(manager.SelectedDocuments.keys()).filter(dv => dv.props.Document._viewType !== CollectionViewType.Docking);
+    export function Views(): Array<DocumentView> {
+        return Array.from(manager.SelectedViews.keys()).filter(dv => dv.props.Document._viewType !== CollectionViewType.Docking);
     }
     export function SelectedSchemaDoc(): Doc | undefined {
         return manager.SelectedSchemaDocument;
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx
index 646926bb7..2aea73528 100644
--- a/src/client/util/SharingManager.tsx
+++ b/src/client/util/SharingManager.tsx
@@ -166,7 +166,7 @@ export class SharingManager extends React.Component<{}> {
         const key = normalizeEmail(StrCast(group.title));
         const acl = `acl-${key}`;
 
-        const docs = SelectionManager.SelectedDocuments().length < 2 ? [target] : SelectionManager.SelectedDocuments().map(docView => docView.props.Document);
+        const docs = SelectionManager.Views().length < 2 ? [target] : SelectionManager.Views().map(docView => docView.props.Document);
 
         docs.forEach(doc => {
             doc.author === Doc.CurrentUserEmail && !doc[`acl-${Doc.CurrentUserEmailNormalized}`] && distributeAcls(`acl-${Doc.CurrentUserEmailNormalized}`, SharingPermissions.Admin, doc);
@@ -271,7 +271,7 @@ export class SharingManager extends React.Component<{}> {
         const acl = `acl-${normalizeEmail(user.email)}`;
         const myAcl = `acl-${Doc.CurrentUserEmailNormalized}`;
 
-        const docs = SelectionManager.SelectedDocuments().length < 2 ? [target] : SelectionManager.SelectedDocuments().map(docView => docView.props.Document);
+        const docs = SelectionManager.Views().length < 2 ? [target] : SelectionManager.Views().map(docView => docView.props.Document);
         docs.forEach(doc => {
             doc.author === Doc.CurrentUserEmail && !doc[myAcl] && distributeAcls(myAcl, SharingPermissions.Admin, doc);
             distributeAcls(acl, permission as SharingPermissions, doc);
@@ -323,7 +323,7 @@ export class SharingManager extends React.Component<{}> {
 
     private focusOn = (contents: string) => {
         const title = this.targetDoc ? StrCast(this.targetDoc.title) : "";
-        const docs = SelectionManager.SelectedDocuments().length > 1 ? SelectionManager.SelectedDocuments().map(docView => docView.props.Document) : [this.targetDoc];
+        const docs = SelectionManager.Views().length > 1 ? SelectionManager.Views().map(docView => docView.props.Document) : [this.targetDoc];
         return (
             <span
                 className={"focus-span"}
@@ -407,7 +407,7 @@ export class SharingManager extends React.Component<{}> {
 
         const target = targetDoc || this.targetDoc!;
 
-        const docs = SelectionManager.SelectedDocuments().length < 2 ? [target] : SelectionManager.SelectedDocuments().map(docView => docView.props.Document);
+        const docs = SelectionManager.Views().length < 2 ? [target] : SelectionManager.Views().map(docView => docView.props.Document);
         docs.forEach(doc => {
             for (const [key, value] of Object.entries(doc[AclSym])) {
                 distributeAcls(key, AclMap.get(value)! as SharingPermissions, target);
@@ -458,9 +458,9 @@ export class SharingManager extends React.Component<{}> {
         const groups = this.groupSort === "ascending" ? groupList.slice().sort(this.sortGroups) : this.groupSort === "descending" ? groupList.slice().sort(this.sortGroups).reverse() : groupList;
 
         // handles the case where multiple documents are selected
-        let docs = SelectionManager.SelectedDocuments().length < 2 ?
+        let docs = SelectionManager.Views().length < 2 ?
             [this.layoutDocAcls ? this.targetDoc : this.targetDoc?.[DataSym]]
-            : SelectionManager.SelectedDocuments().map(docView => this.layoutDocAcls ? docView.props.Document : docView.props.Document?.[DataSym]);
+            : SelectionManager.Views().map(docView => this.layoutDocAcls ? docView.props.Document : docView.props.Document?.[DataSym]);
 
         if (this.myDocAcls) {
             const newDocs: Doc[] = [];
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index dc6311696..96f5d78fd 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -187,7 +187,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={<><div className="dash-tooltip">{SelectionManager.SelectedDocuments().length > 1 ? "Pin multiple documents to presentation" : "Pin to presentation"}</div></>}>
+        return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{SelectionManager.Views().length > 1 ? "Pin multiple documents to presentation" : "Pin to presentation"}</div></>}>
             <div className="documentButtonBar-linker"
                 style={{ color: "white" }}
                 onClick={undoBatch(e => this.props.views().map(view => view && TabDocView.PinDoc(view.props.Document, false)))}>
@@ -336,7 +336,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
     }
 
     openContextMenu = (e: React.MouseEvent) => {
-        let child = SelectionManager.SelectedDocuments()[0].ContentDiv!.children[0];
+        let child = SelectionManager.Views()[0].ContentDiv!.children[0];
         while (child.children.length) {
             const next = Array.from(child.children).find(c => typeof (c.className) === "string");
             if (next?.className.includes(DocumentView.ROOT_DIV)) break;
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 1d0c5dac0..eed77b398 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -57,12 +57,12 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
     constructor(props: any) {
         super(props);
         DocumentDecorations.Instance = this;
-        reaction(() => SelectionManager.SelectedDocuments().slice(), docs => this.titleBlur(false));
+        reaction(() => SelectionManager.Views().slice(), docs => this.titleBlur(false));
     }
 
     @computed
     get Bounds(): { x: number, y: number, b: number, r: number } {
-        return SelectionManager.SelectedDocuments().map(dv => dv.getBounds()).reduce((bounds, rect) =>
+        return SelectionManager.Views().map(dv => dv.getBounds()).reduce((bounds, rect) =>
             !rect ? bounds :
                 {
                     x: Math.min(rect.left, bounds.x),
@@ -80,8 +80,8 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
                 this._titleControlString = this._accumulatedTitle;
             } else if (this._titleControlString.startsWith("#")) {
                 const selectionTitleFieldKey = this._titleControlString.substring(1);
-                selectionTitleFieldKey === "title" && (SelectionManager.SelectedDocuments()[0].dataDoc["title-custom"] = !this._accumulatedTitle.startsWith("-"));
-                UndoManager.RunInBatch(() => selectionTitleFieldKey && SelectionManager.SelectedDocuments().forEach(d => {
+                selectionTitleFieldKey === "title" && (SelectionManager.Views()[0].dataDoc["title-custom"] = !this._accumulatedTitle.startsWith("-"));
+                UndoManager.RunInBatch(() => selectionTitleFieldKey && SelectionManager.Views().forEach(d => {
                     const value = typeof d.props.Document[selectionTitleFieldKey] === "number" ? +this._accumulatedTitle : this._accumulatedTitle;
                     Doc.SetInPlace(d.props.Document, selectionTitleFieldKey, value, true);
                 }), "title blur");
@@ -96,7 +96,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
             const text = e.target.value;
             if (text.startsWith("::")) {
                 this._accumulatedTitle = text.slice(2, text.length);
-                const promoteDoc = SelectionManager.SelectedDocuments()[0];
+                const promoteDoc = SelectionManager.Views()[0];
                 Doc.SetInPlace(promoteDoc.props.Document, "title", this._accumulatedTitle, true);
                 DocUtils.Publish(promoteDoc.props.Document, this._accumulatedTitle, promoteDoc.props.addDocument, promoteDoc.props.removeDocument);
             }
@@ -118,8 +118,8 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
 
     @action
     onBackgroundMove = (dragTitle: boolean, e: PointerEvent): boolean => {
-        const dragDocView = SelectionManager.SelectedDocuments()[0];
-        const dragData = new DragManager.DocumentDragData(SelectionManager.SelectedDocuments().map(dv => dv.props.Document));
+        const dragDocView = SelectionManager.Views()[0];
+        const dragData = new DragManager.DocumentDragData(SelectionManager.Views().map(dv => dv.props.Document));
         const { left, top } = dragDocView.getBounds() || { left: 0, top: 0 };
         dragData.offset = dragDocView.props.ScreenToLocalTransform().scale(dragDocView.ContentScale()).transformDirection(e.x - left, e.y - top);
         dragData.moveDocument = dragDocView.props.moveDocument;
@@ -128,7 +128,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
         dragData.dropAction = dragDocView.props.dropAction;
         this.Interacting = true;
         this._hidden = true;
-        DragManager.StartDocumentDrag(SelectionManager.SelectedDocuments().map(dv => dv.ContentDiv!), dragData, e.x, e.y, {
+        DragManager.StartDocumentDrag(SelectionManager.Views().map(dv => dv.ContentDiv!), dragData, e.x, e.y, {
             dragComplete: action(e => {
                 dragData.canEmbed && SelectionManager.DeselectAll();
                 this._hidden = this.Interacting = false;
@@ -145,7 +145,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
     @action
     onCloseClick = async (e: React.MouseEvent | undefined) => {
         if (!e?.button) {
-            const selected = SelectionManager.SelectedDocuments().slice();
+            const selected = SelectionManager.Views().slice();
             SelectionManager.DeselectAll();
             selected.map(dv => dv.props.removeDocument?.(dv.props.Document));
         }
@@ -158,7 +158,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
     @action
     onMaximizeClick = (e: PointerEvent): void => {
         if (e.button === 0) {
-            const selectedDocs = SelectionManager.SelectedDocuments();
+            const selectedDocs = SelectionManager.Views();
             if (selectedDocs.length) {
                 if (e.ctrlKey) {    // open an alias in a new tab with Ctrl Key
                     selectedDocs[0].props.Document._fullScreenView = Doc.MakeAlias(selectedDocs[0].props.Document);
@@ -181,7 +181,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
     @action
     onIconifyClick = (e: PointerEvent): void => {
         if (e.button === 0) {
-            SelectionManager.SelectedDocuments().forEach(dv => dv?.iconify());
+            SelectionManager.Views().forEach(dv => dv?.iconify());
         }
         SelectionManager.DeselectAll();
     }
@@ -189,7 +189,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
     @action
     onSelectorUp = (e: React.PointerEvent): void => {
         setupMoveUpEvents(this, e, returnFalse, emptyFunction, action((e) => {
-            const selDoc = SelectionManager.SelectedDocuments()?.[0];
+            const selDoc = SelectionManager.Views()?.[0];
             if (selDoc) {
                 selDoc.props.ContainingCollectionView?.props.select(false);
             }
@@ -207,7 +207,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
     onRadiusMove = (e: PointerEvent, down: number[]): boolean => {
         let dist = Math.sqrt((e.clientX - down[0]) * (e.clientX - down[0]) + (e.clientY - down[1]) * (e.clientY - down[1]));
         dist = dist < 3 ? 0 : dist;
-        SelectionManager.SelectedDocuments().map(dv => dv.props.Document).map(doc => doc.layout instanceof Doc ? doc.layout : doc.isTemplateForField ? doc : Doc.GetProto(doc)).
+        SelectionManager.Views().map(dv => dv.props.Document).map(doc => doc.layout instanceof Doc ? doc.layout : doc.isTemplateForField ? doc : Doc.GetProto(doc)).
             map(d => d.borderRounding = `${Math.max(0, dist)}px`);
         return false;
     }
@@ -220,7 +220,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
         setupMoveUpEvents(this, e, this.onRotateMove, this.onRotateUp, (e) => { });
         this._prevX = e.clientX;
         this._prevY = e.clientY;
-        SelectionManager.SelectedDocuments().forEach(action((element: DocumentView) => {
+        SelectionManager.Views().forEach(action((element: DocumentView) => {
             const doc = Document(element.rootDoc);
             if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) {
                 const ink = Cast(doc.data, InkField)?.inkData;
@@ -257,7 +257,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
         this._prevX = e.clientX;
         this._prevY = e.clientY;
         var index = 0;
-        SelectionManager.SelectedDocuments().forEach(action((element: DocumentView) => {
+        SelectionManager.Views().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);
@@ -304,7 +304,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
     onPointerDown = (e: React.PointerEvent): void => {
 
         this._inkDocs = [];
-        SelectionManager.SelectedDocuments().forEach(action((element: DocumentView) => {
+        SelectionManager.Views().forEach(action((element: DocumentView) => {
             const doc = Document(element.rootDoc);
             if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height) {
                 this._inkDocs.push({ x: doc.x, y: doc.y, width: doc._width, height: doc._height });
@@ -327,18 +327,18 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
         this._snapX = e.pageX;
         this._snapY = e.pageY;
         this._initialAutoHeight = true;
-        DragManager.docsBeingDragged = SelectionManager.SelectedDocuments().map(dv => dv.rootDoc);
-        SelectionManager.SelectedDocuments().map(dv => {
+        DragManager.docsBeingDragged = SelectionManager.Views().map(dv => dv.rootDoc);
+        SelectionManager.Views().map(dv => {
             this._dragHeights.set(dv.layoutDoc, NumCast(dv.layoutDoc._height));
             dv.layoutDoc._delayAutoHeight = dv.layoutDoc._height;
         });
     }
 
     onPointerMove = (e: PointerEvent, down: number[], move: number[]): boolean => {
-        const first = SelectionManager.SelectedDocuments()[0];
+        const first = SelectionManager.Views()[0];
         let thisPt = { thisX: e.clientX - this._offX, thisY: e.clientY - this._offY };
         var fixedAspect = Doc.NativeAspect(first.layoutDoc);
-        SelectionManager.SelectedDocuments().forEach(action((element: DocumentView) => {
+        SelectionManager.Views().forEach(action((element: DocumentView) => {
             const doc = Document(element.rootDoc);
             if (doc.type === DocumentType.INK && doc._width && doc._height && InkStrokeProperties.Instance?._lock) {
                 fixedAspect = Doc.NativeHeight(doc);
@@ -371,7 +371,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
         let dragRight = false;
         let dX = 0, dY = 0, dW = 0, dH = 0;
         const unfreeze = () =>
-            SelectionManager.SelectedDocuments().forEach(action((element: DocumentView) =>
+            SelectionManager.Views().forEach(action((element: DocumentView) =>
                 ((element.rootDoc.type === DocumentType.RTF ||
                     element.rootDoc.type === DocumentType.COMPARISON ||
                     (element.rootDoc.type === DocumentType.WEB && Doc.LayoutField(element.rootDoc) instanceof HtmlField))
@@ -420,7 +420,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
                 break;
         }
 
-        SelectionManager.SelectedDocuments().forEach(action((docView: DocumentView) => {
+        SelectionManager.Views().forEach(action((docView: DocumentView) => {
             if (e.ctrlKey && !Doc.NativeHeight(docView.props.Document)) docView.toggleNativeDimensions();
             if (dX !== 0 || dY !== 0 || dW !== 0 || dH !== 0) {
                 const doc = Document(docView.rootDoc);
@@ -486,7 +486,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
 
     @action
     onPointerUp = (e: PointerEvent): void => {
-        SelectionManager.SelectedDocuments().map(dv => {
+        SelectionManager.Views().map(dv => {
             if (NumCast(dv.layoutDoc._delayAutoHeight) < this._dragHeights.get(dv.layoutDoc)!) {
                 dv.nativeWidth > 0 && Doc.toggleNativeDimensions(dv.layoutDoc, dv.ContentScale(), dv.props.PanelWidth(), dv.props.PanelHeight());
                 dv.layoutDoc._autoHeight = true;
@@ -501,7 +501,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
 
 
         //need to change points for resize, or else rotation/control points will fail.
-        SelectionManager.SelectedDocuments().forEach(action((element: DocumentView, index) => {
+        SelectionManager.Views().forEach(action((element: DocumentView, index) => {
             const doc = Document(element.rootDoc);
             if (doc.type === DocumentType.INK && doc.x && doc.y && doc._height && doc._width) {
                 const ink = Cast(doc.data, InkField)?.inkData;
@@ -524,8 +524,8 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
 
     @computed
     get selectionTitle(): string {
-        if (SelectionManager.SelectedDocuments().length === 1) {
-            const selected = SelectionManager.SelectedDocuments()[0];
+        if (SelectionManager.Views().length === 1) {
+            const selected = SelectionManager.Views()[0];
             if (this._titleControlString.startsWith("=")) {
                 return ScriptField.MakeFunction(this._titleControlString.substring(1), { doc: Doc.name })!.script.run({ self: selected.rootDoc, this: selected.layoutDoc }, console.log).result?.toString() || "";
             }
@@ -533,7 +533,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
                 return Field.toString(selected.props.Document[this._titleControlString.substring(1)] as Field) || "-unset-";
             }
             return this._accumulatedTitle;
-        } else if (SelectionManager.SelectedDocuments().length > 1) {
+        } else if (SelectionManager.Views().length > 1) {
             return "-multiple-";
         }
         return "-unset-";
@@ -558,16 +558,16 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
     render() {
         const darkScheme = CurrentUserUtils.ActiveDashboard?.darkScheme ? "dimgray" : undefined;
         const bounds = this.Bounds;
-        const seldoc = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0] : undefined;
+        const seldoc = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
         if (SnappingManager.GetIsDragging() || bounds.r - bounds.x < 1 || bounds.x === Number.MAX_VALUE || !seldoc || this._hidden || isNaN(bounds.r) || isNaN(bounds.b) || isNaN(bounds.x) || isNaN(bounds.y)) {
             return (null);
         }
-        const canDelete = SelectionManager.SelectedDocuments().some(docView => {
+        const canDelete = SelectionManager.Views().some(docView => {
             const collectionAcl = docView.props.ContainingCollectionView ? GetEffectiveAcl(docView.props.ContainingCollectionDoc?.[DataSym]) : AclEdit;
             const docAcl = GetEffectiveAcl(docView.props.Document);
             return !docView.props.Document._stayInCollection && (collectionAcl === AclAdmin || collectionAcl === AclEdit || docAcl === AclAdmin);
         });
-        const canOpen = SelectionManager.SelectedDocuments().some(docView => !docView.props.Document._stayInCollection);
+        const canOpen = SelectionManager.Views().some(docView => !docView.props.Document._stayInCollection);
         const closeIcon = !canDelete ? (null) : (
             <Tooltip title={<div className="dash-tooltip">Close</div>} placement="top">
                 <div className="documentDecorations-closeButton" onClick={this.onCloseClick}>
@@ -575,7 +575,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
                 </div></Tooltip>);
 
         const openIcon = !canOpen ? (null) : <Tooltip title={<div className="dash-tooltip">Open in Tab (ctrl: as alias, shift: in new collection)</div>} placement="top"><div className="documentDecorations-openInTab" onContextMenu={e => { e.preventDefault(); e.stopPropagation(); }} onPointerDown={this.onMaximizeDown}>
-            {SelectionManager.SelectedDocuments().length === 1 ? <FontAwesomeIcon icon="external-link-alt" className="documentView-minimizedIcon" /> : "..."}
+            {SelectionManager.Views().length === 1 ? <FontAwesomeIcon icon="external-link-alt" className="documentView-minimizedIcon" /> : "..."}
         </div>
         </Tooltip>;
 
@@ -606,7 +606,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
                 left: bounds.x - this._resizeBorderWidth / 2,
                 top: bounds.y - this._resizeBorderWidth / 2,
                 pointerEvents: KeyManager.Instance.ShiftPressed || this.Interacting ? "none" : "all",
-                zIndex: SelectionManager.SelectedDocuments().length > 1 ? 900 : 0,
+                zIndex: SelectionManager.Views().length > 1 ? 900 : 0,
             }} onPointerDown={this.onBackgroundDown} onContextMenu={e => { e.preventDefault(); e.stopPropagation(); }} >
             </div>
             {bounds.r - bounds.x < 15 && bounds.b - bounds.y < 15 ? (null) : <>
@@ -618,7 +618,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
                 }}>
                     {closeIcon}
                     {bounds.r - bounds.x < 100 ? null : titleArea}
-                    {SelectionManager.SelectedDocuments().length !== 1 || seldoc.Document.type === DocumentType.INK ? (null) :
+                    {SelectionManager.Views().length !== 1 || seldoc.Document.type === DocumentType.INK ? (null) :
                         <Tooltip title={<div className="dash-tooltip">{`${seldoc.finalLayoutKey.includes("icon") ? "De" : ""}Iconify Document`}</div>} placement="top">
                             <div className="documentDecorations-iconifyButton" onPointerDown={this.onIconifyDown}>
                                 <FontAwesomeIcon icon={seldoc.finalLayoutKey.includes("icon") ? "window-restore" : "window-minimize"} className="documentView-minimizedIcon" />
@@ -645,7 +645,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
 
                 </div >
                 {seldoc?.Document.type === DocumentType.FONTICON ? (null) : <div className="link-button-container" key="links" style={{ left: bounds.x - this._resizeBorderWidth / 2 + 10, top: bounds.b + this._resizeBorderWidth / 2 }}>
-                    <DocumentButtonBar views={SelectionManager.SelectedDocuments} />
+                    <DocumentButtonBar views={SelectionManager.Views} />
                 </div>}
             </>}
         </div >
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index a391bb550..3311a4dcc 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -93,7 +93,7 @@ export class KeyManager {
                     return { stopPropagation: false, preventDefault: false };
                 }
 
-                const ungroupings = SelectionManager.SelectedDocuments().slice();
+                const ungroupings = SelectionManager.Views().slice();
                 UndoManager.RunInBatch(() => ungroupings.map(dv => dv.layoutDoc.group = undefined), "ungroup");
                 SelectionManager.DeselectAll();
                 break;
@@ -102,7 +102,7 @@ export class KeyManager {
                     return { stopPropagation: false, preventDefault: false };
                 }
 
-                const groupings = SelectionManager.SelectedDocuments().slice();
+                const groupings = SelectionManager.Views().slice();
                 const randomGroup = random(0, 1000);
                 UndoManager.RunInBatch(() => groupings.map(dv => dv.layoutDoc.group = randomGroup), "group");
                 SelectionManager.DeselectAll();
@@ -139,14 +139,14 @@ export class KeyManager {
                     return { stopPropagation: false, preventDefault: false };
                 }
 
-                const selected = SelectionManager.SelectedDocuments().slice();
+                const selected = SelectionManager.Views().slice();
                 UndoManager.RunInBatch(() => selected.map(dv => !dv.props.Document._stayInCollection && dv.props.removeDocument?.(dv.props.Document)), "delete");
                 SelectionManager.DeselectAll();
                 break;
-            case "arrowleft": UndoManager.RunInBatch(() => SelectionManager.SelectedDocuments().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge(-1, 0)), "nudge left"); break;
-            case "arrowright": UndoManager.RunInBatch(() => SelectionManager.SelectedDocuments().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(1, 0)), "nudge right"); break;
-            case "arrowup": UndoManager.RunInBatch(() => SelectionManager.SelectedDocuments().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, -1)), "nudge up"); break;
-            case "arrowdown": UndoManager.RunInBatch(() => SelectionManager.SelectedDocuments().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, 1)), "nudge down"); break;
+            case "arrowleft": UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge(-1, 0)), "nudge left"); break;
+            case "arrowright": UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(1, 0)), "nudge right"); break;
+            case "arrowup": UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, -1)), "nudge up"); break;
+            case "arrowdown": UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, 1)), "nudge down"); break;
         }
 
         return {
@@ -160,10 +160,10 @@ export class KeyManager {
         const preventDefault = false;
 
         switch (keyname) {
-            case "arrowleft": UndoManager.RunInBatch(() => SelectionManager.SelectedDocuments().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(-10, 0)), "nudge left"); break;
-            case "arrowright": UndoManager.RunInBatch(() => SelectionManager.SelectedDocuments().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(10, 0)), "nudge right"); break;
-            case "arrowup": UndoManager.RunInBatch(() => SelectionManager.SelectedDocuments().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, -10)), "nudge up"); break;
-            case "arrowdown": UndoManager.RunInBatch(() => SelectionManager.SelectedDocuments().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, 10)), "nudge down"); break;
+            case "arrowleft": UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(-10, 0)), "nudge left"); break;
+            case "arrowright": UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(10, 0)), "nudge right"); break;
+            case "arrowup": UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, -10)), "nudge up"); break;
+            case "arrowdown": UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, 10)), "nudge down"); break;
         }
 
         return {
@@ -179,7 +179,7 @@ export class KeyManager {
         switch (keyname) {
             case "ƒ":
             case "f":
-                const dv = SelectionManager.SelectedDocuments()?.[0];
+                const dv = SelectionManager.Views()?.[0];
                 UndoManager.RunInBatch(() => dv?.float(), "float");
         }
 
@@ -219,7 +219,7 @@ export class KeyManager {
                 SearchBox.Instance.enter(undefined);
                 break;
             case "o":
-                const target = SelectionManager.SelectedDocuments()[0];
+                const target = SelectionManager.Views()[0];
                 target && CollectionDockingView.OpenFullScreen(target.props.Document);
                 break;
             case "r":
@@ -246,11 +246,11 @@ export class KeyManager {
                 preventDefault = false;
                 break;
             case "x":
-                if (SelectionManager.SelectedDocuments().length) {
+                if (SelectionManager.Views().length) {
                     const bds = DocumentDecorations.Instance.Bounds;
-                    const pt = SelectionManager.SelectedDocuments()[0].props.ScreenToLocalTransform().transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2);
-                    const text = `__DashDocId(${pt?.[0] || 0},${pt?.[1] || 0}):` + SelectionManager.SelectedDocuments().map(dv => dv.Document[Id]).join(":");
-                    SelectionManager.SelectedDocuments().length && navigator.clipboard.writeText(text);
+                    const pt = SelectionManager.Views()[0].props.ScreenToLocalTransform().transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2);
+                    const text = `__DashDocId(${pt?.[0] || 0},${pt?.[1] || 0}):` + SelectionManager.Views().map(dv => dv.Document[Id]).join(":");
+                    SelectionManager.Views().length && navigator.clipboard.writeText(text);
                     DocumentDecorations.Instance.onCloseClick(undefined);
                     stopPropagation = false;
                     preventDefault = false;
@@ -259,9 +259,9 @@ export class KeyManager {
             case "c":
                 if (!PDFMenu.Instance.Active && DocumentDecorations.Instance.Bounds.r - DocumentDecorations.Instance.Bounds.x > 2) {
                     const bds = DocumentDecorations.Instance.Bounds;
-                    const pt = SelectionManager.SelectedDocuments()[0].props.ScreenToLocalTransform().transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2);
-                    const text = `__DashCloneId(${pt?.[0] || 0},${pt?.[1] || 0}):` + SelectionManager.SelectedDocuments().map(dv => dv.Document[Id]).join(":");
-                    SelectionManager.SelectedDocuments().length && navigator.clipboard.writeText(text);
+                    const pt = SelectionManager.Views()[0].props.ScreenToLocalTransform().transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2);
+                    const text = `__DashCloneId(${pt?.[0] || 0},${pt?.[1] || 0}):` + SelectionManager.Views().map(dv => dv.Document[Id]).join(":");
+                    SelectionManager.Views().length && navigator.clipboard.writeText(text);
                     stopPropagation = false;
                 }
                 preventDefault = false;
@@ -278,7 +278,7 @@ export class KeyManager {
         const plain = e.clipboardData?.getData("text/plain");
         const clone = plain?.startsWith("__DashCloneId(");
         if (plain && (plain.startsWith("__DashDocId(") || clone)) {
-            const first = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0] : undefined;
+            const first = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
             if (first?.props.Document.type === DocumentType.COL) {
                 const docids = plain.split(":");
                 let count = 1;
diff --git a/src/client/views/InkStrokeProperties.ts b/src/client/views/InkStrokeProperties.ts
index ad5c70fb1..2dac44bf8 100644
--- a/src/client/views/InkStrokeProperties.ts
+++ b/src/client/views/InkStrokeProperties.ts
@@ -25,7 +25,7 @@ export class InkStrokeProperties {
     }
 
     @computed get selectedInk() {
-        const inks = SelectionManager.SelectedDocuments().filter(i => Document(i.rootDoc).type === DocumentType.INK);
+        const inks = SelectionManager.Views().filter(i => Document(i.rootDoc).type === DocumentType.INK);
         return inks.length ? inks : undefined;
     }
     @computed get unFilled() { return this.selectedInk?.reduce((p, i) => p && !i.rootDoc.fillColor ? true : false, true) || false; }
@@ -150,7 +150,7 @@ export class InkStrokeProperties {
     @action
     rotate = (angle: number) => {
         const _centerPoints: { X: number, Y: number }[] = [];
-        SelectionManager.SelectedDocuments().forEach(action(inkView => {
+        SelectionManager.Views().forEach(action(inkView => {
             const doc = Document(inkView.rootDoc);
             if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) {
                 const ink = Cast(doc.data, InkField)?.inkData;
@@ -167,7 +167,7 @@ export class InkStrokeProperties {
         }));
 
         var index = 0;
-        SelectionManager.SelectedDocuments().forEach(action(inkView => {
+        SelectionManager.Views().forEach(action(inkView => {
             const doc = Document(inkView.rootDoc);
             if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) {
                 doc.rotation = Number(doc.rotation) + Number(angle);
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index 1731d715a..bc3be4076 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -55,8 +55,8 @@ export class PropertiesButtons extends React.Component<{}, {}> {
 
     @computed get selectedDoc() { return SelectionManager.SelectedSchemaDoc() || this.selectedDocumentView?.rootDoc; }
     @computed get selectedDocumentView() {
-        if (SelectionManager.SelectedDocuments().length) {
-            return SelectionManager.SelectedDocuments()[0];
+        if (SelectionManager.Views().length) {
+            return SelectionManager.Views()[0];
         } else return undefined;
     }
 
@@ -187,7 +187,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
 
     @action @undoBatch
     onLock = () => {
-        SelectionManager.SelectedDocuments().forEach(dv => dv.docView?.toggleLockPosition());
+        SelectionManager.Views().forEach(dv => dv.docView?.toggleLockPosition());
     }
 
     @computed
@@ -224,7 +224,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     @undoBatch
     @action
     setDictation = () => {
-        SelectionManager.SelectedDocuments().forEach(dv => dv.rootDoc._showAudio = dv.rootDoc._showAudio === !dv.rootDoc._showAudio);
+        SelectionManager.Views().forEach(dv => dv.rootDoc._showAudio = dv.rootDoc._showAudio === !dv.rootDoc._showAudio);
     }
 
     @computed
@@ -244,7 +244,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     @undoBatch
     @action
     setTitle = () => {
-        SelectionManager.SelectedDocuments().forEach(dv => dv.rootDoc._showTitle = dv.rootDoc._showTitle === undefined ? "title" : undefined);
+        SelectionManager.Views().forEach(dv => dv.rootDoc._showTitle = dv.rootDoc._showTitle === undefined ? "title" : undefined);
     }
 
     @computed
@@ -263,7 +263,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     @undoBatch
     @action
     setCaption = () => {
-        SelectionManager.SelectedDocuments().forEach(dv => dv.rootDoc._showCaption = dv.rootDoc._showCaption === undefined ? "caption" : undefined);
+        SelectionManager.Views().forEach(dv => dv.rootDoc._showCaption = dv.rootDoc._showCaption === undefined ? "caption" : undefined);
     }
 
     @computed
@@ -282,7 +282,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     @undoBatch
     @action
     setChrome = () => {
-        SelectionManager.SelectedDocuments().forEach(dv => dv.rootDoc._chromeStatus = dv.rootDoc._chromeStatus === "disabled" ? "enabled" : "disabled");
+        SelectionManager.Views().forEach(dv => dv.rootDoc._chromeStatus = dv.rootDoc._chromeStatus === "disabled" ? "enabled" : "disabled");
     }
 
     @computed
@@ -325,7 +325,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
         const value = e.target.value;
         this.selectedDoc && (this.selectedDoc.onClickBehavior = e.target.value);
 
-        SelectionManager.SelectedDocuments().forEach(dv => {
+        SelectionManager.Views().forEach(dv => {
             if (value === "nothing") {
                 dv.docView?.noOnClick();
             } else if (value === "enterPortal") {
@@ -347,7 +347,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     @undoBatch @action
     editOnClickScript = () => {
         if (this.selectedDoc) {
-            if (SelectionManager.SelectedDocuments().length) SelectionManager.SelectedDocuments().forEach(dv => DocUtils.makeCustomViewClicked(dv.rootDoc, undefined, "onClick"));
+            if (SelectionManager.Views().length) SelectionManager.Views().forEach(dv => DocUtils.makeCustomViewClicked(dv.rootDoc, undefined, "onClick"));
             else DocUtils.makeCustomViewClicked(this.selectedDoc, undefined, "onClick");
         }
     }
@@ -432,7 +432,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     @action @undoBatch
     changeFitToBox = () => {
         if (this.selectedDoc) {
-            if (SelectionManager.SelectedDocuments().length) SelectionManager.SelectedDocuments().forEach(dv => dv.rootDoc._fitToBox = !dv.rootDoc._fitToBox);
+            if (SelectionManager.Views().length) SelectionManager.Views().forEach(dv => dv.rootDoc._fitToBox = !dv.rootDoc._fitToBox);
             else this.selectedDoc._fitToBox = !this.selectedDoc._fitToBox;
         }
     }
@@ -440,7 +440,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     @action @undoBatch
     changeClusters = () => {
         if (this.selectedDoc) {
-            if (SelectionManager.SelectedDocuments().length) SelectionManager.SelectedDocuments().forEach(dv => dv.rootDoc._useClusters = !dv.rootDoc._useClusters);
+            if (SelectionManager.Views().length) SelectionManager.Views().forEach(dv => dv.rootDoc._useClusters = !dv.rootDoc._useClusters);
             else this.selectedDoc._useClusters = !this.selectedDoc._useClusters;
         }
     }
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 1c14bc721..32342075c 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -48,7 +48,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
     @computed get selectedDoc() { return SelectionManager.SelectedSchemaDoc() || this.selectedDocumentView?.rootDoc; }
     @computed get selectedDocumentView() {
-        if (SelectionManager.SelectedDocuments().length) return SelectionManager.SelectedDocuments()[0];
+        if (SelectionManager.Views().length) return SelectionManager.Views()[0];
         if (PresBox.Instance?._selectedArray.size) return DocumentManager.Instance.getDocumentView(PresBox.Instance.rootDoc);
         return undefined;
     }
@@ -118,8 +118,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     @computed get expandedField() {
         if (this.dataDoc && this.selectedDoc) {
             const ids: { [key: string]: string } = {};
-            const docs = SelectionManager.SelectedDocuments().length < 2 ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc] :
-                SelectionManager.SelectedDocuments().map(dv => this.layoutFields ? Doc.Layout(dv.layoutDoc) : dv.dataDoc);
+            const docs = SelectionManager.Views().length < 2 ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc] :
+                SelectionManager.Views().map(dv => this.layoutFields ? Doc.Layout(dv.layoutDoc) : dv.dataDoc);
             docs.forEach(doc => Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key)));
             const rows: JSX.Element[] = [];
             for (const key of Object.keys(ids).slice().sort()) {
@@ -162,7 +162,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     @computed get noviceFields() {
         if (this.dataDoc) {
             const ids: { [key: string]: string } = {};
-            const docs = SelectionManager.SelectedDocuments().length < 2 ? [this.dataDoc] : SelectionManager.SelectedDocuments().map(dv => dv.dataDoc);
+            const docs = SelectionManager.Views().length < 2 ? [this.dataDoc] : SelectionManager.Views().map(dv => dv.dataDoc);
             docs.forEach(doc => Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key)));
             const rows: JSX.Element[] = [];
             const noviceReqFields = ["author", "creationDate", "tags"];
@@ -217,7 +217,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
     @undoBatch
     setKeyValue = (value: string) => {
-        const docs = SelectionManager.SelectedDocuments().length < 2 && this.selectedDoc ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc] : SelectionManager.SelectedDocuments().map(dv => this.layoutFields ? dv.layoutDoc : dv.dataDoc);
+        const docs = SelectionManager.Views().length < 2 && this.selectedDoc ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc] : SelectionManager.Views().map(dv => this.layoutFields ? dv.layoutDoc : dv.dataDoc);
         docs.forEach(doc => {
             if (value.indexOf(":") !== -1) {
                 const newVal = value[0].toUpperCase() + value.substring(1, value.length);
@@ -256,7 +256,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     }
 
     @computed get layoutPreview() {
-        if (SelectionManager.SelectedDocuments().length > 1) {
+        if (SelectionManager.Views().length > 1) {
             return "-- multiple selected --";
         }
         if (this.selectedDoc) {
@@ -305,7 +305,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
      */
     @undoBatch
     changePermissions = (e: any, user: string) => {
-        const docs = SelectionManager.SelectedDocuments().length < 2 ? [this.selectedDoc!] : SelectionManager.SelectedDocuments().map(docView => docView.props.Document);
+        const docs = SelectionManager.Views().length < 2 ? [this.selectedDoc!] : SelectionManager.Views().map(docView => docView.props.Document);
         SharingManager.Instance.shareFromPropertiesSidebar(user, e.currentTarget.value as SharingPermissions, docs);
     }
 
@@ -385,9 +385,9 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         ]);
 
         // all selected docs
-        const docs = SelectionManager.SelectedDocuments().length < 2 ?
+        const docs = SelectionManager.Views().length < 2 ?
             [this.layoutDocAcls ? this.selectedDoc! : this.selectedDoc![DataSym]]
-            : SelectionManager.SelectedDocuments().map(docView => this.layoutDocAcls ? docView.props.Document : docView.props.Document[DataSym]);
+            : SelectionManager.Views().map(docView => this.layoutDocAcls ? docView.props.Document : docView.props.Document[DataSym]);
 
         const target = docs[0];
 
@@ -438,7 +438,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
     @computed get editableTitle() {
         const titles = new Set<string>();
-        SelectionManager.SelectedDocuments().forEach(dv => titles.add(StrCast(dv.rootDoc.title)));
+        SelectionManager.Views().forEach(dv => titles.add(StrCast(dv.rootDoc.title)));
         const title = Array.from(titles.keys()).length > 1 ? "--multiple selected--" : StrCast(this.selectedDoc?.title);
         return <div className="editable-title"><EditableView
             key="editableView"
@@ -452,8 +452,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     @undoBatch
     @action
     setTitle = (value: string) => {
-        if (SelectionManager.SelectedDocuments().length > 1) {
-            SelectionManager.SelectedDocuments().map(dv => Doc.SetInPlace(dv.rootDoc, "title", value, true));
+        if (SelectionManager.Views().length > 1) {
+            SelectionManager.Views().map(dv => Doc.SetInPlace(dv.rootDoc, "title", value, true));
             return true;
         } else if (this.dataDoc) {
             if (this.selectedDoc) Doc.SetInPlace(this.selectedDoc, "title", value, true);
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index d6571276a..83192164f 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -135,7 +135,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps |
             switch (doc?.type) {
                 case DocumentType.COL:
                     return StrCast(doc?.boxShadow,
-                        isBackground() || doc?._isGroup ? undefined : // groups have no drop shadow -- they're supposed to be "invisible"
+                        isBackground() || doc?._isGroup || docProps?.LayoutTemplateString ? undefined : // groups have no drop shadow -- they're supposed to be "invisible".  LayoutString's imply collection is being rendered as something else (e.g., title of a Slide)
                             `${darkScheme() ? "rgb(30, 32, 31) " : "#9c9396 "} ${StrCast(doc.boxShadow, "0.2vw 0.2vw 0.8vw")}`);
                 default:
                     return doc.z ? `#9c9396  ${StrCast(doc?.boxShadow, "10px 10px 0.9vw")}` :  // if it's a floating doc, give it a big shadow
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 20b4fa2d7..3839dff8b 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -52,7 +52,7 @@ export class CollectionMenu extends AntimodeMenu<AntimodeMenuProps> {
     }
 
     componentDidMount() {
-        reaction(() => SelectionManager.SelectedDocuments().length && SelectionManager.SelectedDocuments()[0],
+        reaction(() => SelectionManager.Views().length && SelectionManager.Views()[0],
             (doc) => doc && this.SetSelection(doc));
     }
 
@@ -372,7 +372,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
     }
 
     @computed get selectedDocumentView() {
-        return SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0] : undefined;
+        return SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
     }
     @computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; }
     @computed get notACollection() {
@@ -554,7 +554,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
     }
 
     @computed get selectedDocumentView() {
-        return SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0] : undefined;
+        return SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
     }
     @computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; }
     @computed get isText() {
@@ -621,7 +621,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
 
     @action
     editProperties = (value: any, field: string) => {
-        SelectionManager.SelectedDocuments().forEach(action((element: DocumentView) => {
+        SelectionManager.Views().forEach(action((element: DocumentView) => {
             const doc = Document(element.rootDoc);
             if (doc.type === DocumentType.INK) {
                 switch (field) {
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index f153f1cca..c39f8b255 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -352,7 +352,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     @action setFocused = (doc: Doc) => this._focusedTable = doc;
 
     @action setPreviewDoc = (doc: Opt<Doc>) => {
-        SelectionManager.SelectSchemaDoc(this, doc);
+        SelectionManager.SelectSchemaView(this, doc);
         this._previewDoc = doc;
     }
 
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 38e461e46..d7b9d9745 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -305,8 +305,8 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
                         } else {
                             let srcUrl: string | undefined;
                             let srcWeb: Doc | undefined;
-                            if (SelectionManager.SelectedDocuments().length) {
-                                srcWeb = SelectionManager.SelectedDocuments()[0].props.Document;
+                            if (SelectionManager.Views().length) {
+                                srcWeb = SelectionManager.Views()[0].props.Document;
                                 srcUrl = (srcWeb.data as WebField).url?.href?.match(/http[s]?:\/\/[^/]*/)?.[0];
                             }
                             const reg = new RegExp(Utils.prepend(""), "g");
@@ -315,7 +315,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
                             Doc.GetProto(htmlDoc)["data-text"] = Doc.GetProto(htmlDoc).text = text;
                             this.addDocument(htmlDoc);
                             if (srcWeb) {
-                                const iframe = SelectionManager.SelectedDocuments()[0].ContentDiv?.getElementsByTagName("iframe")?.[0];
+                                const iframe = SelectionManager.Views()[0].ContentDiv?.getElementsByTagName("iframe")?.[0];
                                 const focusNode = (iframe?.contentDocument?.getSelection()?.focusNode as any);
                                 if (focusNode) {
                                     const rects = iframe?.contentWindow?.getSelection()?.getRangeAt(0).getClientRects();
diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss
index f774af74f..72ab51784 100644
--- a/src/client/views/collections/CollectionTreeView.scss
+++ b/src/client/views/collections/CollectionTreeView.scss
@@ -21,7 +21,7 @@
 
     ul {
         list-style: none;
-        padding-left: 20px;
+        padding-left: $TREE_BULLET_WIDTH;
         margin-bottom: 1px; // otherwise vertical scrollbars may pop up for no apparent reason....
         > .contentFittingDocumentView  {
             width: unset;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index a90edc2c9..344a6c103 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -189,6 +189,7 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
     onChildClick = () => this.props.onChildClick?.() || ScriptCast(this.doc.onChildClick);
     whenActiveChanged = (isActive: boolean) => { this.props.whenActiveChanged(this._isChildActive = isActive); };
     active = (outsideReaction: boolean | undefined) => this.props.active(outsideReaction) || this._isChildActive;
+    panelWidth = () => this.props.PanelWidth() - 20; // bcz: 20 is the 10 + 10 for the left and right padding.
     @computed get treeChildren() {
         TraceMobx();
         return this.props.childDocuments || this.childDocs;
@@ -200,7 +201,7 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
         const moveDoc = (d: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => this.props.moveDocument?.(d, target, addDoc) || false;
         return TreeView.GetChildElements(this.treeChildren, this, this.doc, this.props.DataDoc, this.props.fieldKey, this.props.ContainingCollectionDoc, undefined, addDoc, this.remove,
             moveDoc, dropAction, this.props.addDocTab, this.props.pinToPres, this.props.styleProvider, this.props.ScreenToLocalTransform,
-            this.outerXf, this.active, this.props.PanelWidth, this.props.renderDepth, () => this.props.treeViewHideHeaderFields || BoolCast(this.doc.treeViewHideHeaderFields),
+            this.outerXf, this.active, this.panelWidth, this.props.renderDepth, () => this.props.treeViewHideHeaderFields || BoolCast(this.doc.treeViewHideHeaderFields),
             BoolCast(this.doc.treeViewPreventOpen), [], this.props.onCheckedClick,
             this.onChildClick, this.props.treeViewSkipFields, true, this.whenActiveChanged, this.props.dontRegisterView || Cast(this.props.Document.dontRegisterChildViews, "boolean", null));
     }
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index a4ab201bc..0d03936dc 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -117,14 +117,14 @@ export class TabDocView extends React.Component<TabDocViewProps> {
             // select the tab document when the tab is directly clicked and activate the tab whenver the tab document is selected
             titleEle.onpointerdown = action((e: any) => {
                 if (e.target.className !== "lm_close_tab") {
-                    if (this.view) SelectionManager.SelectDoc(this.view, false);
+                    if (this.view) SelectionManager.SelectView(this.view, false);
                     else this._activated = true;
                     if (Date.now() - titleEle.lastClick < 1000) titleEle.select();
                     titleEle.lastClick = Date.now();
                     (document.activeElement !== titleEle) && titleEle.focus();
                 }
             });
-            tab._disposers.selectionDisposer = reaction(() => SelectionManager.SelectedDocuments().some(v => v.topMost && v.props.Document === doc),
+            tab._disposers.selectionDisposer = reaction(() => SelectionManager.Views().some(v => v.topMost && v.props.Document === doc),
                 action((selected) => {
                     if (selected) this._activated = true;
                     const toggle = tab.element[0].children[1].children[0] as HTMLInputElement;
@@ -222,7 +222,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
     }
 
     componentDidMount() {
-        const selected = () => SelectionManager.SelectedDocuments().some(v => v.props.Document === this._document);
+        const selected = () => SelectionManager.Views().some(v => v.props.Document === this._document);
         new _global.ResizeObserver(action((entries: any) => {
             for (const entry of entries) {
                 this._panelWidth = entry.contentRect.width;
diff --git a/src/client/views/collections/TreeView.scss b/src/client/views/collections/TreeView.scss
index 8468e27df..7a654c7cf 100644
--- a/src/client/views/collections/TreeView.scss
+++ b/src/client/views/collections/TreeView.scss
@@ -37,7 +37,7 @@
     }
     .bullet {
         position: relative;
-        width: 20px;
+        width: $TREE_BULLET_WIDTH;
         color: $intermediate-color;
         margin-top: 3px;
         transform: scale(1.3, 1.3);
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 31a1a2b99..f51c745bb 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -1,6 +1,7 @@
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, computed, observable } from "mobx";
 import { observer } from "mobx-react";
+import { TREE_BULLET_WIDTH } from '../globalCssVariables.scss';
 import { DataSym, Doc, DocListCast, DocListCastOrNull, Field, HeightSym, Opt, WidthSym } from '../../../fields/Doc';
 import { Id } from '../../../fields/FieldSymbols';
 import { List } from '../../../fields/List';
@@ -64,6 +65,8 @@ export interface TreeViewProps {
     whenActiveChanged: (isActive: boolean) => void;
 }
 
+let treeBulletWidth = function () { return Number(TREE_BULLET_WIDTH.replace("px", "")); }
+
 @observer
 /**
  * Renders a treeView of a collection of documents
@@ -83,6 +86,7 @@ export class TreeView extends React.Component<TreeViewProps> {
     private _uniqueId = Utils.GenerateGuid();
     private _editMaxWidth: number | string = 0;
 
+
     @observable _dref: DocumentView | undefined | null;
     @computed get doc() { TraceMobx(); return this.props.document; }
     get noviceMode() { return BoolCast(Doc.UserDoc().noviceMode, false); }
@@ -284,9 +288,9 @@ export class TreeView extends React.Component<TreeViewProps> {
     docWidth = () => {
         const layoutDoc = this.layoutDoc;
         const aspect = Doc.NativeAspect(layoutDoc);
-        if (layoutDoc._fitWidth) return Math.min(this.props.panelWidth() - 20, layoutDoc[WidthSym]());
-        if (aspect) return Math.min(layoutDoc[WidthSym](), Math.min(this.MAX_EMBED_HEIGHT * aspect, this.props.panelWidth() - 20));
-        return Doc.NativeWidth(layoutDoc) ? Math.min(layoutDoc[WidthSym](), this.props.panelWidth() - 20) : Math.min(this.layoutDoc[WidthSym](), this.props.panelWidth() - 20);
+        if (layoutDoc._fitWidth) return Math.min(this.props.panelWidth() - treeBulletWidth(), layoutDoc[WidthSym]());
+        if (aspect) return Math.min(layoutDoc[WidthSym](), Math.min(this.MAX_EMBED_HEIGHT * aspect, this.props.panelWidth() - treeBulletWidth()));
+        return Math.min(this.props.panelWidth() - treeBulletWidth(), Doc.NativeWidth(layoutDoc) ? layoutDoc[WidthSym]() : this.layoutDoc[WidthSym]());
     }
     docHeight = () => {
         const layoutDoc = this.layoutDoc;
@@ -354,9 +358,9 @@ export class TreeView extends React.Component<TreeViewProps> {
         return rows;
     }
 
-    rtfWidth = () => Math.min(this.layoutDoc?.[WidthSym](), this.props.panelWidth() - 20);
+    rtfWidth = () => Math.min(this.layoutDoc?.[WidthSym](), this.props.panelWidth() - treeBulletWidth());
     rtfHeight = () => this.rtfWidth() <= this.layoutDoc?.[WidthSym]() ? Math.min(this.layoutDoc?.[HeightSym](), this.MAX_EMBED_HEIGHT) : this.MAX_EMBED_HEIGHT;
-    rtfOutlineHeight = () => Math.max(this.layoutDoc?.[HeightSym](), 20);
+    rtfOutlineHeight = () => Math.max(this.layoutDoc?.[HeightSym](), treeBulletWidth());
     expandPanelHeight = () => {
         if (this.layoutDoc._fitWidth) return this.docHeight();
         const aspect = this.layoutDoc[WidthSym]() / this.layoutDoc[HeightSym]();
@@ -486,7 +490,7 @@ export class TreeView extends React.Component<TreeViewProps> {
 
     showContextMenu = (e: React.MouseEvent) => simulateMouseClick(this._docRef.current?.ContentDiv, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30);
     contextMenuItems = () => Doc.IsSystem(this.doc) ? [] : [{ script: ScriptField.MakeFunction(`openOnRight(self)`)!, label: "Open" }, { script: ScriptField.MakeFunction(`DocFocus(self)`)!, label: "Focus" }];
-    truncateTitleWidth = () => NumCast(this.props.treeView.props.Document.treeViewTruncateTitleWidth, 0);
+    truncateTitleWidth = () => NumCast(this.props.treeView.props.Document.treeViewTruncateTitleWidth, this.props.panelWidth());
     onChildClick = () => this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptCast(this.doc.treeChildClick));
     onChildDoubleClick = () => (!this.outlineMode && this._openScript?.()) || ScriptCast(this.doc.treeChildDoubleClick);
 
@@ -553,8 +557,10 @@ export class TreeView extends React.Component<TreeViewProps> {
                 moveDocument={this.move}
                 removeDocument={this.props.removeDoc}
                 ScreenToLocalTransform={this.getTransform}
+                NativeHeight={returnZero}
+                NativeWidth={returnZero}
                 PanelWidth={this.truncateTitleWidth}
-                PanelHeight={returnZero}
+                PanelHeight={() => 18}
                 contextMenuItems={this.contextMenuItems}
                 renderDepth={1}
                 focus={returnTrue}
@@ -746,7 +752,7 @@ export class TreeView extends React.Component<TreeViewProps> {
 
         const docs = TreeView.sortDocs(childDocs, StrCast(containingCollection?.[key + "-sortCriteria"]));
 
-        const rowWidth = () => panelWidth() - 20;
+        const rowWidth = () => panelWidth() - treeBulletWidth();
         return docs.filter(child => child instanceof Doc).map((child, i) => {
             const pair = Doc.GetLayoutDataDocPair(containingCollection, dataDoc, child);
             if (!pair.layout || pair.data instanceof Promise) {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 1add65c10..0fb1c0f9c 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -208,7 +208,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
 
     private selectDocuments = (docs: Doc[]) => {
         SelectionManager.DeselectAll();
-        docs.map(doc => DocumentManager.Instance.getDocumentView(doc, this.props.CollectionView)).map(dv => dv && SelectionManager.SelectDoc(dv, true));
+        docs.map(doc => DocumentManager.Instance.getDocumentView(doc, this.props.CollectionView)).map(dv => dv && SelectionManager.SelectView(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); }
 
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 47ffc48fb..d20d1abfc 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -152,7 +152,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
                 this.props.addDocument?.(slide);
                 //setTimeout(() => SelectionManager.SelectDoc(DocumentManager.Instance.getDocumentView(slide)!, false));
                 e.stopPropagation();
-            } else if (!e.ctrlKey && !e.metaKey && SelectionManager.SelectedDocuments().length < 2) {
+            } else if (!e.ctrlKey && !e.metaKey && SelectionManager.Views().length < 2) {
                 FormattedTextBox.SelectOnLoadChar = FormattedTextBox.DefaultLayout && !this.props.childLayoutString ? e.key : "";
                 FormattedTextBox.LiveTextUndo = UndoManager.StartBatch("live text batch");
                 this.props.addLiveTextDocument(CurrentUserUtils.GetNewTextDoc("-typed text-", x, y, 200, 100, this.props.xMargin === 0));
diff --git a/src/client/views/globalCssVariables.scss b/src/client/views/globalCssVariables.scss
index b2ea87c06..ccc9306c4 100644
--- a/src/client/views/globalCssVariables.scss
+++ b/src/client/views/globalCssVariables.scss
@@ -39,6 +39,7 @@ $MINIMIZED_ICON_SIZE:25;
 $MAX_ROW_HEIGHT: 44px;
 $DFLT_IMAGE_NATIVE_DIM: 900px;
 $MENU_PANEL_WIDTH: 60px;
+$TREE_BULLET_WIDTH: 20px;
 
 :export {
     contextMenuZindex: $contextMenu-zindex;
@@ -51,4 +52,5 @@ $MENU_PANEL_WIDTH: 60px;
     SEARCH_PANEL_HEIGHT: $searchpanel-height;
     DFLT_IMAGE_NATIVE_DIM: $DFLT_IMAGE_NATIVE_DIM;
     MENU_PANEL_WIDTH: $MENU_PANEL_WIDTH;
+    TREE_BULLET_WIDTH: $TREE_BULLET_WIDTH;
 }
\ No newline at end of file
diff --git a/src/client/views/globalCssVariables.scss.d.ts b/src/client/views/globalCssVariables.scss.d.ts
index c56b75d5e..11e62e1eb 100644
--- a/src/client/views/globalCssVariables.scss.d.ts
+++ b/src/client/views/globalCssVariables.scss.d.ts
@@ -10,6 +10,7 @@ interface IGlobalScss {
     SEARCH_PANEL_HEIGHT: string;
     DFLT_IMAGE_NATIVE_DIM: string;
     MENU_PANEL_WIDTH: string;
+    TREE_BULLET_WIDTH: string;
 }
 declare const globalCssVariables: IGlobalScss;
 
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index 4b3c328b0..67d25e525 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -135,7 +135,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD
             }, { fireImmediately: true });
 
         // for play when link is selected
-        this._disposers.reaction = reaction(() => SelectionManager.SelectedDocuments(),
+        this._disposers.reaction = reaction(() => SelectionManager.Views(),
             selected => {
                 const sel = selected.length ? selected[0].props.Document : undefined;
                 let link;
diff --git a/src/client/views/nodes/ColorBox.tsx b/src/client/views/nodes/ColorBox.tsx
index 52236a648..d5b6a269e 100644
--- a/src/client/views/nodes/ColorBox.tsx
+++ b/src/client/views/nodes/ColorBox.tsx
@@ -31,7 +31,7 @@ export class ColorBox extends ViewBoxBaseComponent<FieldViewProps, ColorDocument
         SetActiveInkColor(color.hex);
 
         if (Doc.GetSelectedTool() === InkTool.None) {
-            const selected = SelectionManager.SelectedDocuments();
+            const selected = SelectionManager.Views();
             selected.map(view => {
                 const targetDoc = view.props.Document.dragFactory instanceof Doc ? view.props.Document.dragFactory :
                     view.props.Document.layout instanceof Doc ? view.props.Document.layout :
@@ -54,7 +54,7 @@ export class ColorBox extends ViewBoxBaseComponent<FieldViewProps, ColorDocument
         super(props);
     }
     render() {
-        const selDoc = SelectionManager.SelectedDocuments()?.[0]?.rootDoc;
+        const selDoc = SelectionManager.Views()?.[0]?.rootDoc;
         return <div className={`colorBox-container${this.active() ? "-interactive" : ""}`}
             onPointerDown={e => e.button === 0 && !e.ctrlKey && e.stopPropagation()} onClick={e => { (e.nativeEvent as any).stuff = true; e.stopPropagation(); }}
             style={{ width: `${100}%`, height: `${100}%` }} >
@@ -67,7 +67,7 @@ export class ColorBox extends ViewBoxBaseComponent<FieldViewProps, ColorDocument
                 <div> {ActiveInkWidth() ?? 2}</div>
                 <input type="range" defaultValue={ActiveInkWidth() ?? 2} min={1} max={100} onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
                     SetActiveInkWidth(e.target.value);
-                    SelectionManager.SelectedDocuments().filter(i => StrCast(i.rootDoc.type) === DocumentType.INK).map(i => i.rootDoc.strokeWidth = Number(e.target.value));
+                    SelectionManager.Views().filter(i => StrCast(i.rootDoc.type) === DocumentType.INK).map(i => i.rootDoc.strokeWidth = Number(e.target.value));
                 }} />
                 {/* <div> {ActiveInkBezierApprox() ?? 2}</div>
                 <input type="range" defaultValue={ActiveInkBezierApprox() ?? 2} min={0} max={300} onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 3c140a22a..56982bd89 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -409,7 +409,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                     self: this.rootDoc,
                     scriptContext: this.props.scriptContext,
                     thisContainer: this.props.ContainingCollectionDoc,
-                    documentView: this,
+                    documentView: this.props.DocumentView,
                     shiftKey
                 }, console.log);
                 const clickFunc = () => {
@@ -616,7 +616,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
         if (e && this.rootDoc._hideContextMenu && Doc.UserDoc().noviceMode) {
             e.preventDefault();
             e.stopPropagation();
-            !this.props.isSelected(true) && SelectionManager.SelectDoc(this.props.DocumentView, false);
+            !this.props.isSelected(true) && SelectionManager.SelectView(this.props.DocumentView, false);
         }
         // the touch onContextMenu is button 0, the pointer onContextMenu is button 2
         if (e) {
@@ -658,8 +658,8 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
 
             const zorders = cm.findByDescription("ZOrder...");
             const zorderItems: ContextMenuProps[] = zorders && "subitems" in zorders ? zorders.subitems : [];
-            zorderItems.push({ description: "Bring to Front", event: () => SelectionManager.SelectedDocuments().forEach(dv => dv.props.bringToFront(dv.rootDoc, false)), icon: "expand-arrows-alt" });
-            zorderItems.push({ description: "Send to Back", event: () => SelectionManager.SelectedDocuments().forEach(dv => dv.props.bringToFront(dv.rootDoc, true)), icon: "expand-arrows-alt" });
+            zorderItems.push({ description: "Bring to Front", event: () => SelectionManager.Views().forEach(dv => dv.props.bringToFront(dv.rootDoc, false)), icon: "expand-arrows-alt" });
+            zorderItems.push({ description: "Send to Back", event: () => SelectionManager.Views().forEach(dv => dv.props.bringToFront(dv.rootDoc, true)), icon: "expand-arrows-alt" });
             zorderItems.push({ description: this.rootDoc._raiseWhenDragged !== false ? "Keep ZIndex when dragged" : "Allow ZIndex to change when dragged", event: undoBatch(action(() => this.rootDoc._raiseWhenDragged = this.rootDoc._raiseWhenDragged === undefined ? false : undefined)), icon: "expand-arrows-alt" });
             !zorders && cm.addItem({ description: "ZOrder...", subitems: zorderItems, icon: "compass" });
 
@@ -733,7 +733,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                 e?.stopPropagation(); // DocumentViews should stop propagation of this event
             }
             cm.displayMenu((e?.pageX || pageX || 0) - 15, (e?.pageY || pageY || 0) - 15);
-            !this.props.isSelected(true) && setTimeout(() => SelectionManager.SelectDoc(this.props.DocumentView, false), 300); // on a mac, the context menu is triggered on mouse down, but a YouTube video becaomes interactive when selected which means that the context menu won't show up.  by delaying the selection until hopefully after the pointer up, the context menu will appear.
+            !this.props.isSelected(true) && setTimeout(() => SelectionManager.SelectView(this.props.DocumentView, false), 300); // on a mac, the context menu is triggered on mouse down, but a YouTube video becaomes interactive when selected which means that the context menu won't show up.  by delaying the selection until hopefully after the pointer up, the context menu will appear.
         });
     }
 
@@ -983,7 +983,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
                 topDoc.x = fpt[0];
                 topDoc.y = fpt[1];
             }
-            setTimeout(() => SelectionManager.SelectDoc(DocumentManager.Instance.getDocumentView(topDoc, container)!, false), 0);
+            setTimeout(() => SelectionManager.SelectView(DocumentManager.Instance.getDocumentView(topDoc, container)!, false), 0);
         }
     }
 
@@ -1061,7 +1061,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     });
 
     isSelected = (outsideReaction?: boolean) => SelectionManager.IsSelected(this, outsideReaction);
-    select = (ctrlPressed: boolean) => SelectionManager.SelectDoc(this, ctrlPressed);
+    select = (ctrlPressed: boolean) => SelectionManager.SelectView(this, ctrlPressed);
     NativeWidth = () => this.nativeWidth;
     NativeHeight = () => this.nativeHeight;
     PanelWidth = () => this.panelWidth;
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index da74edbe3..42462000b 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -160,7 +160,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         this.props.Document.presentationFieldKey = this.fieldKey; // provide info to the presElement script so that it can look up rendering information about the presBox
     }
     @computed get selectedDocumentView() {
-        if (SelectionManager.SelectedDocuments().length) return SelectionManager.SelectedDocuments()[0];
+        if (SelectionManager.Views().length) return SelectionManager.Views()[0];
         if (this._selectedArray.size) return DocumentManager.Instance.getDocumentView(this.rootDoc);
     }
     @computed get isPres(): boolean {
@@ -195,7 +195,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         this.turnOffEdit(true);
         DocListCastAsync((Doc.UserDoc().myPresentations as Doc).data).then(pres =>
             !pres?.includes(this.rootDoc) && Doc.AddDocToList(Doc.UserDoc().myPresentations as Doc, "data", this.rootDoc));
-        this._disposers.selection = reaction(() => SelectionManager.SelectedDocuments(),
+        this._disposers.selection = reaction(() => SelectionManager.Views(),
             views => views.some(view => view.props.Document === this.rootDoc) && this.updateCurrentPresentation());
     }
 
@@ -404,7 +404,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         const self = this;
         const resetSelection = action(() => {
             const presDocView = DocumentManager.Instance.getDocumentView(self.rootDoc);
-            if (presDocView) SelectionManager.SelectDoc(presDocView, false);
+            if (presDocView) SelectionManager.SelectView(presDocView, false);
             self.rootDoc.presStatus = presStatus;
             self._selectedArray.clear();
             selViewCache.forEach(doc => self._selectedArray.set(doc, undefined));
@@ -761,7 +761,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
     @action
     selectPres = () => {
         const presDocView = DocumentManager.Instance.getDocumentView(this.rootDoc);
-        presDocView && SelectionManager.SelectDoc(presDocView, false);
+        presDocView && SelectionManager.SelectView(presDocView, false);
     }
 
     //Regular click
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index cf9b03308..07439825f 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -144,7 +144,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps>   {
     }
 
     componentDidMount() {
-        this._reaction = reaction(() => SelectionManager.SelectedDocuments(),
+        this._reaction = reaction(() => SelectionManager.Views(),
             () => this._delayHide && !(this._delayHide = false) && this.fadeOut(true));
     }
     componentWillUnmount() {
@@ -836,7 +836,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps>   {
                         if (linkDoc instanceof Doc) {
                             const anchor1 = await Cast(linkDoc.anchor1, Doc);
                             const anchor2 = await Cast(linkDoc.anchor2, Doc);
-                            const currentDoc = SelectionManager.SelectedDocuments().length && SelectionManager.SelectedDocuments()[0].props.Document;
+                            const currentDoc = SelectionManager.Views().length && SelectionManager.Views()[0].props.Document;
                             if (currentDoc && anchor1 && anchor2) {
                                 if (Doc.AreProtosEqual(currentDoc, anchor1)) {
                                     return StrCast(anchor2.title);
@@ -987,11 +987,11 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps>   {
                 <div className="richTextMenu-divider" key="divider 3" />,
                 {[this.createMarksDropdown(this.activeFontSize, this.fontSizeOptions, "font size", action((val: string) => {
                     this.activeFontSize = val;
-                    SelectionManager.SelectedDocuments().map(dv => dv.props.Document._fontSize = val);
+                    SelectionManager.Views().map(dv => dv.props.Document._fontSize = val);
                 })),
                 this.createMarksDropdown(this.activeFontFamily, this.fontFamilyOptions, "font family", action((val: string) => {
                     this.activeFontFamily = val;
-                    SelectionManager.SelectedDocuments().map(dv => dv.props.Document._fontFamily = val);
+                    SelectionManager.Views().map(dv => dv.props.Document._fontFamily = val);
                 })),
                 <div className="richTextMenu-divider" key="divider 4" />,
                 this.createNodesDropdown(this.activeListType, this.listTypeOptions, "list type", () => ({})),
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index d6d500702..02f7ada96 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -150,7 +150,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
                     this._savedAnnotations.keys().forEach(k => this._savedAnnotations.setValue(k, []));
                     PDFMenu.Instance.fadeOut(true);
                 }
-                (SelectionManager.SelectedDocuments().length === 1) && this.setupPdfJsViewer();
+                (SelectionManager.Views().length === 1) && this.setupPdfJsViewer();
             },
             { fireImmediately: true });
         this._disposers.scrollY = reaction(
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index d5f852c4d..e1ab1d3d3 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -1329,7 +1329,7 @@ Scripting.addGlobal(function activePresentationItem() {
     return curPres && DocListCast(curPres[Doc.LayoutFieldKey(curPres)])[NumCast(curPres._itemIndex)];
 });
 Scripting.addGlobal(function selectedDocs(container: Doc, excludeCollections: boolean, prevValue: any) {
-    const docs = SelectionManager.SelectedDocuments().map(dv => dv.props.Document).
+    const docs = SelectionManager.Views().map(dv => dv.props.Document).
         filter(d => !Doc.AreProtosEqual(d, container) && !d.annotationOn && d.type !== DocumentType.DOCHOLDER && d.type !== DocumentType.KVP &&
             (!excludeCollections || d.type !== DocumentType.COL || !Cast(d.data, listSpec(Doc), null)));
     return docs.length ? new List(docs) : prevValue;
-- 
cgit v1.2.3-70-g09d2

