aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/CollectionTreeView.tsx
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2023-04-05 22:44:03 -0400
committerbobzel <zzzman@gmail.com>2023-04-05 22:44:03 -0400
commit9b41da1af16b982ee8ac2fc09f2f8b5d67eac9fb (patch)
treebc3f57cd5b31fd453d272c925f6d5b728ab63bae /src/client/views/collections/CollectionTreeView.tsx
parent9dae453967183b294bf4f7444b948023a1d52d39 (diff)
parent8f7e99641f84ad15f34ba9e4a60b664ac93d2e5d (diff)
Merge branch 'master' into data-visualization-view-naafi
Diffstat (limited to 'src/client/views/collections/CollectionTreeView.tsx')
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx157
1 files changed, 90 insertions, 67 deletions
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index dce792d19..4a11e8f0b 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -7,7 +7,7 @@ import { listSpec } from '../../../fields/Schema';
import { ScriptField } from '../../../fields/ScriptField';
import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
import { TraceMobx } from '../../../fields/util';
-import { emptyFunction, OmitKeys, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnOne, returnTrue } from '../../../Utils';
+import { emptyFunction, returnAll, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnNone, returnOne, returnTrue, returnZero } from '../../../Utils';
import { DocUtils } from '../../documents/Documents';
import { DocumentManager } from '../../util/DocumentManager';
import { DragManager, dropActionType } from '../../util/DragManager';
@@ -38,8 +38,8 @@ export type collectionTreeViewProps = {
onCheckedClick?: () => ScriptField;
onChildClick?: () => ScriptField;
// TODO: [AL] add these fields
- AddToMap?: (treeViewDoc: Doc, index: number[]) => Doc[];
- RemFromMap?: (treeViewDoc: Doc, index: number[]) => Doc[];
+ AddToMap?: (treeViewDoc: Doc, index: number[]) => void;
+ RemFromMap?: (treeViewDoc: Doc, index: number[]) => void;
hierarchyIndex?: number[];
};
@@ -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;
@@ -83,7 +82,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;
@@ -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(),
@@ -111,9 +113,9 @@ 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);
+ !this.props.dontRegisterView && this.props.setHeight?.(bodyHeight + titleHeight);
}
};
unobserveHeight = (ref: any) => {
@@ -147,6 +149,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;
@@ -195,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 (
@@ -256,11 +258,14 @@ 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);
+ @observable _renderCount = 1;
@computed get treeViewElements() {
TraceMobx();
const dropAction = StrCast(this.doc.childDropAction) as dropActionType;
const addDoc = (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => this.addDoc(doc, relativeTo, before);
const moveDoc = (d: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => this.props.moveDocument?.(d, target, addDoc) || false;
+ if (this._renderCount < this.treeChildren.length) setTimeout(action(() => (this._renderCount = Math.min(this.treeChildren.length, this._renderCount + 20))));
return TreeView.GetChildElements(
this.treeChildren,
this,
@@ -275,11 +280,11 @@ 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,
- () => this.props.treeViewHideHeaderFields || BoolCast(this.doc.treeViewHideHeaderFields),
+ this.headerFields,
[],
this.props.onCheckedClick,
this.onChildClick,
@@ -293,12 +298,17 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
//TODO: [AL] add these
this.props.AddToMap,
this.props.RemFromMap,
- this.props.hierarchyIndex
+ this.props.hierarchyIndex,
+ this._renderCount
);
}
@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 ? { marginLeft: this.marginX(), paddingTop: this.marginTop() } : {}}>
{this.outlineMode ? this.documentTitle : this.editableTitle}
</div>
);
@@ -366,78 +376,91 @@ 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;
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;
- contentFunc = () => {
+ @observable _headerHeight = 0;
+ @computed get content() {
const background = () => this.props.styleProvider?.(this.doc, this.props, StyleProp.BackgroundColor);
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}
+ return (
+ <div style={{ display: 'flex', flexDirection: 'column', height: '100%', pointerEvents: 'all' }}>
+ {!this.buttonMenu && !this.noviceExplainer ? null : (
+ <div className="documentButtonMenu" ref={action((r: HTMLDivElement | null) => r && (this._headerHeight = Number(getComputedStyle(r).height.replace(/px/, ''))))}>
+ {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 ? { marginLeft: 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(),
+ marginLeft: `${this.marginX()}px`,
+ 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>,
- ];
- };
+ </div>
+ );
+ }
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
+ {...this.props}
+ setContentView={emptyFunction}
+ NativeWidth={returnZero}
+ NativeHeight={returnZero}
+ pointerEvents={SnappingManager.GetIsDragging() ? returnAll : returnNone}
+ 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.content}
+ </CollectionFreeFormView>
+ ) : (
+ this.content
+ )}
+ </div>
);
}
}