From 7902b1021b89e45bd595e4a9588db11dccbf9831 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Sun, 28 Feb 2021 01:06:27 -0500
Subject: a bunch of changes to simplify how autoHeight works.  extended to
 work for pdfs and stacking views.  still some bugs.

---
 src/client/views/collections/CollectionStackingView.tsx | 17 +++++------------
 1 file changed, 5 insertions(+), 12 deletions(-)

(limited to 'src/client/views/collections/CollectionStackingView.tsx')

diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 77046f5ea..b5ce4b443 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -140,8 +140,10 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
             () => this.pivotField,
             () => this.layoutDoc._columnHeaders = new List()
         );
-        this._autoHeightDisposer = reaction(() => this.layoutDoc._autoHeight, this.forceAutoHeight);
+        this._autoHeightDisposer = reaction(() => this.layoutDoc._autoHeight,
+            () => this.props.setHeight(this.headerMargin + this.refList.reduce((p, r) => p + Number(getComputedStyle(r).height.replace("px", "")), 0)));
     }
+
     componentWillUnmount() {
         super.componentWillUnmount();
         this._pivotFieldDisposer?.();
@@ -369,11 +371,7 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
                             const height = this.headerMargin +
                                 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.isAnnotationOverlay) {
-                                doc[this.props.fieldKey + "-height"] = height;
-                            } else {
-                                Doc.Layout(doc)._height = height * NumCast(Doc.Layout(doc)._viewScale, 1);
-                            }
+                            this.props.setHeight(height * NumCast(Doc.Layout(doc)._viewScale, 1));
                         }
                     }));
                     this.observer.observe(ref);
@@ -398,11 +396,6 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
         return new Transform(-translateX, -translateY, 1).scale(this.props.ScreenToLocalTransform().Scale);
     }
 
-    forceAutoHeight = () => {
-        const doc = this.props.DataDoc && this.props.DataDoc.layout === this.layoutDoc ? this.props.DataDoc : this.layoutDoc;
-        Doc.Layout(doc)._height = this.headerMargin + this.refList.reduce((p, r) => p + Number(getComputedStyle(r).height.replace("px", "")), 0);
-    }
-
     sectionMasonry = (heading: SchemaHeaderField | undefined, docList: Doc[], first: boolean) => {
         const key = this.pivotField;
         let type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined = undefined;
@@ -422,7 +415,7 @@ 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 = this.refList.reduce((p, r) => p + Number(getComputedStyle(r).height.replace("px", "")), 0);
-                            Doc.Layout(doc)._height = this.headerMargin + Math.max(height, NumCast(doc[this.props.fieldKey + "-height"]));
+                            this.props.setHeight(this.headerMargin + height);
                         }
                     }));
                     this.observer.observe(ref);
-- 
cgit v1.2.3-70-g09d2


From 1b481cd441cc8bb200906b246b43e4bc5dc53b4e Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 2 Mar 2021 19:52:59 -0500
Subject: added a fitwidth toggle for lightbox.  fixed _showCaption/setting
 _fields to undefined.  updated documentView to use not having fitWidth set as
 a trigger for whether to treat a doc without nativeWidth/Height as if its
 width/height is that.

---
 src/client/documents/Documents.ts                  | 14 ++--
 src/client/views/DocumentDecorations.tsx           |  2 +-
 src/client/views/LightboxView.tsx                  |  5 ++
 src/client/views/PropertiesButtons.tsx             | 30 ++++++++-
 .../views/collections/CollectionStackingView.tsx   | 37 ++++++-----
 .../CollectionMulticolumnView.tsx                  |  6 +-
 .../CollectionMultirowView.tsx                     | 16 ++---
 src/client/views/nodes/DocumentView.tsx            | 75 +++++++++++++---------
 src/client/views/nodes/EquationBox.tsx             | 11 ++--
 src/client/views/nodes/VideoBox.tsx                |  2 +-
 src/fields/Schema.ts                               |  5 +-
 src/fields/util.ts                                 |  2 +-
 12 files changed, 125 insertions(+), 80 deletions(-)

(limited to 'src/client/views/collections/CollectionStackingView.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index e270d2ac8..f87c7185c 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -830,7 +830,7 @@ export namespace Docs {
         }
 
         export function KVPDocument(document: Doc, options: DocumentOptions = {}) {
-            return InstanceFromProto(Prototypes.get(DocumentType.KVP), document, { title: document.title + ".kvp", ...options });
+            return InstanceFromProto(Prototypes.get(DocumentType.KVP), document, { _fitWidth: true, title: document.title + ".kvp", ...options });
         }
 
         export function DocumentDocument(document?: Doc, options: DocumentOptions = {}) {
@@ -860,23 +860,23 @@ export namespace Docs {
         }
 
         export function CarouselDocument(documents: Array<Doc>, options: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", ...options, _viewType: CollectionViewType.Carousel });
+            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", _fitWidth: true, ...options, _viewType: CollectionViewType.Carousel });
         }
 
         export function Carousel3DDocument(documents: Array<Doc>, options: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", ...options, _viewType: CollectionViewType.Carousel3D });
+            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", _fitWidth: true, ...options, _viewType: CollectionViewType.Carousel3D });
         }
 
         export function SchemaDocument(schemaHeaders: SchemaHeaderField[], documents: Array<Doc>, options: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaHeaders: schemaHeaders.length ? new List(schemaHeaders) : undefined, ...options, _viewType: CollectionViewType.Schema });
+            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", _fitWidth: true, schemaHeaders: schemaHeaders.length ? new List(schemaHeaders) : undefined, ...options, _viewType: CollectionViewType.Schema });
         }
 
         export function TreeDocument(documents: Array<Doc>, options: DocumentOptions, id?: string) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", dontRegisterChildViews: true, ...options, _viewType: CollectionViewType.Tree }, id);
+            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", _fitWidth: true, dontRegisterChildViews: true, ...options, _viewType: CollectionViewType.Tree }, id);
         }
 
         export function StackingDocument(documents: Array<Doc>, options: DocumentOptions, id?: string, protoId?: string) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", ...options, _viewType: CollectionViewType.Stacking }, id, undefined, protoId);
+            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", _fitWidth: true, ...options, _viewType: CollectionViewType.Stacking }, id, undefined, protoId);
         }
 
         export function MulticolumnDocument(documents: Array<Doc>, options: DocumentOptions) {
@@ -926,7 +926,7 @@ export namespace Docs {
 
         export function DockDocument(documents: Array<Doc>, config: string, options: DocumentOptions, id?: string) {
             const inst = InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { freezeChildren: "remove|add", treeViewDefaultExpandedView: "data", ...options, _viewType: CollectionViewType.Docking, dockingConfig: config }, id);
-            const tabs = TreeDocument(documents, { title: "On-Screen Tabs", freezeChildren: "remove|add", treeViewLockExpandedView: true, treeViewDefaultExpandedView: "data", system: true });
+            const tabs = TreeDocument(documents, { title: "On-Screen Tabs", freezeChildren: "remove|add", treeViewLockExpandedView: true, treeViewDefaultExpandedView: "data", _fitWidth: true, system: true });
             const all = TreeDocument([], { title: "Off-Screen Tabs", freezeChildren: "add", treeViewLockExpandedView: true, treeViewDefaultExpandedView: "data", system: true });
             Doc.GetProto(inst).data = new List<Doc>([tabs, all]);
             return inst;
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 5b7394c42..1e3c0ba92 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -479,7 +479,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
         SelectionManager.Views().map(dv => {
             const hgts = this._dragHeights.get(dv.layoutDoc);
             if (hgts && hgts.lowest < hgts.start && hgts.lowest <= 20) {
-                dv.nativeWidth > 0 && Doc.toggleNativeDimensions(dv.layoutDoc, dv.ContentScale(), dv.props.PanelWidth(), dv.props.PanelHeight());
+                dv.effectiveNativeWidth > 0 && Doc.toggleNativeDimensions(dv.layoutDoc, dv.ContentScale(), dv.props.PanelWidth(), dv.props.PanelHeight());
                 if (dv.layoutDoc._autoHeight) dv.layoutDoc._autoHeight = false;
                 setTimeout(() => dv.layoutDoc._autoHeight = true);
             }
diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx
index 15b98467c..3fc72c45c 100644
--- a/src/client/views/LightboxView.tsx
+++ b/src/client/views/LightboxView.tsx
@@ -247,6 +247,7 @@ export class LightboxView extends React.Component<LightboxViewProps> {
                         ContainingCollectionDoc={undefined}
                         renderDepth={0} />
                 </div>
+
                 {this.navBtn(0, undefined, this.props.PanelHeight / 2 - 12.50, "chevron-left",
                     () => LightboxView.LightboxDoc && LightboxView._history?.length ? "" : "none", e => {
                         e.stopPropagation();
@@ -258,6 +259,10 @@ export class LightboxView extends React.Component<LightboxViewProps> {
                         LightboxView.Next();
                     })}
                 <LightboxTourBtn navBtn={this.navBtn} future={this.future} stepInto={this.stepInto} tourMap={this.tourMap} />
+                <div className="lightboxView-navBtn" title={"toggle fit width"} style={{ position: "absolute", right: 10, top: 10, color: "white" }}
+                    onClick={e => { e.stopPropagation(); LightboxView.LightboxDoc!._fitWidth = !LightboxView.LightboxDoc!._fitWidth }}>
+                    <FontAwesomeIcon icon={"arrows-alt-h"} size="2x" />
+                </div>
             </div>;
     }
 }
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index e9963bce9..e418a6f3c 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -260,7 +260,10 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     @undoBatch
     @action
     setCaption = () => {
-        SelectionManager.Views().forEach(dv => dv.rootDoc._showCaption = dv.rootDoc._showCaption === undefined ? "caption" : undefined);
+        SelectionManager.Views().forEach(dv => {
+            dv.rootDoc._showCaption = dv.rootDoc._showCaption === undefined ? "caption" : undefined;
+            console.log("caption = " + dv.rootDoc._showCaption);
+        });
     }
 
     @computed
@@ -426,6 +429,14 @@ export class PropertiesButtons extends React.Component<{}, {}> {
         }
     }
 
+    @action @undoBatch
+    changeFitWidth = () => {
+        if (this.selectedDoc) {
+            if (SelectionManager.Views().length) SelectionManager.Views().forEach(dv => dv.rootDoc._fitWidth = !dv.rootDoc._fitWidth);
+            else this.selectedDoc._fitWidth = !this.selectedDoc._fitWidth;
+        }
+    }
+
     @action @undoBatch
     changeClusters = () => {
         if (this.selectedDoc) {
@@ -448,6 +459,20 @@ export class PropertiesButtons extends React.Component<{}, {}> {
         </Tooltip>;
     }
 
+    @computed
+    get fitWidthButton() {
+        const targetDoc = this.selectedDoc;
+        return !targetDoc ? (null) : <Tooltip
+            title={<><div className="dash-tooltip">{this.selectedDoc?._fitWidth ? "Stop Fitting Width" : "Fit Width"}</div></>} placement="top">
+            <div>
+                <div className={`propertiesButtons-linkButton-empty toggle-${targetDoc._fitWidth ? "on" : "off"}`} onPointerDown={this.changeFitWidth}>
+                    <FontAwesomeIcon className="documentdecorations-icon" icon="arrows-alt-h" size="lg" />
+                </div>
+                <div className="propertiesButtons-title"> {this.selectedDoc?._fitWidth ? "unfit" : "fit"} </div>
+            </div>
+        </Tooltip>;
+    }
+
     @undoBatch
     @action
     private makeMask = () => {
@@ -521,6 +546,9 @@ export class PropertiesButtons extends React.Component<{}, {}> {
             <div className="propertiesButtons-button" style={{ display: !isFreeForm && !isText ? "none" : "" }}>
                 {this.fitContentButton}
             </div>
+            <div className="propertiesButtons-button">
+                {this.fitWidthButton}
+            </div>
             <div className="propertiesButtons-button" style={{ display: !isInk ? "none" : "" }}>
                 {this.maskButton}
             </div>
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index b5ce4b443..7152f4272 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -29,6 +29,7 @@ import "./CollectionStackingView.scss";
 import { CollectionStackingViewFieldColumn } from "./CollectionStackingViewFieldColumn";
 import { CollectionSubView } from "./CollectionSubView";
 import { CollectionViewType } from "./CollectionView";
+import { LightboxView } from "../LightboxView";
 const _global = (window /* browser */ || global /* node */) as any;
 
 type StackingDocument = makeInterface<[typeof collectionSchema, typeof documentSchema]>;
@@ -204,10 +205,10 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
         const dataDoc = (!doc.isTemplateDoc && !doc.isTemplateForField && !doc.PARAMS) ? undefined : this.props.DataDoc;
         const height = () => this.getDocHeight(doc);
 
-        let dref: Opt<HTMLDivElement>;
+        let dref: Opt<DocumentView>;
         const stackedDocTransform = () => this.getDocTransform(doc, dref);
         this._docXfs.push({ stackedDocTransform, width, height });
-        return <DocumentView ref={r => dref = r?.ContentDiv ? r.ContentDiv : undefined}
+        return <DocumentView ref={r => dref = r || undefined}
             Document={doc}
             DataDoc={dataDoc || (!Doc.AreProtosEqual(doc[DataSym], doc) && doc[DataSym])}
             renderDepth={this.props.renderDepth + 1}
@@ -247,18 +248,24 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
         />;
     }
 
+    getDocTransform(doc: Doc, dref?: DocumentView) {
+        const y = this._scroll; // required for document decorations to update when the text box container is scrolled
+        const { scale, translateX, translateY } = Utils.GetScreenTransform(dref?.ContentDiv || undefined);
+        // the document view may center its contents and if so, will prepend that onto the screenToLocalTansform.  so we have to subtract that off 
+        return new Transform(- translateX - (dref?.centeringX || 0), - translateY - (dref?.centeringY || 0), 1).scale(this.props.ScreenToLocalTransform().Scale * (this.props.scaling?.() || 1));
+    }
     getDocWidth(d?: Doc) {
         if (!d) return 0;
-        const layoutDoc = Doc.Layout(d, this.props.childLayoutTemplate?.());
-        const nw = Doc.NativeWidth(layoutDoc);
-        return Math.min(nw && !this.layoutDoc._columnsFill ? d[WidthSym]() : Number.MAX_VALUE, this.columnWidth / this.numGroupColumns);
+        const childLayoutDoc = Doc.Layout(d, this.props.childLayoutTemplate?.());
+        const nw = Doc.NativeWidth(childLayoutDoc) || (childLayoutDoc._fitWidth ? 0 : d[WidthSym]());
+        return Math.min(nw && !this.layoutDoc._columnsFill ? (this.props.scaling?.() || 1) * d[WidthSym]() : Number.MAX_VALUE, this.columnWidth / this.numGroupColumns);
     }
     getDocHeight(d?: Doc) {
         if (!d) return 0;
         const childDataDoc = (!d.isTemplateDoc && !d.isTemplateForField && !d.PARAMS) ? undefined : this.props.DataDoc;
         const childLayoutDoc = Doc.Layout(d, this.props.childLayoutTemplate?.());
-        const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc);
-        const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc);
+        const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc) || (childLayoutDoc._fitWidth ? 0 : d[WidthSym]());
+        const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc) || (childLayoutDoc._fitWidth ? 0 : d[HeightSym]());
         let wid = this.columnWidth / (this.isStackingView ? this.numGroupColumns : 1);
         if (!this.layoutDoc._columnsFill) wid = Math.min(wid, childLayoutDoc[WidthSym]());
         const hllimit = NumCast(this.layoutDoc.childLimitHeight, -1);
@@ -268,7 +275,7 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
             return Math.min(hllimit === 0 ? this.props.PanelWidth() : hllimit === -1 ? 10000 : hllimit, wid * aspect);
         }
         return childLayoutDoc._fitWidth ?
-            (!nh ? this.props.PanelHeight() - 2 * this.yMargin :
+            (!nh ? Math.min(NumCast(childLayoutDoc.height, 10000) * (this.props.scaling?.() || 1), this.props.PanelHeight() - 2 * this.yMargin) :
                 Math.min(wid * nh / (nw || 1), this.layoutDoc._autoHeight ? 100000 : this.props.PanelHeight() - 2 * this.yMargin)) :
             Math.min(hllimit === 0 ? this.props.PanelWidth() : hllimit === -1 ? 10000 : hllimit, Math.max(20, childLayoutDoc[HeightSym]()));
     }
@@ -361,8 +368,8 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
         const cols = () => this.isStackingView ? 1 : Math.max(1, Math.min(this.filteredChildren.length,
             Math.floor((this.props.PanelWidth() - 2 * this.xMargin) / (this.columnWidth + this.gridGap))));
         return <CollectionStackingViewFieldColumn
-            unobserveHeight={(ref) => this.refList.splice(this.refList.indexOf(ref), 1)}
-            observeHeight={(ref) => {
+            unobserveHeight={ref => this.refList.splice(this.refList.indexOf(ref), 1)}
+            observeHeight={ref => {
                 if (ref) {
                     this.refList.push(ref);
                     const doc = this.props.DataDoc && this.props.DataDoc.layout === this.layoutDoc ? this.props.DataDoc : this.layoutDoc;
@@ -371,7 +378,9 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
                             const height = this.headerMargin +
                                 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", "")))));
-                            this.props.setHeight(height * NumCast(Doc.Layout(doc)._viewScale, 1));
+                            if (!LightboxView.IsLightboxDocView(this.props.docViewPath())) {
+                                this.props.setHeight(height * NumCast(Doc.Layout(doc)._viewScale, 1));
+                            }
                         }
                     }));
                     this.observer.observe(ref);
@@ -390,12 +399,6 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
         />;
     }
 
-    getDocTransform(doc: Doc, dref?: HTMLDivElement) {
-        const y = this._scroll; // required for document decorations to update when the text box container is scrolled
-        const { scale, translateX, translateY } = Utils.GetScreenTransform(dref);
-        return new Transform(-translateX, -translateY, 1).scale(this.props.ScreenToLocalTransform().Scale);
-    }
-
     sectionMasonry = (heading: SchemaHeaderField | undefined, docList: Doc[], first: boolean) => {
         const key = this.pivotField;
         let type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined = undefined;
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
index e51417f64..d23f3309e 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
@@ -217,8 +217,8 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu
             Document={layout}
             DataDoc={layout.resolvedDataDoc as Doc}
             styleProvider={this.props.styleProvider}
-            layerProvider={undefined}
-            docViewPath={returnEmptyDoclist}
+            layerProvider={this.props.layerProvider}
+            docViewPath={this.props.docViewPath}
             LayoutTemplate={this.props.childLayoutTemplate}
             LayoutTemplateString={this.props.childLayoutString}
             freezeDimensions={this.props.childFreezeDimensions}
@@ -257,7 +257,7 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu
         const collector: JSX.Element[] = [];
         for (let i = 0; i < childLayoutPairs.length; i++) {
             const { layout } = childLayoutPairs[i];
-            const dxf = () => this.lookupIndividualTransform(layout).translate(-NumCast(Document._xMargin), -NumCast(Document._yMargin));
+            const dxf = () => this.lookupIndividualTransform(layout).translate(-NumCast(Document._xMargin), -NumCast(Document._yMargin)).scale((this.props.scaling?.() || 1));
             const width = () => this.lookupPixels(layout);
             const height = () => PanelHeight() - 2 * NumCast(Document._yMargin) - (BoolCast(Document.showWidthLabels) ? 20 : 0);
             collector.push(
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
index d61a2bb72..641ae6ce1 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
@@ -217,8 +217,8 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument)
             Document={layout}
             DataDoc={layout.resolvedDataDoc as Doc}
             styleProvider={this.props.styleProvider}
-            layerProvider={undefined}
-            docViewPath={returnEmptyDoclist}
+            layerProvider={this.props.layerProvider}
+            docViewPath={this.props.docViewPath}
             LayoutTemplate={this.props.childLayoutTemplate}
             LayoutTemplateString={this.props.childLayoutString}
             freezeDimensions={this.props.childFreezeDimensions}
@@ -257,19 +257,13 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument)
         const collector: JSX.Element[] = [];
         for (let i = 0; i < childLayoutPairs.length; i++) {
             const { layout } = childLayoutPairs[i];
-            const dxf = () => this.lookupIndividualTransform(layout).translate(-NumCast(Document._xMargin), -NumCast(Document._yMargin));
+            const dxf = () => this.lookupIndividualTransform(layout).translate(-NumCast(Document._xMargin), -NumCast(Document._yMargin)).scale((this.props.scaling?.() || 1));
             const height = () => this.lookupPixels(layout);
             const width = () => PanelWidth() - 2 * NumCast(Document._xMargin) - (BoolCast(Document.showWidthLabels) ? 20 : 0);
             collector.push(
-                <div
-                    className={"document-wrapper"}
-                    key={"wrapper" + i}
-                >
+                <div className={"document-wrapper"} key={"wrapper" + i} >
                     {this.getDisplayDoc(layout, dxf, width, height)}
-                    <HeightLabel
-                        layout={layout}
-                        collectionDoc={Document}
-                    />
+                    <HeightLabel layout={layout} collectionDoc={Document} />
                 </div>,
                 <ResizeBar
                     height={resizerHeight}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index e5bd14809..c86863ed8 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -997,30 +997,40 @@ export class DocumentView extends React.Component<DocumentViewProps> {
 
     @computed get docViewPath() { return this.props.docViewPath ? [...this.props.docViewPath(), this] : [this]; }
     @computed get layoutDoc() { return Doc.Layout(this.Document, this.props.LayoutTemplate?.()); }
-    @computed get nativeWidth() { return this.docView?._componentView?.reverseNativeScaling?.() ? 0 : returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.DataDoc, this.props.freezeDimensions)); }
-    @computed get nativeHeight() { return this.docView?._componentView?.reverseNativeScaling?.() ? 0 : returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, this.props.freezeDimensions) || 0); }
+    @computed get nativeWidth() {
+        return this.docView?._componentView?.reverseNativeScaling?.() ? 0 :
+            returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.DataDoc, this.props.freezeDimensions));
+    }
+    @computed get nativeHeight() {
+        return this.docView?._componentView?.reverseNativeScaling?.() ? 0 :
+            returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, this.props.freezeDimensions));
+    }
+    shouldNotScale = () => this.layoutDoc._fitWidth || [CollectionViewType.Docking, CollectionViewType.Tree].includes(this.Document._viewType as any);
+    @computed get effectiveNativeWidth() { return this.nativeWidth || (this.shouldNotScale() ? 0 : NumCast(this.layoutDoc.width)); }
+    @computed get effectiveNativeHeight() { return this.nativeHeight || (this.shouldNotScale() ? 0 : NumCast(this.layoutDoc.height)); }
     @computed get nativeScaling() {
-        if (this.nativeWidth && (this.layoutDoc?._fitWidth || this.props.PanelHeight() / this.nativeHeight > this.props.PanelWidth() / this.nativeWidth)) {
-            return this.props.PanelWidth() / this.nativeWidth;  // width-limited or fitWidth
+        const minTextScale = this.Document.type === DocumentType.RTF ? 0.1 : 0;
+        if (this.effectiveNativeWidth && (this.layoutDoc?._fitWidth || this.props.PanelHeight() / this.effectiveNativeHeight > this.props.PanelWidth() / this.effectiveNativeWidth)) {
+            return Math.max(minTextScale, this.props.PanelWidth() / this.effectiveNativeWidth);  // width-limited or fitWidth
         }
-        return this.nativeWidth && this.nativeHeight ? this.props.PanelHeight() / this.nativeHeight : 1; // height-limited or unscaled
+        return this.effectiveNativeWidth && this.effectiveNativeHeight ? Math.max(minTextScale, this.props.PanelHeight() / this.effectiveNativeHeight) : 1; // height-limited or unscaled
     }
 
-    @computed get panelWidth() { return this.nativeWidth ? this.nativeWidth * this.nativeScaling : this.props.PanelWidth(); }
+    @computed get panelWidth() { return this.effectiveNativeWidth ? this.effectiveNativeWidth * this.nativeScaling : this.props.PanelWidth(); }
     @computed get panelHeight() {
-        if (this.nativeHeight) {
+        if (this.effectiveNativeHeight) {
             return Math.min(this.props.PanelHeight(),
                 this.props.Document._fitWidth ?
-                    Math.max(NumCast(this.props.Document._height), NumCast(((this.props.Document.scrollHeight || 0) as number) * this.props.PanelWidth() / this.nativeWidth, this.props.PanelHeight())) :
-                    this.nativeHeight * this.nativeScaling
+                    Math.max(NumCast(this.props.Document._height), NumCast(((this.props.Document.scrollHeight || 0) as number) * this.props.PanelWidth() / this.effectiveNativeWidth, this.props.PanelHeight())) :
+                    this.effectiveNativeHeight * this.nativeScaling
             );
         }
         return this.props.PanelHeight();
     }
-    @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 Xshift() { return this.effectiveNativeWidth ? (this.props.PanelWidth() - this.effectiveNativeWidth * this.nativeScaling) / 2 : 0; }
+    @computed get Yshift() { return this.effectiveNativeWidth && this.effectiveNativeHeight && Math.abs(this.Xshift) < 0.001 ? (this.props.PanelHeight() - this.effectiveNativeHeight * this.nativeScaling) / 2 : 0; }
     @computed get centeringX() { return this.props.dontCenter?.includes("x") ? 0 : this.Xshift; }
-    @computed get centeringY() { return this.props.Document._fitWidth || this.props.dontCenter?.includes("y") ? 0 : this.YShift; }
+    @computed get centeringY() { return this.props.Document._fitWidth || this.props.dontCenter?.includes("y") ? 0 : this.Yshift; }
 
     toggleNativeDimensions = () => this.docView && Doc.toggleNativeDimensions(this.layoutDoc, this.docView.ContentScale, this.props.PanelWidth(), this.props.PanelHeight());
     contentsActive = () => this.docView?.contentsActive();
@@ -1067,8 +1077,8 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     docViewPathFunc = () => this.docViewPath;
     isSelected = (outsideReaction?: boolean) => SelectionManager.IsSelected(this, outsideReaction);
     select = (extendSelection: boolean) => SelectionManager.SelectView(this, !SelectionManager.Views().some(v => v.props.Document === this.props.ContainingCollectionDoc) && extendSelection);
-    NativeWidth = () => this.nativeWidth;
-    NativeHeight = () => this.nativeHeight;
+    NativeWidth = () => this.effectiveNativeWidth;
+    NativeHeight = () => this.effectiveNativeHeight;
     PanelWidth = () => this.panelWidth;
     PanelHeight = () => this.panelHeight;
     ContentScale = () => this.nativeScaling;
@@ -1093,31 +1103,32 @@ export class DocumentView extends React.Component<DocumentViewProps> {
 
     render() {
         TraceMobx();
-        const internalProps = {
-            ...this.props,
-            DocumentView: this.selfView,
-            viewPath: this.docViewPathFunc,
-            PanelWidth: this.PanelWidth,
-            PanelHeight: this.PanelHeight,
-            NativeWidth: this.NativeWidth,
-            NativeHeight: this.NativeHeight,
-            isSelected: this.isSelected,
-            select: this.select,
-            ContentScaling: this.ContentScale,
-            ScreenToLocalTransform: this.screenToLocalTransform,
-            focus: this.props.focus || emptyFunction,
-            bringToFront: emptyFunction,
-        };
+        const xshift = this.props.Document.isInkMask ? InkingStroke.MaskDim : Math.abs(this.Xshift) <= 0.001 ? this.props.PanelWidth() : undefined;
+        const yshift = this.props.Document.isInkMask ? InkingStroke.MaskDim : Math.abs(this.Yshift) <= 0.001 ? this.props.PanelHeight() : undefined;
         return (<div className="contentFittingDocumentView">
             {!this.props.Document || !this.props.PanelWidth() ? (null) : (
                 <div className="contentFittingDocumentView-previewDoc" ref={this.ContentRef}
                     style={{
                         position: this.props.Document.isInkMask ? "absolute" : undefined,
                         transform: `translate(${this.centeringX}px, ${this.centeringY}px)`,
-                        width: this.props.Document.isInkMask ? InkingStroke.MaskDim : Math.abs(this.Xshift) > 0.001 ? `${100 * (this.props.PanelWidth() - this.Xshift * 2) / this.props.PanelWidth()}%` : this.props.PanelWidth(),
-                        height: this.props.Document.isInkMask ? InkingStroke.MaskDim : 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(),
+                        width: xshift ?? `${100 * (this.props.PanelWidth() - this.Xshift * 2) / this.props.PanelWidth()}%`,
+                        height: yshift ?? this.props.Document._fitWidth ? `${this.panelHeight}px` :
+                            `${100 * this.effectiveNativeHeight / this.effectiveNativeWidth * this.props.PanelWidth() / this.props.PanelHeight()}%`,
                     }}>
-                    <DocumentViewInternal {...this.props} {...internalProps} ref={action((r: DocumentViewInternal | null) => this.docView = r)} />
+                    <DocumentViewInternal {...this.props}
+                        DocumentView={this.selfView}
+                        viewPath={this.docViewPathFunc}
+                        PanelWidth={this.PanelWidth}
+                        PanelHeight={this.PanelHeight}
+                        NativeWidth={this.NativeWidth}
+                        NativeHeight={this.NativeHeight}
+                        isSelected={this.isSelected}
+                        select={this.select}
+                        ContentScaling={this.ContentScale}
+                        ScreenToLocalTransform={this.screenToLocalTransform}
+                        focus={this.props.focus || emptyFunction}
+                        bringToFront={emptyFunction}
+                        ref={action((r: DocumentViewInternal | null) => this.docView = r)} />
                 </div>)}
         </div>);
     }
diff --git a/src/client/views/nodes/EquationBox.tsx b/src/client/views/nodes/EquationBox.tsx
index 7f9fc342a..5bc73d5d9 100644
--- a/src/client/views/nodes/EquationBox.tsx
+++ b/src/client/views/nodes/EquationBox.tsx
@@ -56,10 +56,13 @@ export class EquationBox extends ViewBoxBaseComponent<FieldViewProps, EquationDo
     }
     onChange = (str: string) => {
         this.dataDoc.text = str;
-        const _height = Number(getComputedStyle(this._ref.current!.element.current).height.replace("px", ""));
-        const _width = Number(getComputedStyle(this._ref.current!.element.current).width.replace("px", ""));
-        this.layoutDoc._width = Math.max(35, _width);
-        this.layoutDoc._height = Math.max(25, _height);
+        const style = this._ref.current && getComputedStyle(this._ref.current.element.current);
+        if (style) {
+            const _height = Number(style.height.replace("px", ""));
+            const _width = Number(style.width.replace("px", ""));
+            this.layoutDoc._width = Math.max(35, _width);
+            this.layoutDoc._height = Math.max(25, _height);
+        }
     }
     render() {
         TraceMobx();
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 589a6dd24..6afc2258a 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -482,7 +482,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
 
     playing = () => this._playing;
     isActiveChild = () => this._isChildActive;
-    timelineWhenActiveChanged = (isActive: boolean) => this.props.whenActiveChanged(runInAction(() => this._isChildActive = isActive));
+    timelineWhenActiveChanged = action((isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive));
     timelineScreenToLocal = () => this.props.ScreenToLocalTransform().scale(this.scaling()).translate(0, -this.heightPercent / 100 * this.props.PanelHeight());
     setAnchorTime = (time: number) => this.player!.currentTime = this.layoutDoc._currentTimecode = time;
     timelineHeight = () => this.props.PanelHeight() * (100 - this.heightPercent) / 100;
diff --git a/src/fields/Schema.ts b/src/fields/Schema.ts
index 4607e0fd5..78f8a6bfb 100644
--- a/src/fields/Schema.ts
+++ b/src/fields/Schema.ts
@@ -3,6 +3,7 @@ import { Doc, Field } from "./Doc";
 import { ObjectField } from "./ObjectField";
 import { RefField } from "./RefField";
 import { SelfProxy } from "./FieldSymbols";
+import { List } from "./List";
 
 type AllToInterface<T extends Interface[]> = {
     1: ToInterface<Head<T>> & AllToInterface<Tail<T>>,
@@ -67,9 +68,9 @@ export function makeInterface<T extends Interface[]>(...schemas: T): InterfaceFu
     return function (doc?: Doc | Doc[]) {
         if (doc instanceof Doc || doc === undefined) {
             return fn(doc || new Doc);
-        } else {
+        } else if (doc instanceof List) {
             return doc.map(fn);
-        }
+        } else return {};
     };
 }
 
diff --git a/src/fields/util.ts b/src/fields/util.ts
index 7955fc9fb..36c765dd0 100644
--- a/src/fields/util.ts
+++ b/src/fields/util.ts
@@ -289,7 +289,7 @@ export function setter(target: any, in_prop: string | symbol | number, value: an
         //     console.log(prop + " is deprecated - switch to _" + prop);
         //     prop = "_" + prop;
         // }
-        if (!prop.startsWith("__") && value !== undefined) prop = prop.substring(1);
+        if (!prop.startsWith("__")) prop = prop.substring(1);
         if (target.__LAYOUT__) {
             target.__LAYOUT__[prop] = value;
             return true;
-- 
cgit v1.2.3-70-g09d2

