From d182a3462a06ea58c4a0c937190aaa66eced0c01 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Sat, 24 Sep 2022 01:57:34 -0400
Subject: Fixed: treeView now doesn't get pointer events if it's not active. 
 fixed layout of treeview for pres box.  fixed horiz/vert scrolling for trees.
  fixed not adding Loading docs to recently closed.

---
 .../views/collections/CollectionTreeView.tsx       | 73 ++++++++++++----------
 1 file changed, 41 insertions(+), 32 deletions(-)

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

diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index dce792d19..fe5dc17f5 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -83,7 +83,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
         return this.doc === Doc.MyDashboards;
     }
 
-    @observable _explainerHeight = 0; // height of the description of the tree view
+    @observable _titleHeight = 0; // height of the title bar
 
     MainEle = () => this._mainEle;
 
@@ -111,7 +111,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
     computeHeight = () => {
         if (!this._isDisposing) {
             const titleHeight = !this._titleRef ? this.marginTop() : Number(getComputedStyle(this._titleRef).height.replace('px', ''));
-            const bodyHeight = Array.from(this.refList).reduce((p, r) => p + Number(getComputedStyle(r).height.replace('px', '')), this.marginBot());
+            const bodyHeight = Array.from(this.refList).reduce((p, r) => p + Number(getComputedStyle(r).height.replace('px', '')), this.marginBot()) + 6;
             this.layoutDoc._autoHeightMargins = bodyHeight;
             this.props.setHeight?.(bodyHeight + titleHeight);
         }
@@ -298,7 +298,11 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
     }
     @computed get titleBar() {
         return this.dataDoc === null ? null : (
-            <div className="collectionTreeView-titleBar" key={this.doc[Id]} style={!this.outlineMode ? { paddingLeft: this.marginX(), paddingTop: this.marginTop() } : {}} ref={r => (this._titleRef = r)}>
+            <div
+                className="collectionTreeView-titleBar"
+                ref={action((r: any) => (this._titleRef = r) && (this._titleHeight = r.getBoundingClientRect().height * this.props.ScreenToLocalTransform().Scale))}
+                key={this.doc[Id]}
+                style={!this.outlineMode ? { paddingLeft: this.marginX(), paddingTop: this.marginTop() } : {}}>
                 {this.outlineMode ? this.documentTitle : this.editableTitle}
             </div>
         );
@@ -378,40 +382,45 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
         const pointerEvents = () => (!this.props.isContentActive() && !SnappingManager.GetIsDragging() ? 'none' : undefined);
         const titleBar = this.props.treeViewHideTitle || this.doc.treeViewHideTitle ? null : this.titleBar;
         return [
-            <div
-                className="collectionTreeView-contents"
-                key="tree"
-                style={{
-                    ...(!titleBar ? { paddingLeft: this.marginX(), paddingTop: this.marginTop() } : {}),
-                    overflow: 'auto',
-                    height: '100%', //this.layoutDoc._autoHeight ? "max-content" : "100%"
-                }}>
-                {titleBar}
+            <div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
+                {!this.buttonMenu && !this.noviceExplainer ? null : (
+                    <div className="documentButtonMenu">
+                        {this.buttonMenu}
+                        {this.noviceExplainer}
+                    </div>
+                )}
                 <div
-                    className="collectionTreeView-container"
+                    className="collectionTreeView-contents"
+                    key="tree"
                     style={{
-                        transform: this.outlineMode ? `scale(${this.nativeDimScaling})` : '',
-                        paddingLeft: `${this.marginX()}px`,
-                        width: this.outlineMode ? `calc(${100 / this.nativeDimScaling}%)` : '',
-                    }}
-                    onContextMenu={this.onContextMenu}>
-                    {!this.buttonMenu && !this.noviceExplainer ? null : (
-                        <div className="documentButtonMenu" ref={action((r: HTMLDivElement) => r && (this._explainerHeight = r.getBoundingClientRect().height))}>
-                            {this.buttonMenu}
-                            {this.noviceExplainer}
-                        </div>
-                    )}
+                        ...(!titleBar ? { paddingLeft: this.marginX(), paddingTop: this.marginTop() } : {}),
+                        overflow: 'auto',
+                        width: '100%',
+                        height: '100%',
+                    }}>
+                    {titleBar}
                     <div
-                        className="collectionTreeView-dropTarget"
+                        className="collectionTreeView-container"
                         style={{
-                            background: background(),
-                            height: `calc(100% - ${this._explainerHeight}px)`,
-                            pointerEvents: pointerEvents(),
+                            transform: this.outlineMode ? `scale(${this.nativeDimScaling})` : '',
+                            paddingLeft: `${this.marginX()}px`,
+                            width: this.outlineMode ? `calc(${100 / this.nativeDimScaling}%)` : '',
+                            minHeight: `calc(100% - ${this._titleHeight}px)`,
                         }}
-                        onWheel={e => e.stopPropagation()}
-                        onDrop={this.onTreeDrop}
-                        ref={r => !this.doc.treeViewHasOverlay && r && this.createTreeDropTarget(r)}>
-                        <ul className={`no-indent${this.outlineMode ? '-outline' : ''}`}>{this.treeViewElements}</ul>
+                        onContextMenu={this.onContextMenu}>
+                        <div
+                            className="collectionTreeView-dropTarget"
+                            style={{
+                                background: background(),
+                                pointerEvents: pointerEvents(),
+                                height: `max-content`,
+                                minHeight: '100%',
+                            }}
+                            onWheel={e => e.stopPropagation()}
+                            onDrop={this.onTreeDrop}
+                            ref={r => !this.doc.treeViewHasOverlay && r && this.createTreeDropTarget(r)}>
+                            <ul className={`no-indent${this.outlineMode ? '-outline' : ''}`}>{this.treeViewElements}</ul>
+                        </div>
                     </div>
                 </div>
             </div>,
-- 
cgit v1.2.3-70-g09d2


From ba73479fe6c0594ebe37eed6cf295e5adc49c8e1 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 25 Oct 2022 11:10:12 -0400
Subject: various tweaks: show border highlights in tree views, uniform
 treatment of embedding using title bar, even for free form views, choose
 bestAlias when dragging from files menu,  text boxes honor document moves,
 show title for timeline annotations, fix dragoffset for stacks with
 buttons/description headers,

---
 src/Utils.ts                                       |   6 +-
 src/client/util/DocumentManager.ts                 |   4 +-
 src/client/util/DragManager.ts                     |  18 ++-
 src/client/views/DocumentDecorations.tsx           |   7 +-
 src/client/views/StyleProvider.tsx                 |  17 ++-
 src/client/views/collections/CollectionSubView.tsx |   7 +-
 .../views/collections/CollectionTreeView.tsx       |   7 +-
 src/client/views/collections/TreeView.tsx          |  19 +--
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  32 +++--
 src/client/views/nodes/DocumentView.tsx            | 136 ++++++++++-----------
 .../views/nodes/formattedText/FormattedTextBox.tsx |   3 +
 src/fields/Doc.ts                                  |   5 +
 12 files changed, 133 insertions(+), 128 deletions(-)

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

diff --git a/src/Utils.ts b/src/Utils.ts
index bf1f72774..5e0514bc6 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -728,10 +728,10 @@ export function getWordAtPoint(elem: any, x: number, y: number): string | undefi
     return undefined;
 }
 
-export function hasDescendantTarget(x: number, y: number, target: HTMLDivElement | null) {
+export function isTargetChildOf(ele: HTMLDivElement | null, target: Element | null) {
     let entered = false;
-    for (let child = document.elementFromPoint(x, y); !entered && child; child = child.parentElement) {
-        entered = entered || child === target;
+    for (let child = target; !entered && child; child = child.parentElement) {
+        entered = child === ele;
     }
     return entered;
 }
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 9a46d20de..b046d950f 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -335,9 +335,7 @@ export function DocFocusOrOpen(doc: Doc, collectionDoc?: Doc) {
     } else {
         const context = doc.context !== Doc.MyFilesystem && Cast(doc.context, Doc, null);
         const showDoc = context || doc;
-        const bestAlias = showDoc === Doc.GetProto(showDoc) ? DocListCast(showDoc.aliases).find(doc => !doc.context && doc.author === Doc.CurrentUserEmail) : showDoc;
-
-        CollectionDockingView.AddSplit(bestAlias ? bestAlias : Doc.MakeAlias(showDoc), 'right') && context && setTimeout(() => DocumentManager.Instance.getDocumentView(Doc.GetProto(doc))?.focus(doc, {}));
+        CollectionDockingView.AddSplit(Doc.BestAlias(showDoc), 'right') && context && setTimeout(() => DocumentManager.Instance.getDocumentView(Doc.GetProto(doc))?.focus(doc, {}));
     }
 }
 ScriptingGlobals.add(DocFocusOrOpen);
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 160aba294..899764866 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -206,7 +206,7 @@ export namespace DragManager {
                         !dragData.isDocDecorationMove && !dragData.userDropAction && ScriptCast(d.onDragStart)
                             ? addAudioTag(ScriptCast(d.onDragStart).script.run({ this: d }).result)
                             : docDragData.dropAction === 'alias'
-                            ? Doc.MakeAlias(d)
+                            ? Doc.BestAlias(d)
                             : docDragData.dropAction === 'proto'
                             ? Doc.GetProto(d)
                             : docDragData.dropAction === 'copy'
@@ -260,10 +260,6 @@ export namespace DragManager {
         StartDrag([ele], dragData, downX, downY, options);
     }
 
-    export function StartImgDrag(ele: HTMLElement, downX: number, downY: number) {
-        StartDrag([ele], {}, downX, downY);
-    }
-
     export function SetSnapLines(horizLines: number[], vertLines: number[]) {
         SnappingManager.setSnapLines(horizLines, vertLines);
     }
@@ -325,7 +321,7 @@ export namespace DragManager {
     export let DocDragData: DocumentDragData | undefined;
     export function StartDrag(eles: HTMLElement[], dragData: { [id: string]: any }, downX: number, downY: number, options?: DragOptions, finishDrag?: (dropData: DragCompleteEvent) => void) {
         if (dragData.dropAction === 'none') return;
-        DocDragData = dragData instanceof DocumentDragData ? dragData : undefined;
+        DocDragData = dragData as DocumentDragData;
         const batch = UndoManager.StartBatch('dragging');
         eles = eles.filter(e => e);
         CanEmbed = dragData.canEmbed || false;
@@ -357,15 +353,15 @@ export namespace DragManager {
         let rot = 0;
         const docsToDrag = dragData instanceof DocumentDragData ? dragData.draggedDocuments : dragData instanceof AnchorAnnoDragData ? [dragData.dragDocument] : [];
         const dragElements = eles.map(ele => {
-            let useDim = false;
+            // bcz: very hacky -- if dragged element is a freeForm view with a rotation, then extract the rotation in order to apply it to the dragged element
+            let useDim = false; // if doc is rotated by freeformview, then the dragged elements width and height won't reflect the unrotated dimensions, so we need to rely on the element knowing its own width/height.  \
+            // if the parent isn't a freeform view, then the element's width and height are presumed to match the acutal doc's dimensions (eg, dragging from import sidebar menu)
             if (ele?.parentElement?.parentElement?.parentElement?.className === 'collectionFreeFormDocumentView-container') {
                 ele = ele.parentElement.parentElement.parentElement;
-                const rotStr = ele.style.transform.replace(/.*rotate\(([-0-9.e]*)deg\).*/, '$1');
-                if (rotStr) rot = Number(rotStr);
+                rot = Number(ele.style.transform.replace(/.*rotate\(([-0-9.e]*)deg\).*/, '$1') || 0);
             } else {
                 useDim = true;
             }
-            if (rot < 0) rot += 360;
             if (!ele.parentNode) dragDiv.appendChild(ele);
             const dragElement = ele.parentNode === dragDiv ? ele : (ele.cloneNode(true) as HTMLElement);
             const children = Array.from(dragElement.children);
@@ -387,7 +383,7 @@ export namespace DragManager {
             const rect = ele.getBoundingClientRect();
             const w = ele.offsetWidth || rect.width;
             const h = ele.offsetHeight || rect.height;
-            const rotR = -(rot / 180) * Math.PI;
+            const rotR = -((rot < 0 ? rot + 360 : rot) / 180) * Math.PI;
             const tl = [0, 0];
             const tr = [Math.cos(rotR) * w, Math.sin(-rotR) * w];
             const bl = [Math.sin(rotR) * h, Math.cos(-rotR) * h];
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 6cf7df357..10517d829 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -177,6 +177,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
         );
         dragData.offset = dragDocView.props.ScreenToLocalTransform().transformDirection(e.x - left, e.y - top);
         dragData.moveDocument = dragDocView.props.moveDocument;
+        dragData.removeDocument = dragDocView.props.removeDocument;
         dragData.isDocDecorationMove = true;
         dragData.canEmbed = dragTitle;
         this._hidden = this.Interacting = true;
@@ -250,8 +251,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
         if (selectedDocs.length) {
             if (e.ctrlKey) {
                 // open an alias in a new tab with Ctrl Key
-                const bestAlias = DocListCast(selectedDocs[0].props.Document.aliases).find(doc => !doc.context && doc.author === Doc.CurrentUserEmail);
-                CollectionDockingView.AddSplit(bestAlias ?? Doc.MakeAlias(selectedDocs[0].props.Document), 'right');
+                CollectionDockingView.AddSplit(Doc.BestAlias(selectedDocs[0].props.Document), 'right');
             } else if (e.shiftKey) {
                 // open centered in a new workspace with Shift Key
                 const alias = Doc.MakeAlias(selectedDocs[0].props.Document);
@@ -766,6 +766,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
                 onBlur={e => !hideTitle && this.titleBlur()}
                 onChange={action(e => !hideTitle && (this._accumulatedTitle = e.target.value))}
                 onKeyDown={hideTitle ? emptyFunction : this.titleEntered}
+                onPointerDown={e => e.stopPropagation()}
             />
         ) : (
             <div className="documentDecorations-title" key="title" onPointerDown={this.onTitleDown}>
@@ -825,7 +826,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
                             <div className="documentDecorations-topbar" onPointerDown={this.onContainerDown}>
                                 {hideDeleteButton ? <div /> : topBtn('close', 'times', undefined, e => this.onCloseClick(true), 'Close')}
                                 {hideResizers || hideDeleteButton ? <div /> : topBtn('minimize', 'window-maximize', undefined, e => this.onCloseClick(undefined), 'Minimize')}
-                                {hideResizers ? <div /> : titleArea}
+                                {titleArea}
                                 {hideOpenButton ? <div /> : topBtn('open', 'external-link-alt', this.onMaximizeDown, undefined, 'Open in Lightbox (ctrl: as alias, shift: in new collection)')}
                             </div>
                             {hideResizers ? null : (
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index a5a886f42..2eb3dd532 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -3,8 +3,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, runInAction } from 'mobx';
 import { extname } from 'path';
 import { Doc, Opt } from '../../fields/Doc';
-import { BoolCast, Cast, ImageCast, NumCast, StrCast } from '../../fields/Types';
-import { DashColor, lightOrDark } from '../../Utils';
+import { BoolCast, Cast, DocCast, ImageCast, NumCast, StrCast } from '../../fields/Types';
+import { DashColor, emptyFunction, lightOrDark } from '../../Utils';
 import { CollectionViewType, DocumentType } from '../documents/DocumentTypes';
 import { DocFocusOrOpen } from '../util/DocumentManager';
 import { ColorScheme } from '../util/SettingsManager';
@@ -42,6 +42,7 @@ export enum StyleProp {
     FontSize = 'fontSize', // size of text font
     FontFamily = 'fontFamily', // font family of text
     FontWeight = 'fontWeight', // font weight of text
+    Highlighting = 'highlighting', // border highlighting
 }
 
 function darkScheme() {
@@ -107,6 +108,18 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
             if (doc?._viewType === CollectionViewType.Freeform) allSorts[TreeSort.Zindex] = { color: 'green', label: 'z' };
             allSorts[TreeSort.None] = { color: 'darkgray', label: '\u00A0\u00A0\u00A0' };
             return allSorts;
+        case StyleProp.Highlighting:
+            if (doc) {
+                const highlightIndex = Doc.isBrushedHighlightedDegree(doc);
+                const highlightColor = ['transparent', 'rgb(68, 118, 247)', 'rgb(68, 118, 247)', 'orange', 'lightBlue'][highlightIndex];
+                const highlightStyle = ['solid', 'dashed', 'solid', 'solid', 'solid'][highlightIndex];
+                const excludeTypes = !props?.treeViewDoc ? [DocumentType.FONTICON, DocumentType.INK] : [DocumentType.FONTICON];
+                let highlighting = !props?.disableDocBrushing && highlightIndex && !excludeTypes.includes(doc.type as any) && doc._viewType !== CollectionViewType.Linear; // bcz: hack to turn off highlighting onsidebar panel documents.  need to flag a document as not highlightable in a more direct way
+                if (highlighting && props?.focus !== emptyFunction && StrCast(doc.title) !== '[pres element template]') {
+                    return { highlightStyle, highlightColor, highlightIndex };
+                }
+            }
+            return undefined;
         case StyleProp.DocContents:
             return undefined;
         case StyleProp.WidgetColor:
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 30759b766..7bc273d7d 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -218,12 +218,7 @@ export function CollectionSubView<X>(moreProps?: X) {
                     const movedDocs = docDragData.droppedDocuments.filter((d, i) => docDragData.draggedDocuments[i] === d);
                     const addedDocs = docDragData.droppedDocuments.filter((d, i) => docDragData.draggedDocuments[i] !== d);
                     if (movedDocs.length) {
-                        const canAdd =
-                            this.props.Document._viewType === CollectionViewType.Pile ||
-                            de.embedKey ||
-                            !this.props.isAnnotationOverlay ||
-                            this.props.Document.allowOverlayDrop ||
-                            Doc.AreProtosEqual(Cast(movedDocs[0].annotationOn, Doc, null), this.props.Document);
+                        const canAdd = this.props.Document._viewType === CollectionViewType.Pile || de.embedKey || this.props.Document.allowOverlayDrop || Doc.AreProtosEqual(Cast(movedDocs[0].annotationOn, Doc, null), this.props.Document);
                         added = docDragData.moveDocument(movedDocs, this.props.Document, canAdd ? this.addDocument : returnFalse);
                     } else {
                         ScriptCast(this.props.Document.dropConverter)?.script.run({ dragData: docDragData });
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index fe5dc17f5..1169f692a 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -147,6 +147,8 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
         }
     };
 
+    screenToLocalTransform = () => this.props.ScreenToLocalTransform().translate(0, -this._headerHeight);
+
     @action
     remove = (doc: Doc | Doc[]): boolean => {
         const docs = doc instanceof Doc ? [doc] : doc;
@@ -275,7 +277,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
             dropAction,
             this.props.addDocTab,
             this.props.styleProvider,
-            this.props.ScreenToLocalTransform,
+            this.screenToLocalTransform,
             this.isContentActive,
             this.panelWidth,
             this.props.renderDepth,
@@ -377,6 +379,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
     moveAnnotationDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[], annotationKey?: string) => boolean) =>
         this.props.CollectionView?.moveDocument(doc, targetCollection, addDocument, `${this.props.fieldKey}-annotations`) || false;
 
+    @observable _headerHeight = 0;
     contentFunc = () => {
         const background = () => this.props.styleProvider?.(this.doc, this.props, StyleProp.BackgroundColor);
         const pointerEvents = () => (!this.props.isContentActive() && !SnappingManager.GetIsDragging() ? 'none' : undefined);
@@ -384,7 +387,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
         return [
             <div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
                 {!this.buttonMenu && !this.noviceExplainer ? null : (
-                    <div className="documentButtonMenu">
+                    <div className="documentButtonMenu" ref={action((r: HTMLDivElement | null) => r && (this._headerHeight = Number(getComputedStyle(r).height.replace(/px/, ''))))}>
                         {this.buttonMenu}
                         {this.noviceExplainer}
                     </div>
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 409b615f4..b9f86fa6b 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -10,11 +10,12 @@ import { listSpec } from '../../../fields/Schema';
 import { ComputedField, ScriptField } from '../../../fields/ScriptField';
 import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
 import { TraceMobx } from '../../../fields/util';
-import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnOne, returnTrue, simulateMouseClick, Utils } from '../../../Utils';
+import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, simulateMouseClick, Utils } from '../../../Utils';
 import { Docs, DocUtils } from '../../documents/Documents';
 import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
 import { DocumentManager } from '../../util/DocumentManager';
 import { DragManager, dropActionType } from '../../util/DragManager';
+import { ScriptingGlobals } from '../../util/ScriptingGlobals';
 import { SelectionManager } from '../../util/SelectionManager';
 import { SnappingManager } from '../../util/SnappingManager';
 import { Transform } from '../../util/Transform';
@@ -31,7 +32,6 @@ import { CollectionTreeView, TreeViewType } from './CollectionTreeView';
 import { CollectionView } from './CollectionView';
 import './TreeView.scss';
 import React = require('react');
-import { ScriptingGlobals } from '../../util/ScriptingGlobals';
 
 export interface TreeViewProps {
     treeView: CollectionTreeView;
@@ -792,12 +792,14 @@ export class TreeView extends React.Component<TreeViewProps> {
     titleStyleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, 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
 
+        // prettier-ignore
         switch (property.split(':')[0]) {
-            case StyleProp.Opacity:
-                return this.props.treeView.outlineMode ? undefined : 1;
-            case StyleProp.BackgroundColor:
-                return this.selected ? '#7089bb' : StrCast(doc._backgroundColor, StrCast(doc.backgroundColor));
+            case StyleProp.Opacity:         return this.props.treeView.outlineMode ? undefined : 1;
+            case StyleProp.BackgroundColor: return this.selected ? '#7089bb' : StrCast(doc._backgroundColor, StrCast(doc.backgroundColor));
+            case StyleProp.Highlighting:    if (this.props.treeView.outlineMode) return undefined;
             case StyleProp.DocContents:
+                const highlightIndex = this.props.treeView.outlineMode ? Doc.DocBrushStatus.unbrushed : Doc.isBrushedHighlightedDegree(doc);
+                const highlightColor = ['transparent', 'rgb(68, 118, 247)', 'rgb(68, 118, 247)', 'orange', 'lightBlue'][highlightIndex];
                 return this.props.treeView.outlineMode ? null : (
                     <div
                         className="treeView-label"
@@ -805,13 +807,13 @@ export class TreeView extends React.Component<TreeViewProps> {
                             // 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),
+                            outline: `solid ${highlightColor} ${highlightIndex}px`,
                         }}>
                         {StrCast(doc?.title)}
                     </div>
                 );
-            default:
-                return this.props?.treeView?.props.styleProvider?.(doc, props, property);
         }
+        return this.props?.treeView?.props.styleProvider?.(doc, props, property);
     };
     embeddedStyleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, property: string): any => {
         if (property.startsWith(StyleProp.Decorations)) return null;
@@ -1011,6 +1013,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                 pinToPres={this.props.treeView.props.pinToPres}
                 disableDocBrushing={this.props.treeView.props.disableDocBrushing}
                 bringToFront={returnFalse}
+                scriptContext={this}
             />
         );
     };
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 88422cbd4..eca95e1e0 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -113,7 +113,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     @observable _clusterSets: Doc[][] = [];
     @observable _deleteList: DocumentView[] = [];
     @observable _timelineRef = React.createRef<Timeline>();
-    @observable _marqueeRef = React.createRef<HTMLDivElement>();
+    @observable _marqueeRef: HTMLDivElement | null = null;
     @observable _marqueeViewRef = React.createRef<MarqueeView>();
     @observable ChildDrag: DocumentView | undefined; // child document view being dragged.  needed to update drop areas of groups when a group item is dragged.
     @observable _brushedView = { width: 0, height: 0, panX: 0, panY: 0, opacity: 0 }; // highlighted region of freeform canvas used by presentations to indicate a region
@@ -1011,22 +1011,22 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         switch (Doc.UserDoc().freeformScrollMode) {
             case freeformScrollMode.Pan:
                 // if shift is selected then zoom
-                if(e.ctrlKey) {
+                if (e.ctrlKey) {
                     if (!e.ctrlKey && this.props.Document.scrollHeight !== undefined) {
                         // things that can scroll vertically should do that instead of zooming
                     } else if (this.props.isContentActive(true) && !this.Document._isGroup) {
                         !this.props.isAnnotationOverlayScrollable && this.zoom(e.clientX, e.clientY, e.deltaY); // if (!this.props.isAnnotationOverlay) // bcz: do we want to zoom in on images/videos/etc?
                     }
-                // otherwise pan
+                    // otherwise pan
                 } else if (!e.ctrlKey && this.props.Document.scrollHeight !== undefined) {
                     // things that can scroll vertically should do that instead of zooming
                 } else if (this.props.isContentActive(true) && !this.Document._isGroup) {
                     const dx = e.deltaX;
                     const dy = e.deltaY;
                     if (e.shiftKey) {
-                        !this.props.isAnnotationOverlayScrollable && this.scrollPan({ deltaX: dy, deltaY: 0 }); 
+                        !this.props.isAnnotationOverlayScrollable && this.scrollPan({ deltaX: dy, deltaY: 0 });
                     } else {
-                        !this.props.isAnnotationOverlayScrollable && this.scrollPan({ deltaX: dx, deltaY: dy }); 
+                        !this.props.isAnnotationOverlayScrollable && this.scrollPan({ deltaX: dx, deltaY: dy });
                     }
                 }
                 break;
@@ -1548,9 +1548,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         setTimeout(
             action(() => {
                 this._firstRender = false;
-
-                this._marqueeRef.current?.addEventListener('dashDragAutoScroll', this.onDragAutoScroll as any);
-
                 this._disposers.groupBounds = reaction(
                     () => {
                         if (this.props.Document._isGroup && this.childDocs.length === this.childDocList?.length) {
@@ -1668,7 +1665,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
 
     componentWillUnmount() {
         Object.values(this._disposers).forEach(disposer => disposer?.());
-        this._marqueeRef.current?.removeEventListener('dashDragAutoScroll', this.onDragAutoScroll as any);
+        this._marqueeRef?.removeEventListener('dashDragAutoScroll', this.onDragAutoScroll as any);
     }
 
     @action
@@ -1681,10 +1678,10 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         if ((e as any).handlePan || this.props.isAnnotationOverlay) return;
         (e as any).handlePan = true;
 
-        if (!this.layoutDoc._noAutoscroll && !this.props.renderDepth && this._marqueeRef?.current) {
+        if (!this.layoutDoc._noAutoscroll && !this.props.renderDepth && this._marqueeRef) {
             const dragX = e.detail.clientX;
             const dragY = e.detail.clientY;
-            const bounds = this._marqueeRef.current?.getBoundingClientRect();
+            const bounds = this._marqueeRef?.getBoundingClientRect();
 
             const deltaX = dragX - bounds.left < 25 ? -(25 + (bounds.left - dragX)) : bounds.right - dragX < 25 ? 25 - (bounds.right - dragX) : 0;
             const deltaY = dragY - bounds.top < 25 ? -(25 + (bounds.top - dragY)) : bounds.bottom - dragY < 25 ? 25 - (bounds.bottom - dragY) : 0;
@@ -1842,10 +1839,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         DragManager.SetSnapLines(horizLines, vertLines);
     };
 
-    onPointerOver = (e: React.PointerEvent) => {
-        e.stopPropagation();
-    };
-
     incrementalRender = action(() => {
         if (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(this.props.docViewPath())) {
             const unrendered = this.childDocs.filter(doc => !this._renderCutoffData.get(doc[Id]));
@@ -1889,7 +1882,13 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                 getContainerTransform={this.getContainerTransform}
                 getTransform={this.getTransform}
                 isAnnotationOverlay={this.isAnnotationOverlay}>
-                <div className="marqueeView-div" ref={this._marqueeRef} style={{ opacity: this.props.dontRenderDocuments ? 0.7 : undefined }}>
+                <div
+                    className="marqueeView-div"
+                    ref={r => {
+                        this._marqueeRef = r;
+                        r?.addEventListener('dashDragAutoScroll', this.onDragAutoScroll as any);
+                    }}
+                    style={{ opacity: this.props.dontRenderDocuments ? 0.7 : undefined }}>
                     {this.layoutDoc._backgroundGridShow ? (
                         <div>
                             <CollectionFreeFormBackgroundGrid // bcz : UGHH  don't know why, but if we don't wrap in a div, then PDF's don't render whenn taking snapshot of a dashboard and the background grid is on!!?
@@ -1965,7 +1964,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
             <div
                 className={'collectionfreeformview-container'}
                 ref={this.createDashEventsTarget}
-                onPointerOver={this.onPointerOver}
                 onWheel={this.onPointerWheel}
                 onClick={this.onClick}
                 onPointerDown={this.onPointerDown}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index d3858c25e..fecbc2de2 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -15,7 +15,7 @@ import { BoolCast, Cast, ImageCast, NumCast, ScriptCast, StrCast } from '../../.
 import { AudioField } from '../../../fields/URLField';
 import { GetEffectiveAcl, SharingPermissions, TraceMobx } from '../../../fields/util';
 import { MobileInterface } from '../../../mobile/MobileInterface';
-import { emptyFunction, hasDescendantTarget, lightOrDark, OmitKeys, returnEmptyString, returnFalse, returnTrue, returnVal, simulateMouseClick, Utils } from '../../../Utils';
+import { emptyFunction, isTargetChildOf as isParentOf, lightOrDark, OmitKeys, returnEmptyString, returnFalse, returnTrue, returnVal, simulateMouseClick, Utils } from '../../../Utils';
 import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils';
 import { DocServer } from '../../DocServer';
 import { Docs, DocUtils } from '../../documents/Documents';
@@ -956,60 +956,58 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                 moreItems.push({ description: 'Close', event: this.deleteClicked, icon: 'times' });
             }
             !more && moreItems.length && cm.addItem({ description: 'More...', subitems: moreItems, icon: 'compass' });
-
-            const help = cm.findByDescription('Help...');
-            const helpItems: ContextMenuProps[] = help && 'subitems' in help ? help.subitems : [];
-            helpItems.push({ description: 'Show Metadata', event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), 'add:right'), icon: 'layer-group' });
-            !Doc.noviceMode && helpItems.push({ description: 'Text Shortcuts Ctrl+/', event: () => this.props.addDocTab(Docs.Create.PdfDocument('/assets/cheat-sheet.pdf', { _width: 300, _height: 300 }), 'add:right'), icon: 'keyboard' });
-            !Doc.noviceMode && helpItems.push({ description: 'Print Document in Console', event: () => console.log(this.props.Document), icon: 'hand-point-right' });
-            !Doc.noviceMode && helpItems.push({ description: 'Print DataDoc in Console', event: () => console.log(this.props.Document[DataSym]), icon: 'hand-point-right' });
-            
-            let documentationDescription: string | undefined = undefined;
-            let documentationLink: string | undefined = undefined;
-            console.log("type: ", this.props.Document.type);
-            switch(this.props.Document.type) {
-                case DocumentType.COL:
-                    documentationDescription = "See collection documentation";
-                    documentationLink = "https://brown-dash.github.io/Dash-Documentation/views/";
-                    break;
-                case DocumentType.PDF:
-                    documentationDescription = "See PDF node documentation";
-                    documentationLink = "https://brown-dash.github.io/Dash-Documentation/documents/pdf/";
-                    break;
-                case DocumentType.VID:
-                    documentationDescription = "See video node documentation";
-                    documentationLink = "https://brown-dash.github.io/Dash-Documentation/documents/tempMedia/video";
-                    break;
-                case DocumentType.AUDIO:
-                    documentationDescription = "See audio node documentation";
-                    documentationLink = "https://brown-dash.github.io/Dash-Documentation/documents/tempMedia/audio";
-                    break;
-                case DocumentType.WEB:
-                    documentationDescription = "See webpage node documentation";
-                    documentationLink = "https://brown-dash.github.io/Dash-Documentation/documents/webpage/";
-                    break;
-                case DocumentType.IMG:
-                    documentationDescription = "See image node documentation";
-                    documentationLink = "https://brown-dash.github.io/Dash-Documentation/documents/images/";
-                    break;
-                case DocumentType.RTF:
-                    documentationDescription = "See text node documentation";
-                    documentationLink = "https://brown-dash.github.io/Dash-Documentation/documents/text/";
-                    break;
-                default:
-                    break;
-            }
-
-            // Add link to help documentation
-            if (documentationDescription && documentationLink) {
-                console.log("add documentation item");
-                helpItems.push({ description: documentationDescription, event: () => {
+        }
+        const help = cm.findByDescription('Help...');
+        const helpItems: ContextMenuProps[] = help && 'subitems' in help ? help.subitems : [];
+        helpItems.push({ description: 'Show Metadata', event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), 'add:right'), icon: 'layer-group' });
+        !Doc.noviceMode && helpItems.push({ description: 'Text Shortcuts Ctrl+/', event: () => this.props.addDocTab(Docs.Create.PdfDocument('/assets/cheat-sheet.pdf', { _width: 300, _height: 300 }), 'add:right'), icon: 'keyboard' });
+        !Doc.noviceMode && helpItems.push({ description: 'Print Document in Console', event: () => console.log(this.props.Document), icon: 'hand-point-right' });
+        !Doc.noviceMode && helpItems.push({ description: 'Print DataDoc in Console', event: () => console.log(this.props.Document[DataSym]), icon: 'hand-point-right' });
+
+        let documentationDescription: string | undefined = undefined;
+        let documentationLink: string | undefined = undefined;
+        switch (this.props.Document.type) {
+            case DocumentType.COL:
+                documentationDescription = 'See collection documentation';
+                documentationLink = 'https://brown-dash.github.io/Dash-Documentation/views/';
+                break;
+            case DocumentType.PDF:
+                documentationDescription = 'See PDF node documentation';
+                documentationLink = 'https://brown-dash.github.io/Dash-Documentation/documents/pdf/';
+                break;
+            case DocumentType.VID:
+                documentationDescription = 'See video node documentation';
+                documentationLink = 'https://brown-dash.github.io/Dash-Documentation/documents/tempMedia/video';
+                break;
+            case DocumentType.AUDIO:
+                documentationDescription = 'See audio node documentation';
+                documentationLink = 'https://brown-dash.github.io/Dash-Documentation/documents/tempMedia/audio';
+                break;
+            case DocumentType.WEB:
+                documentationDescription = 'See webpage node documentation';
+                documentationLink = 'https://brown-dash.github.io/Dash-Documentation/documents/webpage/';
+                break;
+            case DocumentType.IMG:
+                documentationDescription = 'See image node documentation';
+                documentationLink = 'https://brown-dash.github.io/Dash-Documentation/documents/images/';
+                break;
+            case DocumentType.RTF:
+                documentationDescription = 'See text node documentation';
+                documentationLink = 'https://brown-dash.github.io/Dash-Documentation/documents/text/';
+                break;
+        }
+        // Add link to help documentation
+        if (documentationDescription && documentationLink) {
+            console.log('add documentation item');
+            helpItems.push({
+                description: documentationDescription,
+                event: () => {
                     window.open(documentationLink, '_blank');
-                }, icon: 'book' })
-            };
-
-            cm.addItem({ description: 'Help...', noexpand: true, subitems: helpItems, icon: 'question' });
+                },
+                icon: 'book',
+            });
         }
+        cm.addItem({ description: 'Help...', noexpand: true, subitems: helpItems, icon: 'question' });
 
         if (!this.topMost) e?.stopPropagation(); // DocumentViews should stop propagation of this event
         cm.displayMenu((e?.pageX || pageX || 0) - 15, (e?.pageY || pageY || 0) - 15);
@@ -1411,29 +1409,23 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
     };
     render() {
         TraceMobx();
-        const highlightIndex = this.props.LayoutTemplateString ? (Doc.IsHighlighted(this.props.Document) ? 6 : Doc.DocBrushStatus.unbrushed) : Doc.isBrushedHighlightedDegree(this.props.Document); // bcz: Argh!! need to identify a tree view doc better than a LayoutTemlatString
-        const highlightColor = ['transparent', 'rgb(68, 118, 247)', 'rgb(68, 118, 247)', 'orange', 'lightBlue'][highlightIndex];
-        const highlightStyle = ['solid', 'dashed', 'solid', 'solid', 'solid'][highlightIndex];
-        const excludeTypes = !this.props.treeViewDoc ? [DocumentType.FONTICON, DocumentType.INK] : [DocumentType.FONTICON];
-        let highlighting = !this.props.disableDocBrushing && highlightIndex && !excludeTypes.includes(this.layoutDoc.type as any) && this.layoutDoc._viewType !== CollectionViewType.Linear;
-        highlighting = highlighting && this.props.focus !== emptyFunction && this.layoutDoc.title !== '[pres element template]'; // bcz: hack to turn off highlighting onsidebar panel documents.  need to flag a document as not highlightable in a more direct way
-
+        const highlighting = this.props.styleProvider?.(this.props.Document, this.props, StyleProp.Highlighting);
         const borderPath = this.props.styleProvider?.(this.props.Document, this.props, StyleProp.BorderPath) || { path: undefined };
-        const boxShadow = this.props.treeViewDoc
-            ? null
-            : highlighting && this.borderRounding && highlightStyle !== 'dashed'
-            ? `0 0 0 ${highlightIndex}px ${highlightColor}`
-            : this.boxShadow || (this.props.Document.isTemplateForField ? 'black 0.2vw 0.2vw 0.8vw' : undefined);
+        const boxShadow =
+            this.props.treeViewDoc || !highlighting
+                ? null
+                : highlighting && this.borderRounding && highlighting.highlightStyle !== 'dashed'
+                ? `0 0 0 ${highlighting.highlightIndex}px ${highlighting.highlightColor}`
+                : this.boxShadow || (this.props.Document.isTemplateForField ? 'black 0.2vw 0.2vw 0.8vw' : undefined);
         const renderDoc = this.renderDoc({
             borderRadius: this.borderRounding,
-            outline: highlighting && !this.borderRounding ? `${highlightColor} ${highlightStyle} ${highlightIndex}px` : 'solid 0px',
-            border: highlighting && this.borderRounding && highlightStyle === 'dashed' ? `${highlightStyle} ${highlightColor} ${highlightIndex}px` : undefined,
+            outline: highlighting && !this.borderRounding && highlighting ? `${highlighting.highlightColor} ${highlighting.highlightStyle} ${highlighting.highlightIndex}px` : 'solid 0px',
+            border: highlighting && this.borderRounding && highlighting && highlighting.highlightStyle === 'dashed' ? `${highlighting.highlightStyle} ${highlighting.highlightColor} ${highlighting.highlightIndex}px` : undefined,
             boxShadow,
             clipPath: borderPath.path ? `path('${borderPath.path}')` : undefined,
         });
 
         const animRenderDoc = PresBox.Instance?.isActiveItemTarget(this.layoutDoc) ? PresBox.AnimationEffect(renderDoc, PresBox.Instance.activeItem) : renderDoc;
-        // Return surrounding highlight
         return (
             <div
                 className={`${DocumentView.ROOT_DIV} docView-hack`}
@@ -1442,8 +1434,9 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                 onKeyDown={this.onKeyDown}
                 onPointerDown={this.onPointerDown}
                 onClick={this.onClick}
-                onPointerEnter={action(e => !SnappingManager.GetIsDragging() && Doc.BrushDoc(this.props.Document))}
-                onPointerLeave={action(e => !hasDescendantTarget(e.nativeEvent.x, e.nativeEvent.y, this.ContentDiv) && Doc.UnBrushDoc(this.props.Document))}
+                onPointerEnter={e => (!SnappingManager.GetIsDragging() || DragManager.CanEmbed) && Doc.BrushDoc(this.props.Document)}
+                onPointerOver={e => (!SnappingManager.GetIsDragging() || DragManager.CanEmbed) && Doc.BrushDoc(this.props.Document)}
+                onPointerLeave={e => !isParentOf(this.ContentDiv, document.elementFromPoint(e.nativeEvent.x, e.nativeEvent.y)) && Doc.UnBrushDoc(this.props.Document)}
                 style={{
                     display: this.hidden ? 'inline' : undefined,
                     borderRadius: this.borderRounding,
@@ -1453,9 +1446,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                     animRenderDoc
                 ) : (
                     <>
-                        {/* <div style={{ clipPath: `path('${borderPath.fill}')` }}>
-                        {animRenderDoc}
-                    </div> */}
                         {animRenderDoc}
                         <div key="border2" className="documentView-customBorder" style={{ pointerEvents: 'none' }}>
                             <svg style={{ overflow: 'visible' }} viewBox={`0 0 ${this.props.PanelWidth()} ${this.props.PanelHeight()}`}>
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index a94e2c96d..f5d00c2b8 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -538,6 +538,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
                     docid: target[Id],
                     float: 'unset',
                 });
+                if (!['alias', 'copy'].includes((dragData.dropAction ?? '') as any)) {
+                    dragData.removeDocument?.(dragData.draggedDocuments[0]);
+                }
                 const view = this._editorView!;
                 view.dispatch(view.state.tr.insert(view.posAtCoords({ left: de.x, top: de.y })!.pos, node));
                 e.stopPropagation();
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 0ceaff968..460dd6081 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -680,6 +680,11 @@ export namespace Doc {
         return alias;
     }
 
+    export function BestAlias(doc: Doc) {
+        const bestAlias = Doc.GetProto(doc) ? DocListCast(doc.aliases).find(doc => !doc.context && doc.author === Doc.CurrentUserEmail) : doc;
+        return bestAlias ?? Doc.MakeAlias(doc);
+    }
+
     export async function makeClone(doc: Doc, cloneMap: Map<string, Doc>, linkMap: Map<Doc, Doc>, rtfs: { copy: Doc; key: string; field: RichTextField }[], exclusions: string[], dontCreate: boolean, asBranch: boolean): Promise<Doc> {
         if (Doc.IsBaseProto(doc)) return doc;
         if (cloneMap.get(doc[Id])) return cloneMap.get(doc[Id])!;
-- 
cgit v1.2.3-70-g09d2


From 2fc88a931cb2fc3408297b000208990633445585 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 27 Oct 2022 15:57:09 -0400
Subject: cleaned up treeViews to work across PresBox/ppt slides/collections/ -
 modified DocumentView rendering to remove pres box refs.  fixed mainView
 width.

---
 src/client/documents/Documents.ts                  |   4 +-
 src/client/util/CurrentUserUtils.ts                |   8 +-
 src/client/views/DocumentDecorations.tsx           |  18 +-
 src/client/views/LightboxView.tsx                  |  26 +--
 src/client/views/MainView.tsx                      |   1 +
 src/client/views/StyleProvider.tsx                 |   5 +-
 .../views/collections/CollectionStackingView.tsx   |   2 +
 .../views/collections/CollectionTreeView.scss      |   2 -
 .../views/collections/CollectionTreeView.tsx       |  62 ++++---
 src/client/views/collections/CollectionView.tsx    |   2 +
 src/client/views/collections/TabDocView.tsx        |   1 -
 src/client/views/collections/TreeView.scss         |   3 +-
 src/client/views/collections/TreeView.tsx          | 179 +++++++++----------
 .../collectionFreeForm/CollectionFreeFormView.tsx  |   2 +-
 .../views/nodes/CollectionFreeFormDocumentView.tsx |   6 +-
 src/client/views/nodes/DocumentView.tsx            |  37 ++--
 src/client/views/nodes/FieldView.tsx               |   2 -
 src/client/views/nodes/VideoBox.tsx                |   2 +-
 .../views/nodes/formattedText/FormattedTextBox.tsx |   8 +-
 src/client/views/nodes/trails/PresBox.tsx          |   7 +-
 src/client/views/nodes/trails/PresElementBox.scss  |  14 +-
 src/client/views/nodes/trails/PresElementBox.tsx   | 197 ++++++++++++---------
 src/fields/Doc.ts                                  |   3 +
 23 files changed, 301 insertions(+), 290 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 2d82ffdf9..bbb896d6e 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -335,7 +335,6 @@ export class DocumentOptions {
     treeViewHideHeaderIfTemplate?: boolean; // whether to hide the header for a document in a tree view only if a childLayoutTemplate is provided (presBox)
     treeViewHideHeader?: boolean; // whether to hide the header for a document in a tree view
     treeViewHideHeaderFields?: boolean; // whether to hide the drop down options for tree view items.
-    treeViewGrowsHorizontally?: boolean; // whether an embedded tree view of the document can grow horizontally without growing vertically
     treeViewChildDoubleClick?: ScriptField; //
     // Action Button
     buttonMenu?: boolean; // whether a action button should be displayed
@@ -395,7 +394,6 @@ export namespace Docs {
                         _xMargin: 10,
                         _yMargin: 10,
                         nativeDimModifiable: true,
-                        treeViewGrowsHorizontally: true,
                         nativeHeightUnfrozen: true,
                         forceReflow: true,
                         links: '@links(self)',
@@ -570,7 +568,7 @@ export namespace Docs {
                 DocumentType.SLIDER,
                 {
                     layout: { view: SliderBox, dataField: defaultDataKey },
-                    options: { links: '@links(self)', treeViewGrowsHorizontally: true },
+                    options: { links: '@links(self)' },
                 },
             ],
             [
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 2bc464127..a2974177e 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -480,7 +480,7 @@ export class CurrentUserUtils {
         const childContextMenuIcons = ["chalkboard", "tv", "camera", "users", "times", "trash"]; // entries must be kept in synch with childContextMenuScripts, childContextMenuLabels, and childContextMenuFilters
         const reqdOpts:DocumentOptions = {
             title: "My Dashboards", childHideLinkButton: true, freezeChildren: "remove|add", treeViewHideTitle: true, boxShadow: "0 0", childDontRegisterViews: true,
-            targetDropAction: "same", treeViewType: TreeViewType.fileSystem, isFolder: true, system: true,  treeViewTruncateTitleWidth: 150, ignoreClick: true, 
+            targetDropAction: "same", treeViewType: TreeViewType.fileSystem, isFolder: true, system: true,  treeViewTruncateTitleWidth: 350, ignoreClick: true, 
             buttonMenu: true, buttonMenuDoc: newDashboardButton, childDropAction: "alias",
             _showTitle: "title", _height: 400, _gridGap: 5, _forceActive: true, _lockedPosition: true,
             contextMenuLabels:new List<string>(contextMenuLabels),
@@ -518,7 +518,7 @@ export class CurrentUserUtils {
         const reqdOpts:DocumentOptions = { _showTitle: "title", _height: 100, _gridGap: 5, _forceActive: true, _lockedPosition: true, 
             title: "My Documents", buttonMenu: true, buttonMenuDoc: newFolderButton, treeViewHideTitle: true, targetDropAction: "proto", system: true,
             isFolder: true, treeViewType: TreeViewType.fileSystem, childHideLinkButton: true, boxShadow: "0 0", childDontRegisterViews: true, 
-            treeViewTruncateTitleWidth: 150, ignoreClick: true, childDropAction: "alias",
+            treeViewTruncateTitleWidth: 350, ignoreClick: true, childDropAction: "alias",
             childContextMenuLabels: new List<string>(["Create new folder"]),
             childContextMenuIcons: new List<string>(["plus"]),
             explainer: "This is your file manager where you can create folders to keep track of documents independently of your dashboard."
@@ -535,7 +535,7 @@ export class CurrentUserUtils {
     static setupRecentlyClosed(doc: Doc, field:string) {
         const reqdOpts:DocumentOptions = { _showTitle: "title", _lockedPosition: true, _gridGap: 5, _forceActive: true, 
             title: "My Recently Closed", buttonMenu: true, childHideLinkButton: true, treeViewHideTitle: true, childDropAction: "alias", system: true,
-            treeViewTruncateTitleWidth: 150, ignoreClick: true,  boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same",
+            treeViewTruncateTitleWidth: 350, ignoreClick: true,  boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same",
             contextMenuLabels: new List<string>(["Empty recently closed"]),
             contextMenuIcons:new List<string>(["trash"]),
             explainer: "Recently closed documents appear in this menu. They will only be deleted if you explicity empty this list."
@@ -561,7 +561,7 @@ export class CurrentUserUtils {
         const reqdOpts:DocumentOptions = {
             _lockedPosition: true, _gridGap: 5, _forceActive: true, title: Doc.CurrentUserEmail +"-view",
             boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", ignoreClick: true, system: true,
-            treeViewHideTitle: true, treeViewTruncateTitleWidth: 150
+            treeViewHideTitle: true, treeViewTruncateTitleWidth: 350
         };
         if (!doc[field]) DocUtils.AssignOpts(doc, {treeViewOpen: true, treeViewExpandedView: "fields" });
         return DocUtils.AssignDocField(doc, field, (opts, items) => Docs.Create.TreeDocument(items??[], opts), reqdOpts, [doc]);
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 10517d829..06eb6c6d7 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -112,7 +112,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
                             }
                         }
                         //@ts-ignore
-                        const titleField = +this._accumulatedTitle === this._accumulatedTitle ? +this._accumulatedTitle : this._accumulatedTitle;
+                        const titleField = +this._accumulatedTitle == this._accumulatedTitle ? +this._accumulatedTitle : this._accumulatedTitle;
                         Doc.SetInPlace(d.rootDoc, titleFieldKey, titleField, true);
 
                         if (d.rootDoc.syncLayoutFieldWithTitle) {
@@ -345,7 +345,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
     setRotateCenter = (seldocview: DocumentView, rotCenter: number[]) => {
         const newloccentern = seldocview.props.ScreenToLocalTransform().transformPoint(rotCenter[0], rotCenter[1]);
         const newlocenter = [newloccentern[0] - NumCast(seldocview.layoutDoc._width) / 2, newloccentern[1] - NumCast(seldocview.layoutDoc._height) / 2];
-        const final = Utils.rotPt(newlocenter[0], newlocenter[1], -(NumCast(seldocview.rootDoc._jitterRotation) / 180) * Math.PI);
+        const final = Utils.rotPt(newlocenter[0], newlocenter[1], -(NumCast(seldocview.rootDoc._rotation) / 180) * Math.PI);
         seldocview.rootDoc.rotateCenterX = final.x / NumCast(seldocview.layoutDoc._width);
         seldocview.rootDoc.rotateCenterY = final.y / NumCast(seldocview.layoutDoc._height);
     };
@@ -381,7 +381,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
         const infos = new Map<Doc, { unrotatedDocPos: { x: number; y: number }; startRotCtr: { x: number; y: number }; accumRot: number }>();
         const seldocview = SelectionManager.Views()[0];
         SelectionManager.Views().forEach(dv => {
-            const accumRot = (NumCast(dv.rootDoc._jitterRotation) / 180) * Math.PI;
+            const accumRot = (NumCast(dv.rootDoc._rotation) / 180) * Math.PI;
             const localRotCtr = dv.props.ScreenToLocalTransform().transformPoint(rcScreen.X, rcScreen.Y);
             const localRotCtrOffset = [localRotCtr[0] - NumCast(dv.rootDoc.width) / 2, localRotCtr[1] - NumCast(dv.rootDoc.height) / 2];
             const startRotCtr = Utils.rotPt(localRotCtrOffset[0], localRotCtrOffset[1], -accumRot);
@@ -396,7 +396,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
                     infos.set(dv.rootDoc, { unrotatedDocPos, startRotCtr, accumRot: isAbs ? angle : accumRot + angle });
                     dv.rootDoc.x = infos.get(dv.rootDoc)!.unrotatedDocPos.x - (endRotCtr.x - startRotCtr.x);
                     dv.rootDoc.y = infos.get(dv.rootDoc)!.unrotatedDocPos.y - (endRotCtr.y - startRotCtr.y);
-                    dv.rootDoc._jitterRotation = ((isAbs ? 0 : NumCast(dv.rootDoc._jitterRotation)) + (angle * 180) / Math.PI) % 360; // Rotation between -360 and 360
+                    dv.rootDoc._rotation = ((isAbs ? 0 : NumCast(dv.rootDoc._rotation)) + (angle * 180) / Math.PI) % 360; // Rotation between -360 and 360
                 })
             );
         };
@@ -416,7 +416,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
                 return false;
             }, // moveEvent
             action(() => {
-                const oldRotation = NumCast(seldocview.rootDoc._jitterRotation);
+                const oldRotation = NumCast(seldocview.rootDoc._rotation);
                 const diff = oldRotation - Math.round(oldRotation / 45) * 45;
                 if (Math.abs(diff) < 5) {
                     if (selectedInk.length) {
@@ -611,7 +611,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
                         }
                     } else {
                         const rotCtr = [NumCast(doc._width) / 2, NumCast(doc._height) / 2];
-                        const tlRotated = Utils.rotPt(-rotCtr[0], -rotCtr[1], (NumCast(doc._jitterRotation) / 180) * Math.PI);
+                        const tlRotated = Utils.rotPt(-rotCtr[0], -rotCtr[1], (NumCast(doc._rotation) / 180) * Math.PI);
 
                         const maxHeight = doc.nativHeightUnfrozen || !nheight ? 0 : Math.max(nheight, NumCast(doc.scrollHeight, NumCast(doc[docView.LayoutFieldKey + '-scrollHeight']))) * docView.NativeDimScaling();
                         dH && (doc._height = actualdH > maxHeight && maxHeight ? maxHeight : actualdH);
@@ -619,7 +619,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
                         dH && (doc._autoHeight = false);
 
                         const rotCtr2 = [NumCast(doc._width) / 2, NumCast(doc._height) / 2];
-                        const tlRotated2 = Utils.rotPt(-rotCtr2[0], -rotCtr2[1], (NumCast(doc._jitterRotation) / 180) * Math.PI);
+                        const tlRotated2 = Utils.rotPt(-rotCtr2[0], -rotCtr2[1], (NumCast(doc._rotation) / 180) * Math.PI);
                         doc.x = NumCast(doc.x) + tlRotated.x + rotCtr[0] - (tlRotated2.x + rotCtr2[0]); // doc shifts by amount topleft moves because rotation is about center of doc
                         doc.y = NumCast(doc.y) + tlRotated.y + rotCtr[1] - (tlRotated2.y + rotCtr2[1]);
                     }
@@ -695,7 +695,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
             const loccenter = Utils.rotPt(
                 NumCast(seldocview.rootDoc.rotateCenterX) * NumCast(seldocview.layoutDoc._width),
                 NumCast(seldocview.rootDoc.rotateCenterY) * NumCast(seldocview.layoutDoc._height),
-                (NumCast(seldocview.rootDoc._jitterRotation) / 180) * Math.PI
+                (NumCast(seldocview.rootDoc._rotation) / 180) * Math.PI
             );
             return seldocview.props
                 .ScreenToLocalTransform()
@@ -783,7 +783,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
         bounds.b = Math.max(bounds.y, Math.max(topBounds, Math.min(window.innerHeight, bounds.b + this._resizeBorderWidth / 2 + this._linkBoxHeight) - this._resizeBorderWidth / 2 - this._linkBoxHeight));
 
         const useRotation = seldocview.rootDoc.type !== DocumentType.EQUATION; // when do we want an object to not rotate?
-        const rotation = NumCast(seldocview.rootDoc._jitterRotation);
+        const rotation = NumCast(seldocview.rootDoc._rotation);
 
         const resizerScheme = colorScheme ? 'documentDecorations-resizer' + colorScheme : '';
 
diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx
index bd6cea28a..22b0380a2 100644
--- a/src/client/views/LightboxView.tsx
+++ b/src/client/views/LightboxView.tsx
@@ -289,29 +289,29 @@ export class LightboxView extends React.Component<LightboxViewProps> {
                             })}
                             Document={LightboxView.LightboxDoc}
                             DataDoc={undefined}
+                            PanelWidth={this.lightboxWidth}
+                            PanelHeight={this.lightboxHeight}
                             LayoutTemplate={LightboxView.LightboxDocTemplate}
-                            addDocument={undefined}
                             isDocumentActive={returnFalse}
                             isContentActive={returnTrue}
-                            addDocTab={this.addDocTab}
-                            pinToPres={TabDocView.PinDoc}
-                            onBrowseClick={MainView.Instance.exploreMode}
+                            styleProvider={DefaultStyleProvider}
+                            ScreenToLocalTransform={this.lightboxScreenToLocal}
+                            renderDepth={0}
                             rootSelected={returnTrue}
                             docViewPath={returnEmptyDoclist}
                             docFilters={this.docFilters}
-                            removeDocument={undefined}
-                            styleProvider={DefaultStyleProvider}
-                            ScreenToLocalTransform={this.lightboxScreenToLocal}
-                            PanelWidth={this.lightboxWidth}
-                            PanelHeight={this.lightboxHeight}
-                            focus={DocUtils.DefaultFocus}
-                            whenChildContentsActiveChanged={emptyFunction}
-                            bringToFront={emptyFunction}
                             docRangeFilters={returnEmptyFilter}
                             searchFilterDocs={returnEmptyDoclist}
                             ContainingCollectionView={undefined}
                             ContainingCollectionDoc={undefined}
-                            renderDepth={0}
+                            addDocument={undefined}
+                            removeDocument={undefined}
+                            whenChildContentsActiveChanged={emptyFunction}
+                            addDocTab={this.addDocTab}
+                            pinToPres={TabDocView.PinDoc}
+                            bringToFront={emptyFunction}
+                            onBrowseClick={MainView.Instance.exploreMode}
+                            focus={DocUtils.DefaultFocus}
                         />
                     </GestureOverlay>
                 </div>
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 03c0642ed..4dc1ebd99 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -647,6 +647,7 @@ export class MainView extends React.Component {
                         e.preventDefault();
                     }}
                     style={{
+                        width: `calc(100% - ${this._leftMenuFlyoutWidth + this.leftMenuWidth() + this.propertiesWidth()}px)`,
                         minWidth: `calc(100% - ${this._leftMenuFlyoutWidth + this.leftMenuWidth() + this.propertiesWidth()}px)`,
                         transform: LightboxView.LightboxDoc ? 'scale(0.0001)' : undefined,
                     }}>
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 2eb3dd532..bc8bd7b7f 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -85,7 +85,6 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
     const isAnnotated = property.includes(':annotated');
     const isOpen = property.includes(':open');
     const fieldKey = props?.fieldKey ? props.fieldKey + '-' : isCaption ? 'caption-' : '';
-    const comicStyle = () => doc && !Doc.IsSystem(doc) && Doc.UserDoc().renderStyle === 'comic';
     const isBackground = () => doc && BoolCast(doc._lockedPosition);
     const backgroundCol = () => props?.styleProvider?.(doc, props, StyleProp.BackgroundColor);
     const opacity = () => props?.styleProvider?.(doc, props, StyleProp.Opacity);
@@ -167,11 +166,11 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
         case StyleProp.TitleHeight:
             return 15;
         case StyleProp.BorderPath:
-            return comicStyle() && props?.renderDepth && doc?.type !== DocumentType.INK
+            return Doc.IsComicStyle(doc) && props?.renderDepth && doc?.type !== DocumentType.INK
                 ? { path: wavyBorderPath(props?.PanelWidth?.() || 0, props?.PanelHeight?.() || 0), fill: wavyBorderPath(props?.PanelWidth?.() || 0, props?.PanelHeight?.() || 0, 0.08), width: 3 }
                 : { path: undefined, width: 0 };
         case StyleProp.JitterRotation:
-            return comicStyle() ? random(-1, 1, NumCast(doc?.x), NumCast(doc?.y)) * ((props?.PanelWidth() || 0) > (props?.PanelHeight() || 0) ? 5 : 10) : 0;
+            return Doc.IsComicStyle(doc) ? random(-1, 1, NumCast(doc?.x), NumCast(doc?.y)) * ((props?.PanelWidth() || 0) > (props?.PanelHeight() || 0) ? 5 : 10) : 0;
         case StyleProp.HeaderMargin:
             return ([CollectionViewType.Stacking, CollectionViewType.NoteTaking, CollectionViewType.Masonry, CollectionViewType.Tree].includes(doc?._viewType as any) ||
                 (doc?.type === DocumentType.RTF && !showTitle()?.includes('noMargin')) ||
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index ba29b1d6f..77b47ed82 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -350,6 +350,8 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
                 searchFilterDocs={this.searchFilterDocs}
                 ContainingCollectionDoc={this.props.CollectionView?.props.Document}
                 ContainingCollectionView={this.props.CollectionView}
+                xPadding={NumCast(this.layoutDoc._childXPadding, this.props.childXPadding)}
+                yPadding={NumCast(this.layoutDoc._childYPadding, this.props.childYPadding)}
                 addDocument={this.props.addDocument}
                 moveDocument={this.props.moveDocument}
                 removeDocument={this.props.removeDocument}
diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss
index 1aef29b2f..3785b7d61 100644
--- a/src/client/views/collections/CollectionTreeView.scss
+++ b/src/client/views/collections/CollectionTreeView.scss
@@ -13,8 +13,6 @@
     width: 100%;
     position: relative;
     top: 0;
-    padding-left: 10px;
-    padding-right: 10px;
     background: $light-gray;
     font-size: 13px;
     overflow: auto;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 1169f692a..0ff89c5a7 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -58,7 +58,6 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
     private _isDisposing = false; // notes that instance is in process of being disposed
     private refList: Set<any> = new Set(); // list of tree view items to monitor for height changes
     private observer: any; // observer for monitoring tree view items.
-    private static expandViewLabelSize = 20;
 
     @computed get doc() {
         return this.props.Document;
@@ -100,7 +99,10 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
         Object.values(this._disposers).forEach(disposer => disposer?.());
     }
 
+    shrinkWrap = () => {}; // placeholder to allow setContentView to work
+
     componentDidMount() {
+        //this.props.setContentView?.(this);
         this._disposers.autoheight = reaction(
             () => this.rootDoc.autoHeight,
             auto => auto && this.computeHeight(),
@@ -197,9 +199,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
     onTreeDrop = (e: React.DragEvent, addDocs?: (docs: Doc[]) => void) => this.onExternalDrop(e, {}, addDocs);
 
     @undoBatch
-    makeTextCollection = (childDocs: Doc[]) => {
-        this.addDoc(TreeView.makeTextBullet(), childDocs.length ? childDocs[0] : undefined, true);
-    };
+    makeTextCollection = (childDocs: Doc[]) => this.addDoc(TreeView.makeTextBullet(), childDocs.length ? childDocs[0] : undefined, true);
 
     get editableTitle() {
         return (
@@ -258,6 +258,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
         const icons = StrListCast(this.doc.childContextMenuIcons);
         return StrListCast(this.doc.childContextMenuLabels).map((label, i) => ({ script: customScripts[i], filter: customFilters[i], icon: icons[i], label }));
     };
+    headerFields = () => this.props.treeViewHideHeaderFields || BoolCast(this.doc.treeViewHideHeaderFields);
     @computed get treeViewElements() {
         TraceMobx();
         const dropAction = StrCast(this.doc.childDropAction) as dropActionType;
@@ -281,7 +282,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
             this.isContentActive,
             this.panelWidth,
             this.props.renderDepth,
-            () => this.props.treeViewHideHeaderFields || BoolCast(this.doc.treeViewHideHeaderFields),
+            this.headerFields,
             [],
             this.props.onCheckedClick,
             this.onChildClick,
@@ -304,7 +305,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
                 className="collectionTreeView-titleBar"
                 ref={action((r: any) => (this._titleRef = r) && (this._titleHeight = r.getBoundingClientRect().height * this.props.ScreenToLocalTransform().Scale))}
                 key={this.doc[Id]}
-                style={!this.outlineMode ? { paddingLeft: this.marginX(), paddingTop: this.marginTop() } : {}}>
+                style={!this.outlineMode ? { marginLeft: this.marginX(), paddingTop: this.marginTop() } : {}}>
                 {this.outlineMode ? this.documentTitle : this.editableTitle}
             </div>
         );
@@ -372,7 +373,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
     documentTitleHeight = () => (this.layoutDoc?.[HeightSym]() || 0) - NumCast(this.layoutDoc.autoHeightMargins);
     truncateTitleWidth = () => this.treeViewtruncateTitleWidth;
     onChildClick = () => this.props.onChildClick?.() || ScriptCast(this.doc.onChildClick);
-    panelWidth = () => Math.max(0, this.props.PanelWidth() - this.marginX() - CollectionTreeView.expandViewLabelSize) * (this.props.NativeDimScaling?.() || 1);
+    panelWidth = () => Math.max(0, this.props.PanelWidth() - 2 * this.marginX() * (this.props.NativeDimScaling?.() || 1));
 
     addAnnotationDocument = (doc: Doc | Doc[]) => this.props.CollectionView?.addDocument(doc, `${this.props.fieldKey}-annotations`) || false;
     remAnnotationDocument = (doc: Doc | Doc[]) => this.props.CollectionView?.removeDocument(doc, `${this.props.fieldKey}-annotations`) || false;
@@ -396,7 +397,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
                     className="collectionTreeView-contents"
                     key="tree"
                     style={{
-                        ...(!titleBar ? { paddingLeft: this.marginX(), paddingTop: this.marginTop() } : {}),
+                        ...(!titleBar ? { marginLeft: this.marginX(), paddingTop: this.marginTop() } : {}),
                         overflow: 'auto',
                         width: '100%',
                         height: '100%',
@@ -405,9 +406,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
                     <div
                         className="collectionTreeView-container"
                         style={{
-                            transform: this.outlineMode ? `scale(${this.nativeDimScaling})` : '',
-                            paddingLeft: `${this.marginX()}px`,
-                            width: this.outlineMode ? `calc(${100 / this.nativeDimScaling}%)` : '',
+                            marginLeft: `${this.marginX()}px`,
                             minHeight: `calc(100% - ${this._titleHeight}px)`,
                         }}
                         onContextMenu={this.onContextMenu}>
@@ -432,24 +431,29 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
     render() {
         TraceMobx();
 
-        return !(this.doc instanceof Doc) || !this.treeChildren ? null : this.doc.treeViewHasOverlay ? (
-            <CollectionFreeFormView
-                {...OmitKeys(this.props, ['NativeWidth', 'NativeHeight', 'setContentView']).omit}
-                isAnnotationOverlay={true}
-                isAnnotationOverlayScrollable={true}
-                childDocumentsActive={this.props.isDocumentActive}
-                fieldKey={this.props.fieldKey + '-annotations'}
-                dropAction={'move'}
-                select={emptyFunction}
-                addDocument={this.addAnnotationDocument}
-                removeDocument={this.remAnnotationDocument}
-                moveDocument={this.moveAnnotationDocument}
-                bringToFront={emptyFunction}
-                renderDepth={this.props.renderDepth + 1}>
-                {this.contentFunc}
-            </CollectionFreeFormView>
-        ) : (
-            this.contentFunc()
+        const scale = (this.props.NativeDimScaling?.() || 1) * NumCast(this.layoutDoc._viewScale, 1) || 1;
+        return (
+            <div style={{ transform: `scale(${scale})`, transformOrigin: 'top left', width: `${100 / scale}%`, height: `${100 / scale}%` }}>
+                {!(this.doc instanceof Doc) || !this.treeChildren ? null : this.doc.treeViewHasOverlay ? (
+                    <CollectionFreeFormView
+                        {...OmitKeys(this.props, ['NativeWidth', 'NativeHeight', 'setContentView']).omit}
+                        isAnnotationOverlay={true}
+                        isAnnotationOverlayScrollable={true}
+                        childDocumentsActive={this.props.isDocumentActive}
+                        fieldKey={this.props.fieldKey + '-annotations'}
+                        dropAction={'move'}
+                        select={emptyFunction}
+                        addDocument={this.addAnnotationDocument}
+                        removeDocument={this.remAnnotationDocument}
+                        moveDocument={this.moveAnnotationDocument}
+                        bringToFront={emptyFunction}
+                        renderDepth={this.props.renderDepth + 1}>
+                        {this.contentFunc}
+                    </CollectionFreeFormView>
+                ) : (
+                    this.contentFunc()
+                )}
+            </div>
         );
     }
 }
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index dcaad5632..9f63a11aa 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -54,6 +54,8 @@ interface CollectionViewProps_ extends FieldViewProps {
     childHideDecorationTitle?: () => boolean;
     childHideResizeHandles?: () => boolean;
     childLayoutTemplate?: () => Doc | undefined; // specify a layout Doc template to use for children of the collection
+    childXPadding?: number;
+    childYPadding?: number;
     childLayoutString?: string;
     childIgnoreNativeSize?: boolean;
     childClickScript?: ScriptField;
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index a6cfbd6b2..cde5132a3 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -256,7 +256,6 @@ export class TabDocView extends React.Component<TabDocViewProps> {
             pinDoc.treeViewChildrenOnRoot = true; // tree view will look for hierarchical children on the root doc, not the data doc.
             pinDoc.treeViewFieldKey = 'data'; // tree view will treat the 'data' field as the field where the hierarchical children are located instead of using the document's layout string field
             pinDoc.treeViewExpandedView = 'data'; // in case the data doc has an expandedView set, this will mask that field and use the 'data' field when expanding the tree view
-            pinDoc.treeViewGrowsHorizontally = true; // the document expands horizontally when displayed as a tree view header
             pinDoc.treeViewHideHeaderIfTemplate = true; // this will force the document to render itself as the tree view header
             const presArray: Doc[] = PresBox.Instance?.sortArray();
             const size: number = PresBox.Instance?.selectedArray.size;
diff --git a/src/client/views/collections/TreeView.scss b/src/client/views/collections/TreeView.scss
index 57bb5274d..83fee013a 100644
--- a/src/client/views/collections/TreeView.scss
+++ b/src/client/views/collections/TreeView.scss
@@ -24,6 +24,7 @@
         // width: $TREE_BULLET_WIDTH;
         width: 100%;
         height: 100%;
+        position: absolute;
 
         .treeView-expandIcon {
             display: none;
@@ -118,7 +119,7 @@
     display: flex; // needed for PresBox's treeView
     border: transparent 1px solid;
     align-items: center;
-    width: 100%;
+    width: max-content;
     border-radius: 5px;
 
     &:hover {
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index b9f86fa6b..1e97eee37 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -10,7 +10,7 @@ import { listSpec } from '../../../fields/Schema';
 import { ComputedField, ScriptField } from '../../../fields/ScriptField';
 import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
 import { TraceMobx } from '../../../fields/util';
-import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, simulateMouseClick, Utils } from '../../../Utils';
+import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, returnZero, simulateMouseClick, Utils } from '../../../Utils';
 import { Docs, DocUtils } from '../../documents/Documents';
 import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
 import { DocumentManager } from '../../util/DocumentManager';
@@ -321,6 +321,7 @@ export class TreeView extends React.Component<TreeViewProps> {
             _viewType: CollectionViewType.Tree,
             hideLinkButton: true,
             _showSidebar: true,
+            _fitWidth: true,
             treeViewType: TreeViewType.outline,
             x: 0,
             y: 0,
@@ -398,29 +399,22 @@ export class TreeView extends React.Component<TreeViewProps> {
     };
     docTransform = () => this.refTransform(this._dref?.ContentRef?.current);
     getTransform = () => this.refTransform(this._tref.current);
-    docWidth = () => {
-        const layoutDoc = this.layoutDoc;
-        const aspect = Doc.NativeAspect(layoutDoc);
-        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()) / (this.props.treeView.props.NativeDimScaling?.() || 1), Doc.NativeWidth(layoutDoc) ? layoutDoc[WidthSym]() : this.layoutDoc[WidthSym]());
-    };
-    docHeight = () => {
-        const layoutDoc = this.layoutDoc;
-        return Math.max(
-            70,
-            Math.min(
-                this.MAX_EMBED_HEIGHT,
-                (() => {
-                    const aspect = Doc.NativeAspect(layoutDoc);
-                    if (aspect) return this.docWidth() / (aspect || 1);
-                    return layoutDoc._fitWidth
-                        ? !Doc.NativeHeight(this.doc)
-                            ? NumCast(this.props.containerCollection._height)
-                            : Math.min((this.docWidth() * NumCast(layoutDoc.scrollHeight, Doc.NativeHeight(layoutDoc))) / (Doc.NativeWidth(layoutDoc) || NumCast(this.props.containerCollection._height)))
-                        : layoutDoc[HeightSym]() || 50;
-                })()
-            )
+    embeddedPanelWidth = () => this.props.panelWidth() / (this.props.treeView.props.NativeDimScaling?.() || 1);
+    embeddedPanelHeight = () => {
+        console.log(this.props.treeView.rootDoc.title);
+        const layoutDoc = (temp => temp && Doc.expandTemplateLayout(temp, this.props.document, ''))(this.props.treeView.props.childLayoutTemplate?.()) || this.layoutDoc;
+        return Math.min(
+            layoutDoc[HeightSym](),
+            this.MAX_EMBED_HEIGHT,
+            (() => {
+                const aspect = Doc.NativeAspect(layoutDoc);
+                if (aspect) return this.embeddedPanelWidth() / (aspect || 1);
+                return layoutDoc._fitWidth
+                    ? !Doc.NativeHeight(layoutDoc)
+                        ? NumCast(layoutDoc._height) //this.props.containerCollection._height)
+                        : Math.min((this.embeddedPanelWidth() * NumCast(layoutDoc.scrollHeight, Doc.NativeHeight(layoutDoc))) / (Doc.NativeWidth(layoutDoc) || NumCast(this.props.containerCollection._height)))
+                    : (this.embeddedPanelWidth() * layoutDoc[HeightSym]()) / layoutDoc[WidthSym]();
+            })()
         );
     };
 
@@ -512,28 +506,6 @@ export class TreeView extends React.Component<TreeViewProps> {
         return rows;
     }
 
-    rtfWidth = () => {
-        const layout = (temp => temp && Doc.expandTemplateLayout(temp, this.props.document, ''))(this.props.treeView.props.childLayoutTemplate?.()) || this.layoutDoc;
-        return Math.min(layout[WidthSym](), this.props.panelWidth() - treeBulletWidth()) / (this.props.treeView.props.NativeDimScaling?.() || 1);
-    };
-    rtfHeight = () => {
-        const layout = (temp => temp && Doc.expandTemplateLayout(temp, this.props.document, ''))(this.props.treeView.props.childLayoutTemplate?.()) || this.layoutDoc;
-        return this.rtfWidth() <= layout[WidthSym]() ? Math.min(layout[HeightSym](), this.MAX_EMBED_HEIGHT) : this.MAX_EMBED_HEIGHT;
-    };
-    rtfOutlineHeight = () => Math.max(this.layoutDoc?.[HeightSym](), treeBulletWidth());
-    expandPanelHeight = () => {
-        if (this.layoutDoc._fitWidth) return this.docHeight();
-        const aspect = this.layoutDoc[WidthSym]() / this.layoutDoc[HeightSym]();
-        const docAspect = this.docWidth() / this.docHeight();
-        return docAspect < aspect ? this.docWidth() / aspect : this.docHeight();
-    };
-    expandPanelWidth = () => {
-        if (this.layoutDoc._fitWidth) return this.docWidth();
-        const aspect = this.layoutDoc[WidthSym]() / this.layoutDoc[HeightSym]();
-        const docAspect = this.docWidth() / this.docHeight();
-        return docAspect > aspect ? this.docHeight() * aspect : this.docWidth();
-    };
-
     @computed get renderContent() {
         TraceMobx();
         const expandKey = this.treeViewExpandedView;
@@ -792,15 +764,18 @@ export class TreeView extends React.Component<TreeViewProps> {
     titleStyleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, 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
 
+        const treeView = this.props.treeView;
         // prettier-ignore
         switch (property.split(':')[0]) {
             case StyleProp.Opacity:         return this.props.treeView.outlineMode ? undefined : 1;
             case StyleProp.BackgroundColor: return this.selected ? '#7089bb' : StrCast(doc._backgroundColor, StrCast(doc.backgroundColor));
             case StyleProp.Highlighting:    if (this.props.treeView.outlineMode) return undefined;
+            case StyleProp.Hidden:          return false;
+            case StyleProp.BoxShadow:       return undefined;
             case StyleProp.DocContents:
                 const highlightIndex = this.props.treeView.outlineMode ? Doc.DocBrushStatus.unbrushed : Doc.isBrushedHighlightedDegree(doc);
                 const highlightColor = ['transparent', 'rgb(68, 118, 247)', 'rgb(68, 118, 247)', 'orange', 'lightBlue'][highlightIndex];
-                return this.props.treeView.outlineMode ? null : (
+                return treeView.outlineMode ? null : (
                     <div
                         className="treeView-label"
                         style={{
@@ -808,15 +783,20 @@ export class TreeView extends React.Component<TreeViewProps> {
                             maxWidth: props?.PanelWidth() || undefined,
                             background: props?.styleProvider?.(doc, props, StyleProp.BackgroundColor),
                             outline: `solid ${highlightColor} ${highlightIndex}px`,
+                            paddingLeft: NumCast(treeView.rootDoc.childXPadding, NumCast(treeView.props.childXPadding, Doc.IsComicStyle(doc)?20:0)),
+                            paddingRight: NumCast(treeView.rootDoc.childXPadding, NumCast(treeView.props.childXPadding, Doc.IsComicStyle(doc)?20:0)),
+                            paddingTop: treeView.props.childYPadding,
+                            paddingBottom: treeView.props.childYPadding,
                         }}>
                         {StrCast(doc?.title)}
                     </div>
                 );
         }
-        return this.props?.treeView?.props.styleProvider?.(doc, props, property);
+        return treeView.props.styleProvider?.(doc, props, property);
     };
     embeddedStyleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, property: string): any => {
         if (property.startsWith(StyleProp.Decorations)) return null;
+        if (property.startsWith(StyleProp.Hidden)) return false;
         return this.props?.treeView?.props.styleProvider?.(doc, props, property); // properties are inherited from the CollectionTreeView, not the hierarchical parent in the treeView
     };
     onKeyDown = (e: React.KeyboardEvent, fieldProps: FieldViewProps) => {
@@ -843,7 +823,7 @@ export class TreeView extends React.Component<TreeViewProps> {
         }
         return false;
     };
-    titleWidth = () => Math.max(20, Math.min(this.props.treeView.truncateTitleWidth(), this.props.panelWidth() - 2 * treeBulletWidth()));
+    titleWidth = () => Math.max(20, Math.min(this.props.treeView.truncateTitleWidth(), this.props.panelWidth())) / (this.props.treeView.props.NativeDimScaling?.() || 1) - 3 * treeBulletWidth();
 
     return18 = () => 18;
     /**
@@ -851,6 +831,7 @@ export class TreeView extends React.Component<TreeViewProps> {
      */
     @computed
     get renderTitle() {
+        //
         TraceMobx();
         const view = this._editTitle ? (
             <EditableView
@@ -887,6 +868,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                     }
                 })}
                 Document={this.doc}
+                fitWidth={(doc: Doc) => true}
                 DataDoc={undefined}
                 scriptContext={this}
                 hideDecorationTitle={this.props.treeView.outlineMode}
@@ -905,7 +887,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                 removeDocument={this.props.removeDoc}
                 ScreenToLocalTransform={this.getTransform}
                 NativeHeight={this.return18}
-                NativeWidth={this.titleWidth}
+                NativeWidth={returnZero}
                 PanelWidth={this.titleWidth}
                 PanelHeight={this.return18}
                 contextMenuItems={this.contextMenuItems}
@@ -918,10 +900,12 @@ export class TreeView extends React.Component<TreeViewProps> {
                 disableDocBrushing={this.props.treeView.props.disableDocBrushing}
                 hideLinkButton={BoolCast(this.props.treeView.props.Document.childHideLinkButton)}
                 dontRegisterView={BoolCast(this.props.treeView.props.Document.childDontRegisterViews, this.props.dontRegisterView)}
+                xPadding={NumCast(this.props.treeView.props.Document.childXPadding, this.props.treeView.props.childXPadding)}
+                yPadding={NumCast(this.props.treeView.props.Document.childYPadding, this.props.treeView.props.childYPadding)}
                 docFilters={returnEmptyFilter}
                 docRangeFilters={returnEmptyFilter}
                 searchFilterDocs={returnEmptyDoclist}
-                ContainingCollectionView={undefined}
+                ContainingCollectionView={this.props.treeView.props.CollectionView}
                 ContainingCollectionDoc={this.props.treeView.props.Document}
             />
         );
@@ -968,53 +952,52 @@ export class TreeView extends React.Component<TreeViewProps> {
     };
 
     renderEmbeddedDocument = (asText: boolean, isActive: () => boolean | undefined) => {
-        const isExpandable = this.doc._treeViewGrowsHorizontally;
-        const panelWidth = asText || isExpandable ? this.rtfWidth : this.expandPanelWidth;
-        const panelHeight = asText ? this.rtfOutlineHeight : isExpandable ? this.rtfHeight : this.expandPanelHeight;
         return (
-            <DocumentView
-                key={this.doc[Id]}
-                ref={action((r: DocumentView | null) => (this._dref = r))}
-                Document={this.doc}
-                DataDoc={undefined}
-                PanelWidth={panelWidth}
-                PanelHeight={panelHeight}
-                NativeWidth={!asText && (this.layoutDoc.type === DocumentType.RTF || this.layoutDoc.type === DocumentType.SLIDER) ? this.rtfWidth : undefined}
-                NativeHeight={!asText && (this.layoutDoc.type === DocumentType.RTF || this.layoutDoc.type === DocumentType.SLIDER) ? this.rtfHeight : undefined}
-                LayoutTemplateString={asText ? FormattedTextBox.LayoutString('text') : undefined}
-                LayoutTemplate={this.props.treeView.props.childLayoutTemplate}
-                isContentActive={isActive}
-                isDocumentActive={isActive}
-                styleProvider={asText ? this.titleStyleProvider : this.embeddedStyleProvider}
-                hideTitle={asText}
-                fitContentsToBox={returnTrue}
-                hideDecorationTitle={this.props.treeView.outlineMode}
-                hideResizeHandles={this.props.treeView.outlineMode}
-                onClick={this.onChildClick}
-                focus={this.refocus}
-                onKey={this.onKeyDown}
-                hideLinkButton={BoolCast(this.props.treeView.props.Document.childHideLinkButton)}
-                dontRegisterView={BoolCast(this.props.treeView.props.Document.childDontRegisterViews, this.props.dontRegisterView)}
-                ScreenToLocalTransform={this.docTransform}
-                renderDepth={this.props.renderDepth + 1}
-                treeViewDoc={this.props.treeView?.props.Document}
-                rootSelected={returnTrue}
-                docViewPath={this.props.treeView.props.docViewPath}
-                docFilters={returnEmptyFilter}
-                docRangeFilters={returnEmptyFilter}
-                searchFilterDocs={returnEmptyDoclist}
-                ContainingCollectionDoc={this.props.containerCollection}
-                ContainingCollectionView={undefined}
-                addDocument={this.props.addDocument}
-                moveDocument={this.move}
-                removeDocument={this.props.removeDoc}
-                whenChildContentsActiveChanged={this.props.whenChildContentsActiveChanged}
-                addDocTab={this.props.addDocTab}
-                pinToPres={this.props.treeView.props.pinToPres}
-                disableDocBrushing={this.props.treeView.props.disableDocBrushing}
-                bringToFront={returnFalse}
-                scriptContext={this}
-            />
+            <div style={{ height: this.embeddedPanelHeight(), width: this.embeddedPanelWidth() }}>
+                <DocumentView
+                    key={this.doc[Id]}
+                    ref={action((r: DocumentView | null) => (this._dref = r))}
+                    Document={this.doc}
+                    DataDoc={undefined}
+                    PanelWidth={this.embeddedPanelWidth}
+                    PanelHeight={this.embeddedPanelHeight}
+                    LayoutTemplateString={asText ? FormattedTextBox.LayoutString('text') : undefined}
+                    LayoutTemplate={this.props.treeView.props.childLayoutTemplate}
+                    isContentActive={isActive}
+                    isDocumentActive={isActive}
+                    styleProvider={asText ? this.titleStyleProvider : this.embeddedStyleProvider}
+                    hideTitle={asText}
+                    //fitContentsToBox={returnTrue}
+                    hideDecorationTitle={this.props.treeView.outlineMode}
+                    hideResizeHandles={this.props.treeView.outlineMode}
+                    onClick={this.onChildClick}
+                    focus={this.refocus}
+                    onKey={this.onKeyDown}
+                    hideLinkButton={BoolCast(this.props.treeView.props.Document.childHideLinkButton)}
+                    dontRegisterView={BoolCast(this.props.treeView.props.Document.childDontRegisterViews, this.props.dontRegisterView)}
+                    ScreenToLocalTransform={this.docTransform}
+                    renderDepth={this.props.renderDepth + 1}
+                    treeViewDoc={this.props.treeView?.props.Document}
+                    rootSelected={returnTrue}
+                    docViewPath={this.props.treeView.props.docViewPath}
+                    docFilters={returnEmptyFilter}
+                    docRangeFilters={returnEmptyFilter}
+                    searchFilterDocs={returnEmptyDoclist}
+                    ContainingCollectionDoc={this.props.containerCollection}
+                    ContainingCollectionView={undefined}
+                    addDocument={this.props.addDocument}
+                    moveDocument={this.move}
+                    removeDocument={this.props.removeDoc}
+                    whenChildContentsActiveChanged={this.props.whenChildContentsActiveChanged}
+                    xPadding={NumCast(this.props.treeView.props.Document.childXPadding, this.props.treeView.props.childXPadding)}
+                    yPadding={NumCast(this.props.treeView.props.Document.childYPadding, this.props.treeView.props.childYPadding)}
+                    addDocTab={this.props.addDocTab}
+                    pinToPres={this.props.treeView.props.pinToPres}
+                    disableDocBrushing={this.props.treeView.props.disableDocBrushing}
+                    bringToFront={returnFalse}
+                    scriptContext={this}
+                />
+            </div>
         );
     };
 
@@ -1148,7 +1131,7 @@ export class TreeView extends React.Component<TreeViewProps> {
         }
 
         const docs = TreeView.sortDocs(childDocs, StrCast(containerCollection.treeViewSortCriterion, TreeSort.None));
-        const rowWidth = () => panelWidth() - treeBulletWidth();
+        const rowWidth = () => panelWidth() - treeBulletWidth() * (treeView.props.NativeDimScaling?.() || 1);
         const treeViewRefs = new Map<Doc, TreeView | undefined>();
         return docs
             .filter(child => child instanceof Doc)
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 559951efc..2f246e74f 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1317,7 +1317,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                 dontScaleFilter={this.props.dontScaleFilter}
                 dontRegisterView={this.props.dontRenderDocuments || this.props.dontRegisterView}
                 pointerEvents={this.pointerEvents}
-                jitterRotation={this.props.styleProvider?.(childLayout, this.props, StyleProp.JitterRotation) || 0}
+                rotation={this.props.styleProvider?.(childLayout, this.props, StyleProp.JitterRotation) || 0}
                 //fitContentsToBox={this.props.fitContentsToBox || BoolCast(this.props.freezeChildDimensions)} // bcz: check this
             />
         );
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 04c7b96e3..260c98816 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -25,7 +25,7 @@ export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
     renderCutoffProvider: (doc: Doc) => boolean;
     zIndex?: number;
     highlight?: boolean;
-    jitterRotation: number;
+    rotation: number;
     dataTransition?: string;
     replica: string;
     CollectionFreeFormView: CollectionFreeFormView;
@@ -38,7 +38,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
         { key: '_width' },
         { key: 'x' },
         { key: 'y' },
-        { key: '_jitterRotation', val: 0 },
+        { key: '_rotation', val: 0 },
         { key: '_scrollTop' },
         { key: 'opacity', val: 1 },
         { key: 'viewScale', val: 1 },
@@ -55,7 +55,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
     }
 
     get transform() {
-        return `translate(${this.X}px, ${this.Y}px) rotate(${NumCast(this.Document.jitterRotation, this.props.jitterRotation)}deg)`;
+        return `translate(${this.X}px, ${this.Y}px) rotate(${NumCast(this.Document.rotation, this.props.rotation)}deg)`;
     }
     get X() {
         return this.dataProvider?.x ?? NumCast(this.Document.x);
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index fecbc2de2..5b26469ed 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -53,6 +53,7 @@ import { RadialMenu } from './RadialMenu';
 import { ScriptingBox } from './ScriptingBox';
 import { PresBox } from './trails/PresBox';
 import React = require('react');
+import { CollectionTreeView } from '../collections/CollectionTreeView';
 const { Howl } = require('howler');
 
 interface Window {
@@ -147,6 +148,8 @@ export interface DocumentViewSharedProps {
     pinToPres: (document: Doc) => void;
     ScreenToLocalTransform: () => Transform;
     bringToFront: (doc: Doc, sendToBack?: boolean) => void;
+    xPadding?: number;
+    yPadding?: number;
     dropAction?: dropActionType;
     dontRegisterView?: boolean;
     hideLinkButton?: boolean;
@@ -1349,17 +1352,10 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
             this.contents
         ) : (
             <div className="documentView-styleWrapper">
-                {!this.headerMargin ? (
-                    <>
-                        {' '}
-                        {this.contents} {titleView}{' '}
-                    </>
-                ) : (
-                    <>
-                        {' '}
-                        {titleView} {this.contents}{' '}
-                    </>
-                )}
+                {' '}
+                {!this.headerMargin ? this.contents : titleView}
+                {!this.headerMargin ? titleView : this.contents}
+                {' ' /* */}
                 {captionView}
             </div>
         );
@@ -1372,7 +1368,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
         TraceMobx();
         const thumb = ImageCast(this.layoutDoc['thumb-frozen'], ImageCast(this.layoutDoc.thumb))?.url?.href.replace('.png', '_m.png');
         const isButton = this.props.Document.type === DocumentType.FONTICON;
-        if (!(this.props.Document instanceof Doc) || GetEffectiveAcl(this.props.Document[DataSym]) === AclPrivate || (this.hidden && !this.props.treeViewDoc)) return null;
+        if (!(this.props.Document instanceof Doc) || GetEffectiveAcl(this.props.Document[DataSym]) === AclPrivate || this.hidden) return null;
         return (
             this.docContents ?? (
                 <div
@@ -1448,7 +1444,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                     <>
                         {animRenderDoc}
                         <div key="border2" className="documentView-customBorder" style={{ pointerEvents: 'none' }}>
-                            <svg style={{ overflow: 'visible' }} viewBox={`0 0 ${this.props.PanelWidth()} ${this.props.PanelHeight()}`}>
+                            <svg style={{ overflow: 'visible', height: '100%' }} viewBox={`0 0 ${this.props.PanelWidth()} ${this.props.PanelHeight()}`}>
                                 <path d={borderPath.path} style={{ stroke: 'black', fill: 'transparent', strokeWidth: borderPath.width }} />
                             </svg>
                         </div>
@@ -1552,7 +1548,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         return this.docView?._componentView?.reverseNativeScaling?.() ? 0 : returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, !this.fitWidth));
     }
     @computed get shouldNotScale() {
-        return (this.fitWidth && !this.nativeWidth) || this.props.dontScaleFilter?.(this.Document) || this.props.treeViewDoc || [CollectionViewType.Docking].includes(this.Document._viewType as any);
+        return (this.fitWidth && !this.nativeWidth) || this.props.dontScaleFilter?.(this.Document) || [CollectionViewType.Docking].includes(this.Document._viewType as any);
     }
     @computed get effectiveNativeWidth() {
         return this.shouldNotScale ? 0 : this.nativeWidth || NumCast(this.layoutDoc.width);
@@ -1597,7 +1593,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     toggleNativeDimensions = () => this.docView && Doc.toggleNativeDimensions(this.layoutDoc, this.docView.NativeDimScaling, this.props.PanelWidth(), this.props.PanelHeight());
     focus = (doc: Doc, options: DocFocusOptions) => this.docView?.focus(doc, options);
     getBounds = () => {
-        if (!this.docView || !this.docView.ContentDiv || this.props.Document.presBox || this.docView.props.treeViewDoc || Doc.AreProtosEqual(this.props.Document, Doc.UserDoc())) {
+        if (!this.docView || !this.docView.ContentDiv || this.props.Document.presBox || this.props.treeViewDoc || Doc.AreProtosEqual(this.props.Document, Doc.UserDoc())) {
             return undefined;
         }
         const xf = this.docView?.props.ScreenToLocalTransform().scale(this.nativeScaling).inverse();
@@ -1687,10 +1683,9 @@ export class DocumentView extends React.Component<DocumentViewProps> {
 
     render() {
         TraceMobx();
-        const xshift = () => (Math.abs(this.Xshift) <= 0.001 ? this.props.PanelWidth() : undefined);
-        const yshift = () => (Math.abs(this.Yshift) <= 0.001 ? this.props.PanelHeight() : undefined);
-        const isPresTreeElement: boolean = this.props.treeViewDoc?.type === DocumentType.PRES;
-        const isButton: boolean = this.props.Document.type === DocumentType.FONTICON || this.props.Document._viewType === CollectionViewType.Linear;
+        const xshift = Math.abs(this.Xshift) <= 0.001 ? this.props.PanelWidth() : undefined;
+        const yshift = Math.abs(this.Yshift) <= 0.001 ? this.props.PanelHeight() : undefined;
+        const isButton = this.props.Document.type === DocumentType.FONTICON || this.props.Document._viewType === CollectionViewType.Linear;
         return (
             <div className="contentFittingDocumentView">
                 {!this.props.Document || !this.props.PanelWidth() ? null : (
@@ -1700,11 +1695,11 @@ export class DocumentView extends React.Component<DocumentViewProps> {
                         style={{
                             transition: this.props.dataTransition,
                             transform: isButton ? undefined : `translate(${this.centeringX}px, ${this.centeringY}px)`,
-                            width: isButton || isPresTreeElement ? '100%' : xshift() ?? `${(100 * (this.props.PanelWidth() - this.Xshift * 2)) / this.props.PanelWidth()}%`,
+                            width: isButton ? '100%' : xshift ?? `${(100 * (this.props.PanelWidth() - this.Xshift * 2)) / this.props.PanelWidth()}%`,
                             height:
                                 isButton || this.props.forceAutoHeight
                                     ? undefined
-                                    : yshift() ?? (this.fitWidth ? `${this.panelHeight}px` : `${(((100 * this.effectiveNativeHeight) / this.effectiveNativeWidth) * this.props.PanelWidth()) / this.props.PanelHeight()}%`),
+                                    : yshift ?? (this.fitWidth ? `${this.panelHeight}px` : `${(((100 * this.effectiveNativeHeight) / this.effectiveNativeWidth) * this.props.PanelWidth()) / this.props.PanelHeight()}%`),
                         }}>
                         <DocumentViewInternal
                             {...this.props}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 77aaa4441..e53422ab7 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -36,8 +36,6 @@ export interface FieldViewProps extends DocumentViewSharedProps {
     fontSize?: number;
     height?: number;
     width?: number;
-    xPadding?: number;
-    yPadding?: number;
     noSidebar?: boolean;
     dontScale?: boolean;
     dontSelectOnLoad?: boolean; // suppress selecting (e.g.,. text box) when loaded (and mark as not being associated with scrollTop document field)
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index f7f558bb4..fb47bfc07 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -935,7 +935,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
                     className="videoBox-ui"
                     style={{
                         transformOrigin: 'top left',
-                        transform: `rotate(${NumCast(this.rootDoc.jitterRotation)}deg) translate(${-(xRight - xPos) + 10}px, ${yBot - yMid - uiHeight - uiMargin}px)`,
+                        transform: `rotate(${NumCast(this.rootDoc.rotation)}deg) translate(${-(xRight - xPos) + 10}px, ${yBot - yMid - uiHeight - uiMargin}px)`,
                         left: xPos,
                         top: yMid,
                         height: uiHeight,
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 5470d6ba9..096f9a92c 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1004,11 +1004,13 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
             () => this.autoHeight,
             autoHeight => autoHeight && this.tryUpdateScrollHeight()
         );
+        this._disposers.width = reaction(
+            () => this.props.PanelWidth(),
+            width => this.tryUpdateScrollHeight()
+        );
         this._disposers.scrollHeight = reaction(
             () => ({ scrollHeight: this.scrollHeight, autoHeight: this.autoHeight, width: NumCast(this.layoutDoc._width) }),
-            ({ width, scrollHeight, autoHeight }) => {
-                width && autoHeight && this.resetNativeHeight(scrollHeight);
-            },
+            ({ width, scrollHeight, autoHeight }) => width && autoHeight && this.resetNativeHeight(scrollHeight),
             { fireImmediately: true }
         );
         this._disposers.componentHeights = reaction(
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 258dad39c..4e8aed8a6 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -429,7 +429,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             pinDoc.presPinLayout = true;
             pinDoc.presX = NumCast(targetDoc.x);
             pinDoc.presY = NumCast(targetDoc.y);
-            pinDoc.presRot = NumCast(targetDoc.jitterRotation);
+            pinDoc.presRot = NumCast(targetDoc.rotation);
             pinDoc.presWidth = NumCast(targetDoc.width);
             pinDoc.presHeight = NumCast(targetDoc.height);
         }
@@ -521,7 +521,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             targetDoc._dataTransition = presTransitionTime;
             targetDoc.x = NumCast(activeItem.presX, NumCast(targetDoc.x));
             targetDoc.y = NumCast(activeItem.presY, NumCast(targetDoc.y));
-            targetDoc.jitterRotation = NumCast(activeItem.presRot, NumCast(targetDoc.jitterRotation));
+            targetDoc.rotation = NumCast(activeItem.presRot, NumCast(targetDoc.rotation));
             targetDoc.width = NumCast(activeItem.presWidth, NumCast(targetDoc.width));
             targetDoc.height = NumCast(activeItem.presHeight, NumCast(targetDoc.height));
             setTimeout(() => (targetDoc._dataTransition = undefined), transTime + 10);
@@ -2652,9 +2652,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                 PanelHeight={this.panelHeight}
                                 childIgnoreNativeSize={true}
                                 moveDocument={returnFalse}
-                                childFitWidth={returnTrue}
+                                //childFitWidth={returnTrue}
                                 childOpacity={returnOne}
                                 childLayoutTemplate={this.childLayoutTemplate}
+                                childXPadding={Doc.IsComicStyle(this.rootDoc) ? 20 : undefined}
                                 filterAddDocument={this.addDocumentFilter}
                                 removeDocument={returnFalse}
                                 dontRegisterView={true}
diff --git a/src/client/views/nodes/trails/PresElementBox.scss b/src/client/views/nodes/trails/PresElementBox.scss
index 8a6c2a6dc..415253af1 100644
--- a/src/client/views/nodes/trails/PresElementBox.scss
+++ b/src/client/views/nodes/trails/PresElementBox.scss
@@ -42,10 +42,7 @@ $slide-active: #5b9fdd;
     width: 100%;
     border-bottom: 0.5px solid grey;
     display: flex;
-    justify-content: space-between;
     align-items: center;
-    grid-template-rows: 16px 10px auto;
-    grid-template-columns: max-content max-content max-content max-content auto;
 
     .presItem-name {
         display: flex;
@@ -102,13 +99,7 @@ $slide-active: #5b9fdd;
         grid-row: 3;
         grid-column: 1/8;
         position: relative;
-        display: flex;
-        width: auto;
-        justify-content: center;
-        margin: auto;
-        margin-bottom: 2px;
-        border-bottom-left-radius: 5px;
-        border-bottom-right-radius: 5px;
+        display: inline-block;
     }
 
     .presItem-embeddedMask {
@@ -124,8 +115,7 @@ $slide-active: #5b9fdd;
 
     .presItem-slideButtons {
         display: flex;
-        grid-column: 7;
-        grid-row: 1/3;
+        position: absolute;
         width: max-content;
         justify-self: right;
         justify-content: flex-end;
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx
index f4ab845f3..5d14a0e9a 100644
--- a/src/client/views/nodes/trails/PresElementBox.tsx
+++ b/src/client/views/nodes/trails/PresElementBox.tsx
@@ -4,7 +4,9 @@ import { action, computed, IReactionDisposer, observable, reaction } from 'mobx'
 import { observer } from 'mobx-react';
 import { Doc, DocListCast, HeightSym, Opt, WidthSym } from '../../../../fields/Doc';
 import { Copy, Id } from '../../../../fields/FieldSymbols';
+import { InkField } from '../../../../fields/InkField';
 import { List } from '../../../../fields/List';
+import { RichTextField } from '../../../../fields/RichTextField';
 import { Cast, DocCast, NumCast, StrCast } from '../../../../fields/Types';
 import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents } from '../../../../Utils';
 import { Docs, DocUtils } from '../../../documents/Documents';
@@ -14,6 +16,7 @@ import { DragManager } from '../../../util/DragManager';
 import { SettingsManager } from '../../../util/SettingsManager';
 import { Transform } from '../../../util/Transform';
 import { undoBatch } from '../../../util/UndoManager';
+import { MarqueeView } from '../../collections/collectionFreeForm';
 import { ViewBoxBaseComponent } from '../../DocComponent';
 import { EditableView } from '../../EditableView';
 import { Colors } from '../../global/globalEnums';
@@ -24,9 +27,6 @@ import { PresBox } from './PresBox';
 import './PresElementBox.scss';
 import { PresMovement } from './PresEnums';
 import React = require('react');
-import { InkField } from '../../../../fields/InkField';
-import { RichTextField } from '../../../../fields/RichTextField';
-import { MarqueeView } from '../../collections/collectionFreeForm';
 /**
  * This class models the view a document added to presentation will have in the presentation.
  * It involves some functionality for its buttons and options.
@@ -44,8 +44,11 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @computed get indexInPres() {
         return DocListCast(this.presBox[StrCast(this.presBox.presFieldKey, 'data')]).indexOf(this.rootDoc);
     } // the index field is where this document is in the presBox display list (since this value is different for each presentation element, the value can't be stored on the layout template which is used by all display elements)
+    @computed get expandViewHeight() {
+        return 100;
+    }
     @computed get collapsedHeight() {
-        return [CollectionViewType.Tree, CollectionViewType.Stacking].includes(this.presBox._viewType as any) ? 35 : 31;
+        return 35;
     } // the collapsed height changes depending on the state of the presBox.  We could store this on the presentation element template if it's used by only one presentation - but if it's shared by multiple, then this value must be looked up
     @computed get presStatus() {
         return this.presBox.presStatus;
@@ -58,7 +61,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
         return vpath.length > 1 ? (vpath[vpath.length - 2].ComponentView as PresBox) : undefined;
     }
     @computed get presBox() {
-        return (this.props.DocumentView?.().props.treeViewDoc ?? this.props.ContainingCollectionDoc)!;
+        return this.props.ContainingCollectionDoc!;
     }
     @computed get targetDoc() {
         return Cast(this.rootDoc.presentationTargetDoc, Doc, null) || this.rootDoc;
@@ -67,8 +70,8 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
     componentDidMount() {
         this.layoutDoc.hideLinkButton = true;
         this._heightDisposer = reaction(
-            () => [this.rootDoc.presExpandInlineButton, this.collapsedHeight],
-            params => (this.layoutDoc._height = NumCast(params[1]) + (Number(params[0]) ? 100 : 0)),
+            () => ({ expand: this.rootDoc.presExpandInlineButton, height: this.collapsedHeight }),
+            ({ expand, height }) => (this.layoutDoc._height = height + (expand ? this.expandViewHeight : 0)),
             { fireImmediately: true }
         );
     }
@@ -84,10 +87,10 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @action
     presExpandDocumentClick = () => (this.rootDoc.presExpandInlineButton = !this.rootDoc.presExpandInlineButton);
 
-    embedHeight = (): number => 97;
+    embedHeight = (): number => this.collapsedHeight + this.expandViewHeight;
     // embedWidth = () => this.props.PanelWidth();
     // embedHeight = () => Math.min(this.props.PanelWidth() - 20, this.props.PanelHeight() - this.collapsedHeight);
-    embedWidth = (): number => this.props.PanelWidth() - 35;
+    embedWidth = (): number => this.props.PanelWidth() / 2;
     styleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, property: string): any => {
         if (property === StyleProp.Opacity) return 1;
         return this.props.styleProvider?.(doc, props, property);
@@ -98,35 +101,35 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
      */
     @computed get renderEmbeddedInline() {
         return !this.rootDoc.presExpandInlineButton || !this.targetDoc ? null : (
-            <div className="presItem-embedded" style={{ height: this.embedHeight(), width: this.embedWidth() }}>
+            <div className="presItem-embedded" style={{ height: this.embedHeight(), width: '50%' }}>
                 <DocumentView
                     Document={this.rootDoc}
                     DataDoc={undefined} //this.targetDoc[DataSym] !== this.targetDoc && this.targetDoc[DataSym]}
+                    PanelWidth={this.embedWidth}
+                    PanelHeight={this.embedHeight}
+                    isContentActive={this.props.isContentActive}
                     styleProvider={this.styleProvider}
+                    hideLinkButton={true}
+                    ScreenToLocalTransform={Transform.Identity}
+                    renderDepth={this.props.renderDepth + 1}
                     docViewPath={returnEmptyDoclist}
+                    docFilters={this.props.docFilters}
+                    docRangeFilters={this.props.docRangeFilters}
+                    searchFilterDocs={this.props.searchFilterDocs}
+                    ContainingCollectionView={undefined}
+                    ContainingCollectionDoc={undefined}
                     rootSelected={returnTrue}
                     addDocument={returnFalse}
                     removeDocument={returnFalse}
-                    isContentActive={this.props.isContentActive}
-                    addDocTab={returnFalse}
-                    pinToPres={returnFalse}
                     fitContentsToBox={returnTrue}
-                    PanelWidth={this.embedWidth}
-                    PanelHeight={this.embedHeight}
-                    ScreenToLocalTransform={Transform.Identity}
                     moveDocument={this.props.moveDocument!}
-                    renderDepth={this.props.renderDepth + 1}
                     focus={DocUtils.DefaultFocus}
                     whenChildContentsActiveChanged={returnFalse}
+                    addDocTab={returnFalse}
+                    pinToPres={returnFalse}
                     bringToFront={returnFalse}
-                    docFilters={this.props.docFilters}
-                    docRangeFilters={this.props.docRangeFilters}
-                    searchFilterDocs={this.props.searchFilterDocs}
-                    ContainingCollectionView={undefined}
-                    ContainingCollectionDoc={undefined}
-                    hideLinkButton={true}
                 />
-                <div className="presItem-embeddedMask" />
+                {/* <div className="presItem-embeddedMask" /> */}
             </div>
         );
     }
@@ -206,8 +209,8 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
         const dragData = new DragManager.DocumentDragData(this.presBoxView?.sortArray() ?? []);
         if (!dragData.draggedDocuments.length) dragData.draggedDocuments.push(this.rootDoc);
         dragData.dropAction = 'move';
-        dragData.treeViewDoc = this.props.docViewPath().lastElement()?.props.treeViewDoc;
-        dragData.moveDocument = this.props.docViewPath().lastElement()?.props.moveDocument;
+        dragData.treeViewDoc = this.presBox._viewType === CollectionViewType.Tree ? this.props.ContainingCollectionDoc : undefined; // this.props.DocumentView?.()?.props.treeViewDoc;
+        dragData.moveDocument = this.props.moveDocument;
         const dragItem: HTMLElement[] = [];
         if (dragArray.length === 1) {
             const doc = this._itemRef.current || dragArray[0];
@@ -307,7 +310,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
     updateCapturedContainerLayout = (targetDoc: Doc, activeItem: Doc) => {
         activeItem.presX = NumCast(targetDoc.x);
         activeItem.presY = NumCast(targetDoc.y);
-        activeItem.presRot = NumCast(targetDoc.jitterRotation);
+        activeItem.presRot = NumCast(targetDoc.rotation);
         activeItem.presWidth = NumCast(targetDoc.width);
         activeItem.presHeight = NumCast(targetDoc.height);
     };
@@ -464,16 +467,90 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
         return width;
     }
 
+    @computed get presButtons() {
+        const presBox: Doc = this.presBox; //presBox
+        const presBoxColor: string = StrCast(presBox._backgroundColor);
+        const presColorBool: boolean = presBoxColor ? presBoxColor !== Colors.WHITE && presBoxColor !== 'transparent' : false;
+        const targetDoc: Doc = this.targetDoc;
+        const activeItem: Doc = this.rootDoc;
+
+        const items: JSX.Element[] = [];
+        if (activeItem.presPinLayout) {
+            items.push(
+                <Tooltip key="slide" title={<div className="dash-tooltip">Update captured doc layout</div>}>
+                    <div className="slideButton" onClick={() => this.updateCapturedContainerLayout(targetDoc, activeItem)} style={{ fontWeight: 700, display: 'flex' }}>
+                        L
+                    </div>
+                </Tooltip>
+            );
+        }
+        if (activeItem.presPinData || activeItem.presPinView) {
+            items.push(
+                <Tooltip key="flex" title={<div className="dash-tooltip">Update captured doc content</div>}>
+                    <div className="slideButton" onClick={() => this.updateCapturedViewContents(targetDoc, activeItem)} style={{ fontWeight: 700, display: 'flex' }}>
+                        C
+                    </div>
+                </Tooltip>
+            );
+        }
+        if (!Doc.noviceMode) {
+            items.push(
+                <Tooltip key="slash" title={<div className="dash-tooltip">{this.recordingIsInOverlay ? 'Hide Recording' : `${PresElementBox.videoIsRecorded(activeItem) ? 'Show' : 'Start'} recording`}</div>}>
+                    <div className="slideButton" onClick={e => (this.recordingIsInOverlay ? this.hideRecording(e, true) : this.startRecording(e, activeItem))} style={{ fontWeight: 700 }}>
+                        <FontAwesomeIcon icon={`video${this.recordingIsInOverlay ? '-slash' : ''}`} onPointerDown={e => e.stopPropagation()} />
+                    </div>
+                </Tooltip>
+            );
+        }
+        if (this.indexInPres === 0) {
+            items.push(
+                <Tooltip key="arrow" title={<div className="dash-tooltip">{activeItem.groupWithUp ? 'Ungroup' : 'Group with up'}</div>}>
+                    <div
+                        className="slideButton"
+                        onClick={() => (activeItem.groupWithUp = !activeItem.groupWithUp)}
+                        style={{
+                            zIndex: 1000 - this.indexInPres,
+                            fontWeight: 700,
+                            backgroundColor: activeItem.groupWithUp ? (presColorBool ? presBoxColor : Colors.MEDIUM_BLUE) : undefined,
+                            height: activeItem.groupWithUp ? 53 : 18,
+                            transform: activeItem.groupWithUp ? 'translate(0, -17px)' : undefined,
+                        }}>
+                        <div style={{ transform: activeItem.groupWithUp ? 'rotate(180deg) translate(0, -17.5px)' : 'rotate(0deg)' }}>
+                            <FontAwesomeIcon icon={'arrow-up'} onPointerDown={e => e.stopPropagation()} />
+                        </div>
+                    </div>
+                </Tooltip>
+            );
+        }
+        items.push(
+            <Tooltip key="eye" title={<div className="dash-tooltip">{this.rootDoc.presExpandInlineButton ? 'Minimize' : 'Expand'}</div>}>
+                <div
+                    className="slideButton"
+                    onClick={e => {
+                        e.stopPropagation();
+                        this.presExpandDocumentClick();
+                    }}>
+                    <FontAwesomeIcon icon={this.rootDoc.presExpandInlineButton ? 'eye-slash' : 'eye'} onPointerDown={e => e.stopPropagation()} />
+                </div>
+            </Tooltip>
+        );
+        items.push(
+            <Tooltip key="trash" title={<div className="dash-tooltip">Remove from presentation</div>}>
+                <div className={'slideButton'} onClick={this.removeItem}>
+                    <FontAwesomeIcon icon={'trash'} onPointerDown={e => e.stopPropagation()} />
+                </div>
+            </Tooltip>
+        );
+        return items;
+    }
+
     @computed get mainItem() {
         const isSelected: boolean = this.selectedArray?.has(this.rootDoc) ? true : false;
         const isCurrent: boolean = this.presBox._itemIndex === this.indexInPres;
-        const toolbarWidth: number = this.toolbarWidth;
-        const showMore: boolean = this.toolbarWidth >= 300;
         const miniView: boolean = this.toolbarWidth <= 110;
         const presBox: Doc = this.presBox; //presBox
         const presBoxColor: string = StrCast(presBox._backgroundColor);
         const presColorBool: boolean = presBoxColor ? presBoxColor !== Colors.WHITE && presBoxColor !== 'transparent' : false;
-        const targetDoc: Doc = this.targetDoc;
         const activeItem: Doc = this.rootDoc;
 
         return (
@@ -484,6 +561,10 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 style={{
                     backgroundColor: presColorBool ? (isSelected ? 'rgba(250,250,250,0.3)' : 'transparent') : isSelected ? Colors.LIGHT_BLUE : 'transparent',
                     opacity: this._dragging ? 0.3 : 1,
+                    paddingLeft: NumCast(this.layoutDoc._xPadding, this.props.xPadding),
+                    paddingRight: NumCast(this.layoutDoc._xPadding, this.props.xPadding),
+                    paddingTop: NumCast(this.layoutDoc._yPadding, this.props.yPadding),
+                    paddingBottom: NumCast(this.layoutDoc._yPadding, this.props.yPadding),
                 }}
                 onClick={e => {
                     e.stopPropagation();
@@ -507,6 +588,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         ref={this._dragRef}
                         className={`presItem-slide ${isCurrent ? 'active' : ''}`}
                         style={{
+                            display: 'infline-block',
                             backgroundColor: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor),
                             //boxShadow: presBoxColor && presBoxColor !== 'white' && presBoxColor !== 'transparent' ? (isCurrent ? '0 0 0px 1.5px' + presBoxColor : undefined) : undefined,
                             border: presBoxColor && presBoxColor !== 'white' && presBoxColor !== 'transparent' ? (isCurrent ? presBoxColor + ' solid 2.5px' : undefined) : undefined,
@@ -514,8 +596,9 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         <div
                             className="presItem-name"
                             style={{
+                                display: 'inline-flex',
                                 pointerEvents: isSelected ? undefined : 'none',
-                                maxWidth: showMore ? toolbarWidth - 195 : toolbarWidth - 105,
+                                width: `calc(100% ${this.rootDoc.presExpandInlineButton ? '- 50%' : ''} - ${this.presButtons.length * 22}px`,
                                 cursor: isSelected ? 'text' : 'grab',
                             }}>
                             <div>{`${this.indexInPres + 1}.  `}</div>
@@ -523,56 +606,8 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         </div>
                         {/* <Tooltip title={<><div className="dash-tooltip">{"Movement speed"}</div></>}><div className="presItem-time" style={{ display: showMore ? "block" : "none" }}>{this.transition}</div></Tooltip> */}
                         {/* <Tooltip title={<><div className="dash-tooltip">{"Duration"}</div></>}><div className="presItem-time" style={{ display: showMore ? "block" : "none" }}>{this.duration}</div></Tooltip> */}
-                        <div className="presItem-slideButtons">
-                            <Tooltip title={<div className="dash-tooltip">Update captured doc layout</div>}>
-                                <div className="slideButton" onClick={() => this.updateCapturedContainerLayout(targetDoc, activeItem)} style={{ fontWeight: 700, display: activeItem.presPinLayout ? 'flex' : 'none' }}>
-                                    L
-                                </div>
-                            </Tooltip>
-                            <Tooltip title={<div className="dash-tooltip">Update captured doc content</div>}>
-                                <div className="slideButton" onClick={() => this.updateCapturedViewContents(targetDoc, activeItem)} style={{ fontWeight: 700, display: activeItem.presPinData || activeItem.presPinView ? 'flex' : 'none' }}>
-                                    C
-                                </div>
-                            </Tooltip>
-                            {!Doc.noviceMode && (
-                                <Tooltip title={<div className="dash-tooltip">{this.recordingIsInOverlay ? 'Hide Recording' : `${PresElementBox.videoIsRecorded(activeItem) ? 'Show' : 'Start'} recording`}</div>}>
-                                    <div className="slideButton" onClick={e => (this.recordingIsInOverlay ? this.hideRecording(e, true) : this.startRecording(e, activeItem))} style={{ fontWeight: 700 }}>
-                                        <FontAwesomeIcon icon={`video${this.recordingIsInOverlay ? '-slash' : ''}`} onPointerDown={e => e.stopPropagation()} />
-                                    </div>
-                                </Tooltip>
-                            )}
-                            <Tooltip title={<div className="dash-tooltip">{activeItem.groupWithUp ? 'Ungroup' : 'Group with up'}</div>}>
-                                <div
-                                    className="slideButton"
-                                    onClick={() => (activeItem.groupWithUp = !activeItem.groupWithUp)}
-                                    style={{
-                                        display: this.indexInPres === 0 ? 'none' : '',
-                                        zIndex: 1000 - this.indexInPres,
-                                        fontWeight: 700,
-                                        backgroundColor: activeItem.groupWithUp ? (presColorBool ? presBoxColor : Colors.MEDIUM_BLUE) : undefined,
-                                        height: activeItem.groupWithUp ? 53 : 18,
-                                        transform: activeItem.groupWithUp ? 'translate(0, -17px)' : undefined,
-                                    }}>
-                                    <div style={{ transform: activeItem.groupWithUp ? 'rotate(180deg) translate(0, -17.5px)' : 'rotate(0deg)' }}>
-                                        <FontAwesomeIcon icon={'arrow-up'} onPointerDown={e => e.stopPropagation()} />
-                                    </div>
-                                </div>
-                            </Tooltip>
-                            <Tooltip title={<div className="dash-tooltip">{this.rootDoc.presExpandInlineButton ? 'Minimize' : 'Expand'}</div>}>
-                                <div
-                                    className="slideButton"
-                                    onClick={e => {
-                                        e.stopPropagation();
-                                        this.presExpandDocumentClick();
-                                    }}>
-                                    <FontAwesomeIcon icon={this.rootDoc.presExpandInlineButton ? 'eye-slash' : 'eye'} onPointerDown={e => e.stopPropagation()} />
-                                </div>
-                            </Tooltip>
-                            <Tooltip title={<div className="dash-tooltip">Remove from presentation</div>}>
-                                <div className={'slideButton'} onClick={this.removeItem}>
-                                    <FontAwesomeIcon icon={'trash'} onPointerDown={e => e.stopPropagation()} />
-                                </div>
-                            </Tooltip>
+                        <div className="presItem-slideButtons" style={{ position: 'absolute', right: 0 }}>
+                            {...this.presButtons}
                         </div>
                         {this.renderEmbeddedInline}
                     </div>
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 466b43287..fc43325fe 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -238,6 +238,9 @@ export class Doc extends RefField {
         Doc.UserDoc().activePage = val;
         DocServer.UPDATE_SERVER_CACHE();
     }
+    public static IsComicStyle(doc?: Doc) {
+        return doc && Doc.ActiveDashboard && !Doc.IsSystem(doc) && Doc.UserDoc().renderStyle === 'comic';
+    }
     public static get ActiveDashboard() {
         return DocCast(Doc.UserDoc().activeDashboard);
     }
-- 
cgit v1.2.3-70-g09d2

