aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/TreeView.tsx
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2022-07-08 00:17:26 -0400
committerbobzel <zzzman@gmail.com>2022-07-08 00:17:26 -0400
commit146f8622d5bac2edc6b09f57c173bd057dfbcfad (patch)
treef871089c438a476543ca96bac163c0532b9557c7 /src/client/views/collections/TreeView.tsx
parentb7e66da6b23cdb41c127000dfe13843d35f7d0cc (diff)
restructured currentUserUtils to avoid having import cycles.
Diffstat (limited to 'src/client/views/collections/TreeView.tsx')
-rw-r--r--src/client/views/collections/TreeView.tsx1168
1 files changed, 689 insertions, 479 deletions
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 704b8989a..eb5faf4e1 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -1,7 +1,7 @@
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction } from "mobx";
-import { observer } from "mobx-react";
+import { action, computed, IReactionDisposer, observable, ObservableMap, reaction } from 'mobx';
+import { observer } from 'mobx-react';
import { DataSym, Doc, DocListCast, DocListCastOrNull, Field, HeightSym, Opt, StrListCast, WidthSym } from '../../../fields/Doc';
import { Id } from '../../../fields/FieldSymbols';
import { List } from '../../../fields/List';
@@ -12,26 +12,25 @@ import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Ty
import { TraceMobx } from '../../../fields/util';
import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnOne, returnTrue, simulateMouseClick, Utils } from '../../../Utils';
import { Docs, DocUtils } from '../../documents/Documents';
-import { DocumentType } from "../../documents/DocumentTypes";
-import { CurrentUserUtils } from '../../util/CurrentUserUtils';
-import { DocumentManager, DocFocusOrOpen } from '../../util/DocumentManager';
-import { DragManager, dropActionType } from "../../util/DragManager";
+import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
+import { DocumentManager } from '../../util/DocumentManager';
+import { DragManager, dropActionType } from '../../util/DragManager';
import { SelectionManager } from '../../util/SelectionManager';
import { SnappingManager } from '../../util/SnappingManager';
import { Transform } from '../../util/Transform';
import { undoBatch, UndoManager } from '../../util/UndoManager';
-import { EditableView } from "../EditableView";
+import { EditableView } from '../EditableView';
import { TREE_BULLET_WIDTH } from '../global/globalCssVariables.scss';
import { DocumentView, DocumentViewInternal, DocumentViewProps, StyleProviderFunc } from '../nodes/DocumentView';
+import { FieldViewProps } from '../nodes/FieldView';
import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
import { RichTextMenu } from '../nodes/formattedText/RichTextMenu';
+import { KeyValueBox } from '../nodes/KeyValueBox';
import { StyleProp } from '../StyleProvider';
import { CollectionTreeView, TreeViewType } from './CollectionTreeView';
-import { CollectionView, CollectionViewType } from './CollectionView';
-import "./TreeView.scss";
-import React = require("react");
-import { KeyValueBox } from '../nodes/KeyValueBox';
-import { FieldViewProps } from '../nodes/FieldView';
+import { CollectionView } from './CollectionView';
+import './TreeView.scss';
+import React = require('react');
export interface TreeViewProps {
treeView: CollectionTreeView;
@@ -55,7 +54,7 @@ export interface TreeViewProps {
indentDocument?: (editTitle: boolean) => void;
outdentDocument?: (editTitle: boolean) => void;
ScreenToLocalTransform: () => Transform;
- contextMenuItems: { script: ScriptField, filter: ScriptField, icon: string, label: string }[];
+ contextMenuItems: { script: ScriptField; filter: ScriptField; icon: string; label: string }[];
dontRegisterView?: boolean;
styleProvider?: StyleProviderFunc | undefined;
treeViewHideHeaderFields: () => boolean;
@@ -70,24 +69,26 @@ export interface TreeViewProps {
hierarchyIndex?: number[];
}
-const treeBulletWidth = function () { return Number(TREE_BULLET_WIDTH.replace("px", "")); };
+const treeBulletWidth = function () {
+ return Number(TREE_BULLET_WIDTH.replace('px', ''));
+};
export enum TreeSort {
- Up = "up",
- Down = "down",
- Zindex = "z",
- None = "none"
+ Up = 'up',
+ Down = 'down',
+ Zindex = 'z',
+ None = 'none',
}
/**
* Renders a treeView of a collection of documents
- *
+ *
* special fields:
* treeViewOpen : flag denoting whether the documents sub-tree (contents) is visible or hidden
* treeViewExpandedView : name of field whose contents are being displayed as the document's subtree
*/
@observer
export class TreeView extends React.Component<TreeViewProps> {
- static _editTitleOnLoad: Opt<{ id: string, parent: TreeView | CollectionTreeView | undefined }>;
+ static _editTitleOnLoad: Opt<{ id: string; parent: TreeView | CollectionTreeView | undefined }>;
static _openTitleScript: Opt<ScriptField | undefined>;
static _openLevelScript: Opt<ScriptField | undefined>;
private _header: React.RefObject<HTMLDivElement> = React.createRef();
@@ -98,7 +99,9 @@ export class TreeView extends React.Component<TreeViewProps> {
private _openScript: (() => ScriptField) | undefined;
private _treedropDisposer?: DragManager.DragDropDisposer;
- get treeViewOpenIsTransient() { return this.props.treeView.doc.treeViewOpenIsTransient || Doc.IsPrototype(this.doc); }
+ get treeViewOpenIsTransient() {
+ return this.props.treeView.doc.treeViewOpenIsTransient || Doc.IsPrototype(this.doc);
+ }
set treeViewOpen(c: boolean) {
if (this.treeViewOpenIsTransient) this._transientOpenState = c;
else {
@@ -109,26 +112,61 @@ export class TreeView extends React.Component<TreeViewProps> {
@observable _transientOpenState = false; // override of the treeViewOpen field allowing the display state to be independent of the document's state
@observable _editTitle: boolean = false;
@observable _dref: DocumentView | undefined | null;
- get displayName() { return "TreeView(" + this.props.document.title + ")"; } // this makes mobx trace() statements more descriptive
+ get displayName() {
+ return 'TreeView(' + this.props.document.title + ')';
+ } // this makes mobx trace() statements more descriptive
get defaultExpandedView() {
- return this.doc.viewType === CollectionViewType.Docking ? this.fieldKey :
- this.props.treeView.dashboardMode ? this.fieldKey :
- this.props.treeView.fileSysMode ? (this.doc.isFolder ? this.fieldKey : "aliases") : // for displaying
- this.props.treeView.outlineMode || this.childDocs ? this.fieldKey : Doc.noviceMode ? "layout" : StrCast(this.props.treeView.doc.treeViewExpandedView, "fields");
- }
-
- @computed get doc() { return this.props.document; }
- @computed get treeViewOpen() { return (!this.treeViewOpenIsTransient && Doc.GetT(this.doc, "treeViewOpen", "boolean", true)) || this._transientOpenState; }
- @computed get treeViewExpandedView() { return this.validExpandViewTypes.includes(StrCast(this.doc.treeViewExpandedView)) ? StrCast(this.doc.treeViewExpandedView) : this.defaultExpandedView; }
- @computed get MAX_EMBED_HEIGHT() { return NumCast(this.props.containerCollection.maxEmbedHeight, 200); }
- @computed get dataDoc() { return this.props.document.treeViewChildrenOnRoot ? this.doc : this.doc[DataSym]; }
- @computed get layoutDoc() { return Doc.Layout(this.doc); }
- @computed get fieldKey() { return StrCast(this.doc._treeViewFieldKey, Doc.LayoutFieldKey(this.doc)); }
- @computed get childDocs() { return this.childDocList(this.fieldKey); }
- @computed get childLinks() { return this.childDocList("links"); }
- @computed get childAliases() { return this.childDocList("aliases"); }
- @computed get childAnnos() { return this.childDocList(this.fieldKey + "-annotations"); }
- @computed get selected() { return SelectionManager.IsSelected(this._docRef); }
+ return this.doc.viewType === CollectionViewType.Docking
+ ? this.fieldKey
+ : this.props.treeView.dashboardMode
+ ? this.fieldKey
+ : this.props.treeView.fileSysMode
+ ? this.doc.isFolder
+ ? this.fieldKey
+ : 'aliases' // for displaying
+ : this.props.treeView.outlineMode || this.childDocs
+ ? this.fieldKey
+ : Doc.noviceMode
+ ? 'layout'
+ : StrCast(this.props.treeView.doc.treeViewExpandedView, 'fields');
+ }
+
+ @computed get doc() {
+ return this.props.document;
+ }
+ @computed get treeViewOpen() {
+ return (!this.treeViewOpenIsTransient && Doc.GetT(this.doc, 'treeViewOpen', 'boolean', true)) || this._transientOpenState;
+ }
+ @computed get treeViewExpandedView() {
+ return this.validExpandViewTypes.includes(StrCast(this.doc.treeViewExpandedView)) ? StrCast(this.doc.treeViewExpandedView) : this.defaultExpandedView;
+ }
+ @computed get MAX_EMBED_HEIGHT() {
+ return NumCast(this.props.containerCollection.maxEmbedHeight, 200);
+ }
+ @computed get dataDoc() {
+ return this.props.document.treeViewChildrenOnRoot ? this.doc : this.doc[DataSym];
+ }
+ @computed get layoutDoc() {
+ return Doc.Layout(this.doc);
+ }
+ @computed get fieldKey() {
+ return StrCast(this.doc._treeViewFieldKey, Doc.LayoutFieldKey(this.doc));
+ }
+ @computed get childDocs() {
+ return this.childDocList(this.fieldKey);
+ }
+ @computed get childLinks() {
+ return this.childDocList('links');
+ }
+ @computed get childAliases() {
+ return this.childDocList('aliases');
+ }
+ @computed get childAnnos() {
+ return this.childDocList(this.fieldKey + '-annotations');
+ }
+ @computed get selected() {
+ return SelectionManager.IsSelected(this._docRef);
+ }
// SelectionManager.Views().lastElement()?.props.Document === this.props.document; }
@observable _presTimer!: NodeJS.Timeout;
@@ -136,64 +174,76 @@ export class TreeView extends React.Component<TreeViewProps> {
@observable _selectedArray: ObservableMap = new ObservableMap<Doc, any>();
// the selected item's index
- @computed get itemIndex() { return NumCast(this.doc._itemIndex); }
- // the item that's active
- @computed get activeItem() { return this.childDocs ? Cast(this.childDocs[NumCast(this.doc._itemIndex)], Doc, null) : undefined; }
- @computed get targetDoc() { return Cast(this.activeItem?.presentationTargetDoc, Doc, null); }
+ @computed get itemIndex() {
+ return NumCast(this.doc._itemIndex);
+ }
+ // the item that's active
+ @computed get activeItem() {
+ return this.childDocs ? Cast(this.childDocs[NumCast(this.doc._itemIndex)], Doc, null) : undefined;
+ }
+ @computed get targetDoc() {
+ return Cast(this.activeItem?.presentationTargetDoc, Doc, null);
+ }
childDocList(field: string) {
const layout = Cast(Doc.LayoutField(this.doc), Doc, null);
- return (this.props.dataDoc ? DocListCastOrNull(this.props.dataDoc[field]) : undefined) || // if there's a data doc for an expanded template, use it's data field
+ return (
+ (this.props.dataDoc ? DocListCastOrNull(this.props.dataDoc[field]) : undefined) || // if there's a data doc for an expanded template, use it's data field
(layout ? DocListCastOrNull(layout[field]) : undefined) || // else if there's a layout doc, display it's fields
- DocListCastOrNull(this.doc[field]); // otherwise use the document's data field
+ DocListCastOrNull(this.doc[field])
+ ); // otherwise use the document's data field
}
@undoBatch move = (doc: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => {
- if (this.doc !== target && addDoc !== returnFalse) { // bcz: this should all be running in a Temp undo batch instead of hackily testing for returnFalse
+ if (this.doc !== target && addDoc !== returnFalse) {
+ // bcz: this should all be running in a Temp undo batch instead of hackily testing for returnFalse
if (this.props.removeDoc?.(doc) === true) {
return addDoc(doc);
}
}
return false;
- }
+ };
@undoBatch @action remove = (doc: Doc | Doc[], key: string) => {
this.props.treeView.props.select(false);
const ind = this.dataDoc[key].indexOf(doc);
const res = (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && Doc.RemoveDocFromList(this.dataDoc, key, doc), true);
res && ind > 0 && DocumentManager.Instance.getDocumentView(this.dataDoc[key][ind - 1], this.props.treeView.props.CollectionView)?.select(false);
return res;
- }
+ };
@action setEditTitle = (docView?: DocumentView) => {
this._selDisposer?.();
if (!docView) {
this._editTitle = false;
- }
- else if (docView.isSelected()) {
+ } else if (docView.isSelected()) {
const doc = docView.Document;
SelectionManager.SelectSchemaViewDoc(doc);
this._editTitle = true;
- this._selDisposer = reaction(() => SelectionManager.SelectedSchemaDoc(), seldoc => seldoc !== doc && this.setEditTitle(undefined));
+ this._selDisposer = reaction(
+ () => SelectionManager.SelectedSchemaDoc(),
+ seldoc => seldoc !== doc && this.setEditTitle(undefined)
+ );
} else {
docView.select(false);
}
- }
+ };
@action
openLevel = (docView: DocumentView) => {
if (this.props.document.isFolder || Doc.IsSystem(this.props.document)) {
this.treeViewOpen = !this.treeViewOpen;
} else {
// choose an appropriate alias or make one. --- choose the first alias that (1) user owns, (2) has no context field ... otherwise make a new alias
- const bestAlias = docView.props.Document.author === Doc.CurrentUserEmail && !Doc.IsPrototype(docView.props.Document) ? docView.props.Document : DocListCast(this.props.document.aliases).find(doc => !doc.context && doc.author === Doc.CurrentUserEmail);
+ const bestAlias =
+ docView.props.Document.author === Doc.CurrentUserEmail && !Doc.IsPrototype(docView.props.Document) ? docView.props.Document : DocListCast(this.props.document.aliases).find(doc => !doc.context && doc.author === Doc.CurrentUserEmail);
const nextBestAlias = DocListCast(this.props.document.aliases).find(doc => doc.author === Doc.CurrentUserEmail);
- this.props.addDocTab(bestAlias ?? nextBestAlias ?? Doc.MakeAlias(this.props.document), "lightbox");
+ this.props.addDocTab(bestAlias ?? nextBestAlias ?? Doc.MakeAlias(this.props.document), 'lightbox');
}
- }
+ };
constructor(props: any) {
super(props);
if (!TreeView._openLevelScript) {
- TreeView._openTitleScript = ScriptField.MakeScript("scriptContext.setEditTitle(documentView)", { scriptContext: "any", documentView: "any" });
- TreeView._openLevelScript = ScriptField.MakeScript(`scriptContext.openLevel(documentView)`, { scriptContext: "any", documentView: "any" });
+ TreeView._openTitleScript = ScriptField.MakeScript('scriptContext.setEditTitle(documentView)', { scriptContext: 'any', documentView: 'any' });
+ TreeView._openLevelScript = ScriptField.MakeScript(`scriptContext.openLevel(documentView)`, { scriptContext: 'any', documentView: 'any' });
}
this._openScript = Doc.IsSystem(this.props.document) ? undefined : () => TreeView._openLevelScript!;
this._editTitleScript = Doc.IsSystem(this.props.document) ? () => TreeView._openLevelScript! : () => TreeView._openTitleScript!;
@@ -202,16 +252,16 @@ export class TreeView extends React.Component<TreeViewProps> {
_treeEle: any;
protected createTreeDropTarget = (ele: HTMLDivElement) => {
this._treedropDisposer?.();
- ele && (this._treedropDisposer = DragManager.MakeDropTarget(ele, this.treeDrop.bind(this), undefined, this.preTreeDrop.bind(this)), this.doc);
+ ele && ((this._treedropDisposer = DragManager.MakeDropTarget(ele, this.treeDrop.bind(this), undefined, this.preTreeDrop.bind(this))), this.doc);
if (this._treeEle) this.props.unobserveHeight(this._treeEle);
- this.props.observeHeight(this._treeEle = ele);
- }
+ this.props.observeHeight((this._treeEle = ele));
+ };
componentWillUnmount() {
this._selDisposer?.();
this._treeEle && this.props.unobserveHeight(this._treeEle);
- document.removeEventListener("pointermove", this.onDragMove, true);
- document.removeEventListener("pointermove", this.onDragUp, true);
+ document.removeEventListener('pointermove', this.onDragMove, true);
+ document.removeEventListener('pointermove', this.onDragUp, true);
// TODO: [AL] add these
this.props.hierarchyIndex !== undefined && this.props.RemFromMap?.(this.doc, this.props.hierarchyIndex);
}
@@ -225,49 +275,60 @@ export class TreeView extends React.Component<TreeViewProps> {
}
onDragUp = (e: PointerEvent) => {
- document.removeEventListener("pointerup", this.onDragUp, true);
- document.removeEventListener("pointermove", this.onDragMove, true);
- }
+ document.removeEventListener('pointerup', this.onDragUp, true);
+ document.removeEventListener('pointermove', this.onDragMove, true);
+ };
onPointerEnter = (e: React.PointerEvent): void => {
this.props.isContentActive(true) && Doc.BrushDoc(this.dataDoc);
if (e.buttons === 1 && SnappingManager.GetIsDragging()) {
- this._header.current!.className = "treeView-header";
- document.removeEventListener("pointermove", this.onDragMove, true);
- document.removeEventListener("pointerup", this.onDragUp, true);
- document.addEventListener("pointermove", this.onDragMove, true);
- document.addEventListener("pointerup", this.onDragUp, true);
+ this._header.current!.className = 'treeView-header';
+ document.removeEventListener('pointermove', this.onDragMove, true);
+ document.removeEventListener('pointerup', this.onDragUp, true);
+ document.addEventListener('pointermove', this.onDragMove, true);
+ document.addEventListener('pointerup', this.onDragUp, true);
}
- }
+ };
onPointerLeave = (e: React.PointerEvent): void => {
Doc.UnBrushDoc(this.dataDoc);
- if (this._header.current?.className !== "treeView-header-editing") {
- this._header.current!.className = "treeView-header";
+ if (this._header.current?.className !== 'treeView-header-editing') {
+ this._header.current!.className = 'treeView-header';
}
- document.removeEventListener("pointerup", this.onDragUp, true);
- document.removeEventListener("pointermove", this.onDragMove, true);
- }
+ document.removeEventListener('pointerup', this.onDragUp, true);
+ document.removeEventListener('pointermove', this.onDragMove, true);
+ };
onDragMove = (e: PointerEvent): void => {
Doc.UnBrushDoc(this.dataDoc);
const pt = [e.clientX, e.clientY];
const rect = this._header.current!.getBoundingClientRect();
const before = pt[1] < rect.top + rect.height / 2;
- const inside = pt[0] > Math.min(rect.left + 75, rect.left + rect.width * .75) || (!before && this.treeViewOpen && this.childDocList.length);
- this._header.current!.className = "treeView-header";
+ const inside = pt[0] > Math.min(rect.left + 75, rect.left + rect.width * 0.75) || (!before && this.treeViewOpen && this.childDocList.length);
+ this._header.current!.className = 'treeView-header';
if (!this.props.treeView.outlineMode || DragManager.DocDragData?.treeViewDoc === this.props.treeView.rootDoc) {
- if (inside) this._header.current!.className += " treeView-header-inside";
- else if (before) this._header.current!.className += " treeView-header-above";
- else if (!before) this._header.current!.className += " treeView-header-below";
+ if (inside) this._header.current!.className += ' treeView-header-inside';
+ else if (before) this._header.current!.className += ' treeView-header-above';
+ else if (!before) this._header.current!.className += ' treeView-header-below';
}
e.stopPropagation();
- }
+ };
public static makeTextBullet() {
- const bullet = Docs.Create.TextDocument("-text-", {
- layout: CollectionView.LayoutString("data"),
- title: "-title-",
- treeViewExpandedViewLock: true, treeViewExpandedView: "data",
- _viewType: CollectionViewType.Tree, hideLinkButton: true, _showSidebar: true, treeViewType: TreeViewType.outline,
- x: 0, y: 0, _xMargin: 0, _yMargin: 0, _autoHeight: true, _singleLine: true, _width: 1000, _height: 10
+ const bullet = Docs.Create.TextDocument('-text-', {
+ layout: CollectionView.LayoutString('data'),
+ title: '-title-',
+ treeViewExpandedViewLock: true,
+ treeViewExpandedView: 'data',
+ _viewType: CollectionViewType.Tree,
+ hideLinkButton: true,
+ _showSidebar: true,
+ treeViewType: TreeViewType.outline,
+ x: 0,
+ y: 0,
+ _xMargin: 0,
+ _yMargin: 0,
+ _autoHeight: true,
+ _singleLine: true,
+ _width: 1000,
+ _height: 10,
});
Doc.GetProto(bullet).title = ComputedField.MakeFunction('self.text?.Text');
Doc.GetProto(bullet).data = new List<Doc>([]);
@@ -279,19 +340,19 @@ export class TreeView extends React.Component<TreeViewProps> {
const bullet = TreeView.makeTextBullet();
TreeView._editTitleOnLoad = { id: bullet[Id], parent: this };
return this.props.addDocument(bullet);
- }
+ };
makeFolder = () => {
- const folder = Docs.Create.TreeDocument([], { title: "Untitled folder", _stayInCollection: true, isFolder: true });
+ const folder = Docs.Create.TreeDocument([], { title: 'Untitled folder', _stayInCollection: true, isFolder: true });
TreeView._editTitleOnLoad = { id: folder[Id], parent: this.props.parentTreeView };
return this.props.addDocument(folder);
- }
+ };
deleteItem = () => this.props.removeDoc?.(this.doc);
preTreeDrop = (e: Event, de: DragManager.DropEvent, targetAction: dropActionType) => {
const dragData = de.complete.docDragData;
- dragData && (dragData.dropAction = this.props.treeView.props.Document === dragData.treeViewDoc ? "same" : dragData.dropAction);
- }
+ dragData && (dragData.dropAction = this.props.treeView.props.Document === dragData.treeViewDoc ? 'same' : dragData.dropAction);
+ };
@undoBatch
treeDrop = (e: Event, de: DragManager.DropEvent) => {
@@ -299,11 +360,11 @@ export class TreeView extends React.Component<TreeViewProps> {
if (!this._header.current) return;
const rect = this._header.current.getBoundingClientRect();
const before = pt[1] < rect.top + rect.height / 2;
- const inside = this.props.treeView.fileSysMode && !this.doc.isFolder ? false : pt[0] > Math.min(rect.left + 75, rect.left + rect.width * .75) || (!before && this.treeViewOpen && this.childDocList.length);
+ const inside = this.props.treeView.fileSysMode && !this.doc.isFolder ? false : pt[0] > Math.min(rect.left + 75, rect.left + rect.width * 0.75) || (!before && this.treeViewOpen && this.childDocList.length);
if (de.complete.linkDragData) {
const sourceDoc = de.complete.linkDragData.linkSourceGetAnchor();
const destDoc = this.doc;
- DocUtils.MakeLink({ doc: sourceDoc }, { doc: destDoc }, "tree link", "");
+ DocUtils.MakeLink({ doc: sourceDoc }, { doc: destDoc }, 'tree link', '');
e.stopPropagation();
}
const docDragData = de.complete.docDragData;
@@ -313,22 +374,16 @@ export class TreeView extends React.Component<TreeViewProps> {
e.stopPropagation();
}
}
- }
+ };
dropDocuments(droppedDocuments: Doc[], before: boolean, inside: number | boolean, dropAction: dropActionType, moveDocument: DragManager.MoveFunction | undefined, forceAdd: boolean) {
const parentAddDoc = (doc: Doc | Doc[]) => this.props.addDocument(doc, undefined, before);
- const canAdd = (!this.props.treeView.outlineMode && !StrCast((inside ? this.props.document : this.props.containerCollection)?.freezeChildren).includes("add")) || forceAdd;
- const localAdd = (doc: Doc) => Doc.AddDocToList(this.dataDoc, this.fieldKey, doc) && ((doc.context = this.doc.context) || true) ? true : false;
- const addDoc = !inside ? parentAddDoc :
- (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && localAdd(doc), true as boolean);
- const move = (!dropAction || dropAction === "proto" || dropAction === "move" || dropAction === "same") && moveDocument;
+ const canAdd = (!this.props.treeView.outlineMode && !StrCast((inside ? this.props.document : this.props.containerCollection)?.freezeChildren).includes('add')) || forceAdd;
+ const localAdd = (doc: Doc) => (Doc.AddDocToList(this.dataDoc, this.fieldKey, doc) && ((doc.context = this.doc.context) || true) ? true : false);
+ const addDoc = !inside ? parentAddDoc : (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && localAdd(doc), true as boolean);
+ const move = (!dropAction || dropAction === 'proto' || dropAction === 'move' || dropAction === 'same') && moveDocument;
if (canAdd) {
- return UndoManager.RunInTempBatch(() => droppedDocuments.reduce((added, d) =>
- (move ?
- move(d, undefined, addDoc) || (dropAction === "proto" ? addDoc(d) : false)
- :
- addDoc(d)) || added,
- false));
+ return UndoManager.RunInTempBatch(() => droppedDocuments.reduce((added, d) => (move ? move(d, undefined, addDoc) || (dropAction === 'proto' ? addDoc(d) : false) : addDoc(d)) || added, false));
}
return false;
}
@@ -339,7 +394,7 @@ export class TreeView extends React.Component<TreeViewProps> {
const outerXf = Utils.GetScreenTransform(this.props.treeView.MainEle());
const offset = this.props.ScreenToLocalTransform().transformDirection(outerXf.translateX - translateX, outerXf.translateY - translateY);
return this.props.ScreenToLocalTransform().translate(offset[0], offset[1]);
- }
+ };
docTransform = () => this.refTransform(this._dref?.ContentRef?.current);
getTransform = () => this.refTransform(this._tref.current);
docWidth = () => {
@@ -348,22 +403,25 @@ export class TreeView extends React.Component<TreeViewProps> {
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.scaling?.() || 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);
- })()));
- }
+ 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;
+ })()
+ )
+ );
+ };
@computed get expandedField() {
const ids: { [key: string]: string } = {};
@@ -372,11 +430,11 @@ export class TreeView extends React.Component<TreeViewProps> {
doc && Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key));
for (const key of Object.keys(ids).slice().sort()) {
- if (this.props.skipFields?.includes(key) || key === "title" || key === "treeViewOpen") continue;
+ if (this.props.skipFields?.includes(key) || key === 'title' || key === 'treeViewOpen') continue;
const contents = doc[key];
let contentElement: (JSX.Element | null)[] | JSX.Element = [];
- if (contents instanceof Doc || (Cast(contents, listSpec(Doc)) && (Cast(contents, listSpec(Doc))!.length && Cast(contents, listSpec(Doc))![0] instanceof Doc))) {
+ if (contents instanceof Doc || (Cast(contents, listSpec(Doc)) && Cast(contents, listSpec(Doc))!.length && Cast(contents, listSpec(Doc))![0] instanceof Doc)) {
const remDoc = (doc: Doc | Doc[]) => this.remove(doc, key);
const localAdd = (doc: Doc, addBefore?: Doc, before?: boolean) => {
const added = Doc.AddDocToList(this.dataDoc, key, doc, addBefore, before, false, true);
@@ -384,74 +442,109 @@ export class TreeView extends React.Component<TreeViewProps> {
return added;
};
const addDoc = (doc: Doc | Doc[], addBefore?: Doc, before?: boolean) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && localAdd(doc, addBefore, before), true);
- contentElement = TreeView.GetChildElements(contents instanceof Doc ? [contents] : DocListCast(contents),
- this.props.treeView, this, doc, undefined, this.props.containerCollection, this.props.prevSibling, addDoc, remDoc, this.move,
- this.props.dropAction, this.props.addDocTab, this.titleStyleProvider, this.props.ScreenToLocalTransform, this.props.isContentActive,
- this.props.panelWidth, this.props.renderDepth, this.props.treeViewHideHeaderFields,
- [...this.props.renderedIds, doc[Id]], this.props.onCheckedClick, this.props.onChildClick, this.props.skipFields, false, this.props.whenChildContentsActiveChanged,
- this.props.dontRegisterView, emptyFunction, emptyFunction, this.childContextMenuItems(),
+ contentElement = TreeView.GetChildElements(
+ contents instanceof Doc ? [contents] : DocListCast(contents),
+ this.props.treeView,
+ this,
+ doc,
+ undefined,
+ this.props.containerCollection,
+ this.props.prevSibling,
+ addDoc,
+ remDoc,
+ this.move,
+ this.props.dropAction,
+ this.props.addDocTab,
+ this.titleStyleProvider,
+ this.props.ScreenToLocalTransform,
+ this.props.isContentActive,
+ this.props.panelWidth,
+ this.props.renderDepth,
+ this.props.treeViewHideHeaderFields,
+ [...this.props.renderedIds, doc[Id]],
+ this.props.onCheckedClick,
+ this.props.onChildClick,
+ this.props.skipFields,
+ false,
+ this.props.whenChildContentsActiveChanged,
+ this.props.dontRegisterView,
+ emptyFunction,
+ emptyFunction,
+ this.childContextMenuItems(),
// TODO: [AL] Add these
this.props.AddToMap,
this.props.RemFromMap,
this.props.hierarchyIndex
);
} else {
- contentElement = <EditableView key="editableView"
- contents={contents !== undefined ? Field.toString(contents as Field) : "null"}
- height={13}
- fontSize={12}
- GetValue={() => Field.toKeyValueString(doc, key)}
- SetValue={(value: string) => KeyValueBox.SetField(doc, key, value, true)} />;
+ contentElement = (
+ <EditableView
+ key="editableView"
+ contents={contents !== undefined ? Field.toString(contents as Field) : 'null'}
+ height={13}
+ fontSize={12}
+ GetValue={() => Field.toKeyValueString(doc, key)}
+ SetValue={(value: string) => KeyValueBox.SetField(doc, key, value, true)}
+ />
+ );
}
- rows.push(<div style={{ display: "flex" }} key={key}>
- <span style={{ fontWeight: "bold" }}>{key + ":"}</span>
- &nbsp;
- {contentElement}
- </div>);
+ rows.push(
+ <div style={{ display: 'flex' }} key={key}>
+ <span style={{ fontWeight: 'bold' }}>{key + ':'}</span>
+ &nbsp;
+ {contentElement}
+ </div>
+ );
}
- rows.push(<div style={{ display: "flex" }} key={"newKeyValue"}>
- <EditableView
- key="editableView"
- contents={"+key:value"}
- height={13}
- fontSize={12}
- GetValue={returnEmptyString}
- SetValue={value => value.indexOf(":") !== -1 && KeyValueBox.SetField(doc, value.substring(0, value.indexOf(":")), value.substring(value.indexOf(":") + 1, value.length), true)} />
- </div>);
+ rows.push(
+ <div style={{ display: 'flex' }} key={'newKeyValue'}>
+ <EditableView
+ key="editableView"
+ contents={'+key:value'}
+ height={13}
+ fontSize={12}
+ GetValue={returnEmptyString}
+ SetValue={value => value.indexOf(':') !== -1 && KeyValueBox.SetField(doc, value.substring(0, value.indexOf(':')), value.substring(value.indexOf(':') + 1, value.length), true)}
+ />
+ </div>
+ );
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.scaling?.() || 1);
- }
+ 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.scaling?.() || 1);
+ };
rtfHeight = () => {
- const layout = (temp => temp && Doc.expandTemplateLayout(temp, this.props.document, ""))(this.props.treeView.props.childLayoutTemplate?.()) || this.layoutDoc;
+ 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();
- }
+ 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();
- }
+ return docAspect > aspect ? this.docHeight() * aspect : this.docWidth();
+ };
@computed get renderContent() {
TraceMobx();
const expandKey = this.treeViewExpandedView;
- const sortings = this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewSortings) as { [key: string]: { color: string, label: string } };
- if (["links", "annotations", "aliases", this.fieldKey].includes(expandKey)) {
+ const sortings = this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewSortings) as { [key: string]: { color: string; label: string } };
+ if (['links', 'annotations', 'aliases', this.fieldKey].includes(expandKey)) {
const sorting = StrCast(this.doc.treeViewSortCriterion, TreeSort.None);
const sortKeys = Object.keys(sortings);
- const curSortIndex = Math.max(0, sortKeys.findIndex(val => val === sorting));
- const key = (expandKey === "annotations" ? `${this.fieldKey}-` : "") + expandKey;
+ const curSortIndex = Math.max(
+ 0,
+ sortKeys.findIndex(val => val === sorting)
+ );
+ const key = (expandKey === 'annotations' ? `${this.fieldKey}-` : '') + expandKey;
const remDoc = (doc: Doc | Doc[]) => this.remove(doc, key);
const localAdd = (doc: Doc, addBefore?: Doc, before?: boolean) => {
// if there's a sort ordering specified that can be modified on drop (eg, zorder can be modified, alphabetical can't),
@@ -461,107 +554,161 @@ export class TreeView extends React.Component<TreeViewProps> {
const docs = TreeView.sortDocs(this.childDocs || ([] as Doc[]), ordering);
doc.zIndex = addBefore ? NumCast(addBefore.zIndex) + (before ? -0.5 : 0.5) : 1000;
docs.push(doc);
- docs.sort((a, b) => NumCast(a.zIndex) > NumCast(b.zIndex) ? 1 : -1).forEach((d, i) => d.zIndex = i);
+ docs.sort((a, b) => (NumCast(a.zIndex) > NumCast(b.zIndex) ? 1 : -1)).forEach((d, i) => (d.zIndex = i));
}
const added = Doc.AddDocToList(this.dataDoc, key, doc, addBefore, before, false, true);
added && (doc.context = this.doc.context);
return added;
};
const addDoc = (doc: Doc | Doc[], addBefore?: Doc, before?: boolean) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && localAdd(doc, addBefore, before), true);
- const docs = expandKey === "aliases" ? this.childAliases : expandKey === "links" ? this.childLinks : expandKey === "annotations" ? this.childAnnos : this.childDocs;
- let downX = 0, downY = 0;
- return <>
- {!docs?.length || this.props.AddToMap /* hack to identify pres box trees */ ? (null) : <div className={'treeView-sorting'} style={{ background: sortings[sorting]?.color }} >
- {sortings[sorting]?.label}
- </div>}
- <ul key={expandKey + "more"} title="click to change sort order" className={this.doc.treeViewHideTitle ? "no-indent" : ""}
- onPointerDown={e => { downX = e.clientX; downY = e.clientY; e.stopPropagation(); }}
- onClick={(e) => {
- if (this.props.isContentActive() && Math.abs(e.clientX - downX) < 3 && Math.abs(e.clientY - downY) < 3) {
- !this.props.treeView.outlineMode && (this.doc.treeViewSortCriterion = sortKeys[(curSortIndex + 1) % sortKeys.length]);
+ const docs = expandKey === 'aliases' ? this.childAliases : expandKey === 'links' ? this.childLinks : expandKey === 'annotations' ? this.childAnnos : this.childDocs;
+ let downX = 0,
+ downY = 0;
+ return (
+ <>
+ {!docs?.length || this.props.AddToMap /* hack to identify pres box trees */ ? null : (
+ <div className={'treeView-sorting'} style={{ background: sortings[sorting]?.color }}>
+ {sortings[sorting]?.label}
+ </div>
+ )}
+ <ul
+ key={expandKey + 'more'}
+ title="click to change sort order"
+ className={this.doc.treeViewHideTitle ? 'no-indent' : ''}
+ onPointerDown={e => {
+ downX = e.clientX;
+ downY = e.clientY;
e.stopPropagation();
- }
- }}>
- {!docs ? (null) :
- TreeView.GetChildElements(docs, this.props.treeView, this, this.layoutDoc,
- this.dataDoc, this.props.containerCollection, this.props.prevSibling, addDoc, remDoc, this.move,
- StrCast(this.doc.childDropAction, this.props.dropAction) as dropActionType, this.props.addDocTab, this.titleStyleProvider, this.props.ScreenToLocalTransform,
- this.props.isContentActive, this.props.panelWidth, this.props.renderDepth, this.props.treeViewHideHeaderFields,
- [...this.props.renderedIds, this.doc[Id]], this.props.onCheckedClick, this.props.onChildClick, this.props.skipFields, false, this.props.whenChildContentsActiveChanged,
- this.props.dontRegisterView, emptyFunction, emptyFunction, this.childContextMenuItems(),
- // TODO: [AL] add these
- this.props.AddToMap,
- this.props.RemFromMap,
- this.props.hierarchyIndex)}
- </ul >
- </>;
- } else if (this.treeViewExpandedView === "fields") {
- return <ul key={this.doc[Id] + this.doc.title}>
- <div style={{ display: "inline-block" }} >
- {this.expandedField}
- </div>
- </ul>;
+ }}
+ onClick={e => {
+ if (this.props.isContentActive() && Math.abs(e.clientX - downX) < 3 && Math.abs(e.clientY - downY) < 3) {
+ !this.props.treeView.outlineMode && (this.doc.treeViewSortCriterion = sortKeys[(curSortIndex + 1) % sortKeys.length]);
+ e.stopPropagation();
+ }
+ }}>
+ {!docs
+ ? null
+ : TreeView.GetChildElements(
+ docs,
+ this.props.treeView,
+ this,
+ this.layoutDoc,
+ this.dataDoc,
+ this.props.containerCollection,
+ this.props.prevSibling,
+ addDoc,
+ remDoc,
+ this.move,
+ StrCast(this.doc.childDropAction, this.props.dropAction) as dropActionType,
+ this.props.addDocTab,
+ this.titleStyleProvider,
+ this.props.ScreenToLocalTransform,
+ this.props.isContentActive,
+ this.props.panelWidth,
+ this.props.renderDepth,
+ this.props.treeViewHideHeaderFields,
+ [...this.props.renderedIds, this.doc[Id]],
+ this.props.onCheckedClick,
+ this.props.onChildClick,
+ this.props.skipFields,
+ false,
+ this.props.whenChildContentsActiveChanged,
+ this.props.dontRegisterView,
+ emptyFunction,
+ emptyFunction,
+ this.childContextMenuItems(),
+ // TODO: [AL] add these
+ this.props.AddToMap,
+ this.props.RemFromMap,
+ this.props.hierarchyIndex
+ )}
+ </ul>
+ </>
+ );
+ } else if (this.treeViewExpandedView === 'fields') {
+ return (
+ <ul key={this.doc[Id] + this.doc.title}>
+ <div style={{ display: 'inline-block' }}>{this.expandedField}</div>
+ </ul>
+ );
}
- return <ul onPointerDown={e => { e.preventDefault(); e.stopPropagation(); }}>{this.renderEmbeddedDocument(false, this.props.treeView.props.childDocumentsActive ?? returnFalse)}</ul>; // "layout"
+ return (
+ <ul
+ onPointerDown={e => {
+ e.preventDefault();
+ e.stopPropagation();
+ }}>
+ {this.renderEmbeddedDocument(false, this.props.treeView.props.childDocumentsActive ?? returnFalse)}
+ </ul>
+ ); // "layout"
}
- get onCheckedClick() { return this.doc.type === DocumentType.COL ? undefined : this.props.onCheckedClick?.() ?? ScriptCast(this.doc.onCheckedClick); }
+ get onCheckedClick() {
+ return this.doc.type === DocumentType.COL ? undefined : this.props.onCheckedClick?.() ?? ScriptCast(this.doc.onCheckedClick);
+ }
@action
bulletClick = (e: React.MouseEvent) => {
if (this.onCheckedClick) {
- this.onCheckedClick?.script.run({
- this: this.doc.isTemplateForField && this.props.dataDoc ? this.props.dataDoc : this.doc,
- heading: this.props.containerCollection.title,
- checked: this.doc.treeViewChecked === "check" ? "x" : this.doc.treeViewChecked === "x" ? "remove" : "check",
- containingTreeView: this.props.treeView.props.Document,
- }, console.log);
+ this.onCheckedClick?.script.run(
+ {
+ this: this.doc.isTemplateForField && this.props.dataDoc ? this.props.dataDoc : this.doc,
+ heading: this.props.containerCollection.title,
+ checked: this.doc.treeViewChecked === 'check' ? 'x' : this.doc.treeViewChecked === 'x' ? 'remove' : 'check',
+ containingTreeView: this.props.treeView.props.Document,
+ },
+ console.log
+ );
} else {
this.treeViewOpen = !this.treeViewOpen;
}
e.stopPropagation();
- }
+ };
@computed get renderBullet() {
TraceMobx();
- const iconType = this.props.treeView.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewIcon + (this.treeViewOpen ? ":open" : "")) || "question";
- const checked = this.onCheckedClick ? (this.doc.treeViewChecked ?? "unchecked") : undefined;
- return <div className={`bullet${this.props.treeView.outlineMode ? "-outline" : ""}`} key={"bullet"}
- title={this.childDocs?.length ? `click to see ${this.childDocs?.length} items` : "view fields"}
- onClick={this.bulletClick}
- style={this.props.treeView.outlineMode ?
- {
- opacity: this.titleStyleProvider?.(this.doc, this.props.treeView.props, StyleProp.Opacity)
- } :
- {
- pointerEvents: this.props.isContentActive() ? "all" : undefined,
- opacity: checked === "unchecked" || typeof iconType !== "string" ? undefined : 0.4,
- color: StrCast(this.doc.color, checked === "unchecked" ? "white" : "inherit"),
- }}>
- {this.props.treeView.outlineMode ?
- !(this.doc.text as RichTextField)?.Text ? (null) :
- <FontAwesomeIcon size="sm" icon={[this.childDocs?.length && !this.treeViewOpen ? "fas" : "far", "circle"]} /> :
- <div className="treeView-bulletIcons" >
- <div className={`treeView-${this.onCheckedClick ? "checkIcon" : "expandIcon"}`}>
- <FontAwesomeIcon size="sm" icon={
- checked === "check" ? "check" :
- checked === "x" ? "times" :
- checked === "unchecked" ? "square" :
- !this.treeViewOpen ? "caret-right" : "caret-down"} />
+ const iconType = this.props.treeView.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewIcon + (this.treeViewOpen ? ':open' : '')) || 'question';
+ const checked = this.onCheckedClick ? this.doc.treeViewChecked ?? 'unchecked' : undefined;
+ return (
+ <div
+ className={`bullet${this.props.treeView.outlineMode ? '-outline' : ''}`}
+ key={'bullet'}
+ title={this.childDocs?.length ? `click to see ${this.childDocs?.length} items` : 'view fields'}
+ onClick={this.bulletClick}
+ style={
+ this.props.treeView.outlineMode
+ ? {
+ opacity: this.titleStyleProvider?.(this.doc, this.props.treeView.props, StyleProp.Opacity),
+ }
+ : {
+ pointerEvents: this.props.isContentActive() ? 'all' : undefined,
+ opacity: checked === 'unchecked' || typeof iconType !== 'string' ? undefined : 0.4,
+ color: StrCast(this.doc.color, checked === 'unchecked' ? 'white' : 'inherit'),
+ }
+ }>
+ {this.props.treeView.outlineMode ? (
+ !(this.doc.text as RichTextField)?.Text ? null : (
+ <FontAwesomeIcon size="sm" icon={[this.childDocs?.length && !this.treeViewOpen ? 'fas' : 'far', 'circle']} />
+ )
+ ) : (
+ <div className="treeView-bulletIcons">
+ <div className={`treeView-${this.onCheckedClick ? 'checkIcon' : 'expandIcon'}`}>
+ <FontAwesomeIcon size="sm" icon={checked === 'check' ? 'check' : checked === 'x' ? 'times' : checked === 'unchecked' ? 'square' : !this.treeViewOpen ? 'caret-right' : 'caret-down'} />
+ </div>
+ {this.onCheckedClick ? null : typeof iconType === 'string' ? <FontAwesomeIcon icon={iconType as IconProp} /> : iconType}
</div>
- {this.onCheckedClick ? (null) : typeof iconType === "string" ? <FontAwesomeIcon icon={iconType as IconProp} /> : iconType}
- </div>
- }
- </div>;
+ )}
+ </div>
+ );
}
@computed get validExpandViewTypes() {
- const annos = () => DocListCast(this.doc[this.fieldKey + "-annotations"]).length && !this.props.treeView.dashboardMode ? "annotations" : "";
- const links = () => DocListCast(this.doc.links).length && !this.props.treeView.dashboardMode ? "links" : "";
- const data = () => this.childDocs || this.props.treeView.dashboardMode ? this.fieldKey : "";
- const aliases = () => this.props.treeView.dashboardMode ? "" : "aliases";
- const fields = () => Doc.noviceMode ? "" : "fields";
- const layout = (Doc.noviceMode) || this.doc.viewType === CollectionViewType.Docking ? [] : ["layout"];
+ const annos = () => (DocListCast(this.doc[this.fieldKey + '-annotations']).length && !this.props.treeView.dashboardMode ? 'annotations' : '');
+ const links = () => (DocListCast(this.doc.links).length && !this.props.treeView.dashboardMode ? 'links' : '');
+ const data = () => (this.childDocs || this.props.treeView.dashboardMode ? this.fieldKey : '');
+ const aliases = () => (this.props.treeView.dashboardMode ? '' : 'aliases');
+ const fields = () => (Doc.noviceMode ? '' : 'fields');
+ const layout = Doc.noviceMode || this.doc.viewType === CollectionViewType.Docking ? [] : ['layout'];
return [data(), ...layout, ...(this.props.treeView.fileSysMode ? [aliases(), links(), annos()] : []), fields()].filter(m => m);
}
@action
@@ -571,49 +718,68 @@ export class TreeView extends React.Component<TreeViewProps> {
this.doc.treeViewExpandedView = next(this.validExpandViewTypes);
}
this.treeViewOpen = true;
- }
+ };
@computed get headerElements() {
- return this.props.treeViewHideHeaderFields() || this.doc.treeViewHideHeaderFields ? (null)
- : <>
- {this.doc.hideContextMenu ? (null) : <FontAwesomeIcon title="context menu" key="bars" icon="bars" size="sm" onClick={e => { this.showContextMenu(e); e.stopPropagation(); }} />}
- {this.doc.treeViewExpandedViewLock || Doc.IsSystem(this.doc) ? (null) :
+ return this.props.treeViewHideHeaderFields() || this.doc.treeViewHideHeaderFields ? null : (
+ <>
+ {this.doc.hideContextMenu ? null : (
+ <FontAwesomeIcon
+ title="context menu"
+ key="bars"
+ icon="bars"
+ size="sm"
+ onClick={e => {
+ this.showContextMenu(e);
+ e.stopPropagation();
+ }}
+ />
+ )}
+ {this.doc.treeViewExpandedViewLock || Doc.IsSystem(this.doc) ? null : (
<span className="collectionTreeView-keyHeader" title="type of expanded data" key={this.treeViewExpandedView} onPointerDown={this.expandNextviewType}>
{this.treeViewExpandedView}
- </span>}
- </>;
+ </span>
+ )}
+ </>
+ );
}
showContextMenu = (e: React.MouseEvent) => {
DocumentViewInternal.SelectAfterContextMenu = false;
simulateMouseClick(this._docRef?.ContentDiv, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30);
DocumentViewInternal.SelectAfterContextMenu = true;
- }
+ };
contextMenuItems = () => {
- const makeFolder = { script: ScriptField.MakeFunction(`scriptContext.makeFolder()`, { scriptContext: "any" })!, icon: "folder-plus", label: "New Folder" };
- const deleteItem = { script: ScriptField.MakeFunction(`scriptContext.deleteItem()`, { scriptContext: "any" })!, icon: "folder-plus", label: "Delete" };
+ const makeFolder = { script: ScriptField.MakeFunction(`scriptContext.makeFolder()`, { scriptContext: 'any' })!, icon: 'folder-plus', label: 'New Folder' };
+ const deleteItem = { script: ScriptField.MakeFunction(`scriptContext.deleteItem()`, { scriptContext: 'any' })!, icon: 'folder-plus', label: 'Delete' };
const folderOp = this.childDocs?.length ? [makeFolder] : [];
- const openAlias = { script: ScriptField.MakeFunction(`openOnRight(getAlias(self))`)!, icon: "copy", label: "Open Alias" };
- const focusDoc = { script: ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!, icon: "eye", label: "Focus or Open" };
- return [...this.props.contextMenuItems.filter(mi => !mi.filter ? true : mi.filter.script.run({ doc: this.doc })?.result), ... (this.doc.isFolder ? folderOp :
- Doc.IsSystem(this.doc) ? [] :
- this.props.treeView.fileSysMode && this.doc === Doc.GetProto(this.doc) ?
- [openAlias, makeFolder] :
- this.doc.viewType === CollectionViewType.Docking ? [] :
- [deleteItem, openAlias, focusDoc])];
- }
+ const openAlias = { script: ScriptField.MakeFunction(`openOnRight(getAlias(self))`)!, icon: 'copy', label: 'Open Alias' };
+ const focusDoc = { script: ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!, icon: 'eye', label: 'Focus or Open' };
+ return [
+ ...this.props.contextMenuItems.filter(mi => (!mi.filter ? true : mi.filter.script.run({ doc: this.doc })?.result)),
+ ...(this.doc.isFolder
+ ? folderOp
+ : Doc.IsSystem(this.doc)
+ ? []
+ : this.props.treeView.fileSysMode && this.doc === Doc.GetProto(this.doc)
+ ? [openAlias, makeFolder]
+ : this.doc.viewType === CollectionViewType.Docking
+ ? []
+ : [deleteItem, openAlias, focusDoc]),
+ ];
+ };
childContextMenuItems = () => {
const customScripts = Cast(this.doc.childContextMenuScripts, listSpec(ScriptField), []);
const customFilters = Cast(this.doc.childContextMenuFilters, listSpec(ScriptField), []);
const icons = StrListCast(this.doc.childContextMenuIcons);
return StrListCast(this.doc.childContextMenuLabels).map((label, i) => ({ script: customScripts[i], filter: customFilters[i], icon: icons[i], label }));
- }
+ };
onChildClick = () => {
return this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!);
- }
+ };
- onChildDoubleClick = () => ScriptCast(this.props.treeView.Document.treeViewChildDoubleClick,(!this.props.treeView.outlineMode ? this._openScript?.():null));
+ onChildDoubleClick = () => ScriptCast(this.props.treeView.Document.treeViewChildDoubleClick, !this.props.treeView.outlineMode ? this._openScript?.() : null);
refocus = () => this.props.treeView.props.focus(this.props.treeView.props.Document);
ignoreEvent = (e: any) => {
@@ -621,51 +787,59 @@ export class TreeView extends React.Component<TreeViewProps> {
e.stopPropagation();
e.preventDefault();
}
- }
- titleStyleProvider = (doc: (Doc | undefined), props: Opt<DocumentViewProps>, property: string): any => {
+ };
+ 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
- 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.DocContents: return this.props.treeView.outlineMode ? (null) :
- <div className="treeView-label" style={{ // just render a title for a tree view label (identified by treeViewDoc being set in 'props')
- maxWidth: props?.PanelWidth() || undefined,
- background: props?.styleProvider?.(doc, props, StyleProp.BackgroundColor),
- }}>
- {StrCast(doc?.title)}
- </div>;
- default: return this.props?.treeView?.props.styleProvider?.(doc, props, property);
+ 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.DocContents:
+ return this.props.treeView.outlineMode ? null : (
+ <div
+ className="treeView-label"
+ style={{
+ // just render a title for a tree view label (identified by treeViewDoc being set in 'props')
+ maxWidth: props?.PanelWidth() || undefined,
+ background: props?.styleProvider?.(doc, props, StyleProp.BackgroundColor),
+ }}>
+ {StrCast(doc?.title)}
+ </div>
+ );
+ default:
+ 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);
+ };
+ embeddedStyleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, property: string): any => {
+ if (property.startsWith(StyleProp.Decorations)) return null;
return this.props?.treeView?.props.styleProvider?.(doc, props, property); // properties are inherited from the CollectionTreeView, not the hierarchical parent in the treeView
- }
+ };
onKeyDown = (e: React.KeyboardEvent, fieldProps: FieldViewProps) => {
if (this.doc.treeViewHideHeader || (this.doc.treeViewHideHeaderIfTemplate && this.props.treeView.props.childLayoutTemplate?.()) || this.props.treeView.outlineMode) {
switch (e.key) {
- case "Tab":
+ case 'Tab':
e.stopPropagation?.();
e.preventDefault?.();
setTimeout(() => RichTextMenu.Instance.TextView?.EditorView?.focus(), 150);
- UndoManager.RunInBatch(() => e.shiftKey ? this.props.outdentDocument?.(true) : this.props.indentDocument?.(true), "tab");
+ UndoManager.RunInBatch(() => (e.shiftKey ? this.props.outdentDocument?.(true) : this.props.indentDocument?.(true)), 'tab');
return true;
- case "Backspace":
+ case 'Backspace':
if (!(this.doc.text as RichTextField)?.Text && this.props.removeDoc?.(this.doc)) {
e.stopPropagation?.();
e.preventDefault?.();
return true;
}
break;
- case "Enter":
+ case 'Enter':
e.stopPropagation?.();
e.preventDefault?.();
- return UndoManager.RunInBatch(this.makeTextCollection, "bullet");
+ return UndoManager.RunInBatch(this.makeTextCollection, 'bullet');
}
}
return false;
- }
+ };
titleWidth = () => Math.max(20, Math.min(this.props.treeView.truncateTitleWidth(), this.props.panelWidth() - 2 * treeBulletWidth()));
return18 = () => 18;
@@ -675,28 +849,32 @@ export class TreeView extends React.Component<TreeViewProps> {
@computed
get renderTitle() {
TraceMobx();
- const view = this._editTitle ? <EditableView key="_editTitle"
- oneLine={true}
- display={"inline-block"}
- editing={this._editTitle}
- background={"#7089bb"}
- contents={StrCast(this.doc.title)}
- height={12}
- sizeToContent={true}
- fontSize={12}
- GetValue={() => StrCast(this.doc.title)}
- OnTab={undoBatch((shift?: boolean) => {
- if (!shift) this.props.indentDocument?.(true);
- else this.props.outdentDocument?.(true);
- })}
- OnEmpty={undoBatch(() => this.props.treeView.outlineMode && this.props.removeDoc?.(this.doc))}
- OnFillDown={val => this.props.treeView.fileSysMode && this.makeFolder()}
- SetValue={undoBatch((value: string, shiftKey: boolean, enterKey: boolean) => {
- Doc.SetInPlace(this.doc, "title", value, false);
- this.props.treeView.outlineMode && enterKey && this.makeTextCollection();
- })}
- />
- : <DocumentView key="title"
+ const view = this._editTitle ? (
+ <EditableView
+ key="_editTitle"
+ oneLine={true}
+ display={'inline-block'}
+ editing={this._editTitle}
+ background={'#7089bb'}
+ contents={StrCast(this.doc.title)}
+ height={12}
+ sizeToContent={true}
+ fontSize={12}
+ GetValue={() => StrCast(this.doc.title)}
+ OnTab={undoBatch((shift?: boolean) => {
+ if (!shift) this.props.indentDocument?.(true);
+ else this.props.outdentDocument?.(true);
+ })}
+ OnEmpty={undoBatch(() => this.props.treeView.outlineMode && this.props.removeDoc?.(this.doc))}
+ OnFillDown={val => this.props.treeView.fileSysMode && this.makeFolder()}
+ SetValue={undoBatch((value: string, shiftKey: boolean, enterKey: boolean) => {
+ Doc.SetInPlace(this.doc, 'title', value, false);
+ this.props.treeView.outlineMode && enterKey && this.makeTextCollection();
+ })}
+ />
+ ) : (
+ <DocumentView
+ key="title"
ref={action((r: any) => {
this._docRef = r ? r : undefined;
if (this._docRef && TreeView._editTitleOnLoad?.id === this.props.document[Id] && TreeView._editTitleOnLoad.parent === this.props.parentTreeView) {
@@ -743,139 +921,161 @@ export class TreeView extends React.Component<TreeViewProps> {
ContainingCollectionView={undefined}
ContainingCollectionDoc={this.props.treeView.props.Document}
ContentScaling={returnOne}
- />;
-
- const buttons = this.props.styleProvider?.(this.doc, { ...this.props.treeView.props, ContainingCollectionDoc: this.props.parentTreeView?.doc }, StyleProp.Decorations + (Doc.IsSystem(this.props.containerCollection) ? ":afterHeader" : ""));
- return <>
- <div className={`docContainer${Doc.IsSystem(this.props.document) || this.props.document.isFolder ? "-system" : ""}`} ref={this._tref} title="click to edit title. Double Click or Drag to Open"
- style={{
- fontWeight: Doc.IsSearchMatch(this.doc) !== undefined ? "bold" : undefined,
- textDecoration: Doc.GetT(this.doc, "title", "string", true) ? "underline" : undefined,
- outline: this.doc === CurrentUserUtils.ActiveDashboard ? "dashed 1px #06123232" : undefined,
- pointerEvents: !this.props.isContentActive() && !SnappingManager.GetIsDragging() ? "none" : undefined
- }} >
- {view}
- </div >
- <div className="treeView-rightButtons">
- {buttons} {/* hide and lock buttons */}
- {this.headerElements}
- </div>
- </>;
- }
+ />
+ );
- renderBulletHeader = (contents: JSX.Element, editing: boolean) => {
- return <>
- <div className={`treeView-header` + (editing ? "-editing" : "")} key="titleheader"
- style={{ width: StrCast(this.doc.treeViewHeaderWidth, "max-content") }}
- ref={this._header}
- onClick={this.ignoreEvent}
- onPointerDown={this.ignoreEvent}
- onPointerEnter={this.onPointerEnter}
- onPointerLeave={this.onPointerLeave}>
- {contents}
- </div>
- {this.renderBorder}
- </>;
+ const buttons = this.props.styleProvider?.(this.doc, { ...this.props.treeView.props, ContainingCollectionDoc: this.props.parentTreeView?.doc }, StyleProp.Decorations + (Doc.IsSystem(this.props.containerCollection) ? ':afterHeader' : ''));
+ return (
+ <>
+ <div
+ className={`docContainer${Doc.IsSystem(this.props.document) || this.props.document.isFolder ? '-system' : ''}`}
+ ref={this._tref}
+ title="click to edit title. Double Click or Drag to Open"
+ style={{
+ fontWeight: Doc.IsSearchMatch(this.doc) !== undefined ? 'bold' : undefined,
+ textDecoration: Doc.GetT(this.doc, 'title', 'string', true) ? 'underline' : undefined,
+ outline: this.doc === Doc.ActiveDashboard ? 'dashed 1px #06123232' : undefined,
+ pointerEvents: !this.props.isContentActive() && !SnappingManager.GetIsDragging() ? 'none' : undefined,
+ }}>
+ {view}
+ </div>
+ <div className="treeView-rightButtons">
+ {buttons} {/* hide and lock buttons */}
+ {this.headerElements}
+ </div>
+ </>
+ );
}
+ renderBulletHeader = (contents: JSX.Element, editing: boolean) => {
+ return (
+ <>
+ <div
+ className={`treeView-header` + (editing ? '-editing' : '')}
+ key="titleheader"
+ style={{ width: StrCast(this.doc.treeViewHeaderWidth, 'max-content') }}
+ ref={this._header}
+ onClick={this.ignoreEvent}
+ onPointerDown={this.ignoreEvent}
+ onPointerEnter={this.onPointerEnter}
+ onPointerLeave={this.onPointerLeave}>
+ {contents}
+ </div>
+ {this.renderBorder}
+ </>
+ );
+ };
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}
- ContentScaling={returnOne}
- 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}
- />;
- }
+ 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}
+ ContentScaling={returnOne}
+ 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}
+ />
+ );
+ };
// renders the text version of a document as the header. This is used in the file system mode and in other vanilla tree views.
@computed get renderTitleAsHeader() {
- return <>
- {this.renderBullet}
- {this.renderTitle}
- </>;
+ return (
+ <>
+ {this.renderBullet}
+ {this.renderTitle}
+ </>
+ );
}
// renders the document in the header field instead of a text proxy.
renderDocumentAsHeader = (asText: boolean) => {
- return <>
- {this.renderBullet}
- {this.renderEmbeddedDocument(asText, this.props.isContentActive)}
- </>;
- }
+ return (
+ <>
+ {this.renderBullet}
+ {this.renderEmbeddedDocument(asText, this.props.isContentActive)}
+ </>
+ );
+ };
@computed get renderBorder() {
const sorting = StrCast(this.doc.treeViewSortCriterion, TreeSort.None);
- const sortings = this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewSortings) as { [key: string]: { color: string, label: string } };
- return <div className={`treeView-border${this.props.treeView.outlineMode ? TreeViewType.outline : ""}`} style={{ borderColor: sortings[sorting]?.color }}>
- {!this.treeViewOpen ? (null) : this.renderContent}
- </div>;
+ const sortings = this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewSortings) as { [key: string]: { color: string; label: string } };
+ return (
+ <div className={`treeView-border${this.props.treeView.outlineMode ? TreeViewType.outline : ''}`} style={{ borderColor: sortings[sorting]?.color }}>
+ {!this.treeViewOpen ? null : this.renderContent}
+ </div>
+ );
}
onTreeDrop = (de: React.DragEvent) => {
const pt = [de.clientX, de.clientY];
const rect = this._header.current!.getBoundingClientRect();
const before = pt[1] < rect.top + rect.height / 2;
- const inside = this.props.treeView.fileSysMode && !this.doc.isFolder ? false : pt[0] > Math.min(rect.left + 75, rect.left + rect.width * .75) || (!before && this.treeViewOpen && this.childDocList.length);
-
- const docs = this.props.treeView.onTreeDrop(de, (docs: Doc[]) => this.dropDocuments(docs, before, inside, "copy", undefined, false));
- }
+ const inside = this.props.treeView.fileSysMode && !this.doc.isFolder ? false : pt[0] > Math.min(rect.left + 75, rect.left + rect.width * 0.75) || (!before && this.treeViewOpen && this.childDocList.length);
+ const docs = this.props.treeView.onTreeDrop(de, (docs: Doc[]) => this.dropDocuments(docs, before, inside, 'copy', undefined, false));
+ };
render() {
TraceMobx();
const hideTitle = this.doc.treeViewHideHeader || (this.doc.treeViewHideHeaderIfTemplate && this.props.treeView.props.childLayoutTemplate?.()) || this.props.treeView.outlineMode;
- return this.props.renderedIds.indexOf(this.doc[Id]) !== -1 ? "<" + this.doc.title + ">" : // just print the title of documents we've previously rendered in this hierarchical path to avoid cycles
- <div className={`treeView-container${this.props.isContentActive() ? "-active" : ""}`}
+ return this.props.renderedIds.indexOf(this.doc[Id]) !== -1 ? (
+ '<' + this.doc.title + '>' // just print the title of documents we've previously rendered in this hierarchical path to avoid cycles
+ ) : (
+ <div
+ className={`treeView-container${this.props.isContentActive() ? '-active' : ''}`}
ref={this.createTreeDropTarget}
onDrop={this.onTreeDrop}
- //onPointerDown={e => this.props.isContentActive(true) && SelectionManager.DeselectAll()} // bcz: this breaks entering a text filter in a filterBox since it deselects the filter's target document
- // onKeyDown={this.onKeyDown}
+ //onPointerDown={e => this.props.isContentActive(true) && SelectionManager.DeselectAll()} // bcz: this breaks entering a text filter in a filterBox since it deselects the filter's target document
+ // onKeyDown={this.onKeyDown}
>
<li className="collection-child">
- {hideTitle && this.doc.type !== DocumentType.RTF && !this.doc.treeViewRenderAsBulletHeader ? // should test for prop 'treeViewRenderDocWithBulletAsHeader"
- this.renderEmbeddedDocument(false, returnFalse) :
- this.renderBulletHeader(hideTitle ? this.renderDocumentAsHeader(!this.doc.treeViewRenderAsBulletHeader) : this.renderTitleAsHeader, this._editTitle)}
+ {hideTitle && this.doc.type !== DocumentType.RTF && !this.doc.treeViewRenderAsBulletHeader // should test for prop 'treeViewRenderDocWithBulletAsHeader"
+ ? this.renderEmbeddedDocument(false, returnFalse)
+ : this.renderBulletHeader(hideTitle ? this.renderDocumentAsHeader(!this.doc.treeViewRenderAsBulletHeader) : this.renderTitleAsHeader, this._editTitle)}
</li>
- </div>;
+ </div>
+ );
}
public static sortDocs(childDocs: Doc[], criterion: string | undefined) {
@@ -883,9 +1083,10 @@ export class TreeView extends React.Component<TreeViewProps> {
if (criterion !== TreeSort.None) {
const sortAlphaNum = (a: string, b: string): 0 | 1 | -1 => {
const reN = /[0-9]*$/;
- const aA = a.replace(reN, "") ? a.replace(reN, "") : +a; // get rid of trailing numbers
- const bA = b.replace(reN, "") ? b.replace(reN, "") : +b;
- if (aA === bA) { // if header string matches, then compare numbers numerically
+ const aA = a.replace(reN, '') ? a.replace(reN, '') : +a; // get rid of trailing numbers
+ const bA = b.replace(reN, '') ? b.replace(reN, '') : +b;
+ if (aA === bA) {
+ // if header string matches, then compare numbers numerically
const aN = parseInt(a.match(reN)![0], 10);
const bN = parseInt(b.match(reN)![0], 10);
return aN === bN ? 0 : aN > bN ? 1 : -1;
@@ -894,11 +1095,11 @@ export class TreeView extends React.Component<TreeViewProps> {
}
};
docs.sort(function (d1, d2): 0 | 1 | -1 {
- const a = (criterion === TreeSort.Up ? d2 : d1);
- const b = (criterion === TreeSort.Up ? d1 : d2);
- const first = a[criterion === TreeSort.Zindex ? "zIndex" : "title"];
- const second = b[criterion === TreeSort.Zindex ? "zIndex" : "title"];
- if (typeof first === 'number' && typeof second === 'number') return (first - second) > 0 ? 1 : -1;
+ const a = criterion === TreeSort.Up ? d2 : d1;
+ const b = criterion === TreeSort.Up ? d1 : d2;
+ const first = a[criterion === TreeSort.Zindex ? 'zIndex' : 'title'];
+ const second = b[criterion === TreeSort.Zindex ? 'zIndex' : 'title'];
+ if (typeof first === 'number' && typeof second === 'number') return first - second > 0 ? 1 : -1;
if (typeof first === 'string' && typeof second === 'string') return sortAlphaNum(first, second);
return criterion ? 1 : -1;
});
@@ -934,11 +1135,11 @@ export class TreeView extends React.Component<TreeViewProps> {
dontRegisterView: boolean | undefined,
observerHeight: (ref: any) => void,
unobserveHeight: (ref: any) => void,
- contextMenuItems: ({ script: ScriptField, filter: ScriptField, label: string, icon: string }[]),
+ contextMenuItems: { script: ScriptField; filter: ScriptField; label: string; icon: string }[],
// TODO: [AL] add these
AddToMap?: (treeViewDoc: Doc, index: number[]) => Doc[],
RemFromMap?: (treeViewDoc: Doc, index: number[]) => Doc[],
- hierarchyIndex?: number[],
+ hierarchyIndex?: number[]
) {
const viewSpecScript = Cast(containerCollection.viewSpecScript, ScriptField);
if (viewSpecScript) {
@@ -948,68 +1149,77 @@ export class TreeView extends React.Component<TreeViewProps> {
const docs = TreeView.sortDocs(childDocs, StrCast(containerCollection.treeViewSortCriterion, TreeSort.None));
const rowWidth = () => panelWidth() - treeBulletWidth();
const treeViewRefs = new Map<Doc, TreeView | undefined>();
- return docs.filter(child => child instanceof Doc).map((child, i) => {
- const pair = Doc.GetLayoutDataDocPair(containerCollection, dataDoc, child);
- if (!pair.layout || pair.data instanceof Promise) {
- return (null);
- }
-
- const dentDoc = (editTitle: boolean, newParent: Doc, addAfter: Doc | undefined, parent: TreeView | CollectionTreeView | undefined) => {
- if (parent instanceof TreeView && parent.props.treeView.fileSysMode && !newParent.isFolder) return;
- const fieldKey = Doc.LayoutFieldKey(newParent);
- if (remove && fieldKey && Cast(newParent[fieldKey], listSpec(Doc)) !== undefined) {
- remove(child);
- FormattedTextBox.SelectOnLoad = child[Id];
- TreeView._editTitleOnLoad = editTitle ? { id: child[Id], parent } : undefined;
- Doc.AddDocToList(newParent, fieldKey, child, addAfter, false);
- newParent.treeViewOpen = true;
- child.context = treeView.Document;
+ return docs
+ .filter(child => child instanceof Doc)
+ .map((child, i) => {
+ const pair = Doc.GetLayoutDataDocPair(containerCollection, dataDoc, child);
+ if (!pair.layout || pair.data instanceof Promise) {
+ return null;
}
- };
- const indent = i === 0 ? undefined : (editTitle: boolean) => dentDoc(editTitle, docs[i - 1], undefined, treeViewRefs.get(docs[i - 1]));
- const outdent = parentCollectionDoc?._viewType !== CollectionViewType.Tree ? undefined : ((editTitle: boolean) => dentDoc(editTitle, parentCollectionDoc, containerPrevSibling, parentTreeView instanceof TreeView ? parentTreeView.props.parentTreeView : undefined));
- const addDocument = (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => add(doc, relativeTo ?? docs[i], before !== undefined ? before : false);
- const childLayout = Doc.Layout(pair.layout);
- const rowHeight = () => {
- const aspect = Doc.NativeAspect(childLayout);
- return (aspect ? Math.min(childLayout[WidthSym](), rowWidth()) / aspect : childLayout[HeightSym]());
- };
- return <TreeView key={child[Id]} ref={r => treeViewRefs.set(child, r ? r : undefined)}
- document={pair.layout}
- dataDoc={pair.data}
- containerCollection={containerCollection}
- prevSibling={docs[i]}
- // TODO: [AL] add these
- hierarchyIndex={hierarchyIndex ? [...hierarchyIndex, i + 1] : undefined}
- AddToMap={AddToMap}
- RemFromMap={RemFromMap}
- treeView={treeView}
- indentDocument={indent}
- outdentDocument={outdent}
- onCheckedClick={onCheckedClick}
- onChildClick={onChildClick}
- renderDepth={renderDepth}
- removeDoc={StrCast(containerCollection.freezeChildren).includes("remove") ? undefined : remove}
- addDocument={addDocument}
- styleProvider={styleProvider}
- panelWidth={rowWidth}
- panelHeight={rowHeight}
- dontRegisterView={dontRegisterView}
- moveDocument={move}
- dropAction={dropAction}
- addDocTab={addDocTab}
- ScreenToLocalTransform={screenToLocalXf}
- isContentActive={isContentActive}
- treeViewHideHeaderFields={treeViewHideHeaderFields}
- renderedIds={renderedIds}
- skipFields={skipFields}
- firstLevel={firstLevel}
- whenChildContentsActiveChanged={whenChildContentsActiveChanged}
- parentTreeView={parentTreeView}
- observeHeight={observerHeight}
- unobserveHeight={unobserveHeight}
- contextMenuItems={contextMenuItems}
- />;
- });
+
+ const dentDoc = (editTitle: boolean, newParent: Doc, addAfter: Doc | undefined, parent: TreeView | CollectionTreeView | undefined) => {
+ if (parent instanceof TreeView && parent.props.treeView.fileSysMode && !newParent.isFolder) return;
+ const fieldKey = Doc.LayoutFieldKey(newParent);
+ if (remove && fieldKey && Cast(newParent[fieldKey], listSpec(Doc)) !== undefined) {
+ remove(child);
+ FormattedTextBox.SelectOnLoad = child[Id];
+ TreeView._editTitleOnLoad = editTitle ? { id: child[Id], parent } : undefined;
+ Doc.AddDocToList(newParent, fieldKey, child, addAfter, false);
+ newParent.treeViewOpen = true;
+ child.context = treeView.Document;
+ }
+ };
+ const indent = i === 0 ? undefined : (editTitle: boolean) => dentDoc(editTitle, docs[i - 1], undefined, treeViewRefs.get(docs[i - 1]));
+ const outdent =
+ parentCollectionDoc?._viewType !== CollectionViewType.Tree
+ ? undefined
+ : (editTitle: boolean) => dentDoc(editTitle, parentCollectionDoc, containerPrevSibling, parentTreeView instanceof TreeView ? parentTreeView.props.parentTreeView : undefined);
+ const addDocument = (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => add(doc, relativeTo ?? docs[i], before !== undefined ? before : false);
+ const childLayout = Doc.Layout(pair.layout);
+ const rowHeight = () => {
+ const aspect = Doc.NativeAspect(childLayout);
+ return aspect ? Math.min(childLayout[WidthSym](), rowWidth()) / aspect : childLayout[HeightSym]();
+ };
+ return (
+ <TreeView
+ key={child[Id]}
+ ref={r => treeViewRefs.set(child, r ? r : undefined)}
+ document={pair.layout}
+ dataDoc={pair.data}
+ containerCollection={containerCollection}
+ prevSibling={docs[i]}
+ // TODO: [AL] add these
+ hierarchyIndex={hierarchyIndex ? [...hierarchyIndex, i + 1] : undefined}
+ AddToMap={AddToMap}
+ RemFromMap={RemFromMap}
+ treeView={treeView}
+ indentDocument={indent}
+ outdentDocument={outdent}
+ onCheckedClick={onCheckedClick}
+ onChildClick={onChildClick}
+ renderDepth={renderDepth}
+ removeDoc={StrCast(containerCollection.freezeChildren).includes('remove') ? undefined : remove}
+ addDocument={addDocument}
+ styleProvider={styleProvider}
+ panelWidth={rowWidth}
+ panelHeight={rowHeight}
+ dontRegisterView={dontRegisterView}
+ moveDocument={move}
+ dropAction={dropAction}
+ addDocTab={addDocTab}
+ ScreenToLocalTransform={screenToLocalXf}
+ isContentActive={isContentActive}
+ treeViewHideHeaderFields={treeViewHideHeaderFields}
+ renderedIds={renderedIds}
+ skipFields={skipFields}
+ firstLevel={firstLevel}
+ whenChildContentsActiveChanged={whenChildContentsActiveChanged}
+ parentTreeView={parentTreeView}
+ observeHeight={observerHeight}
+ unobserveHeight={unobserveHeight}
+ contextMenuItems={contextMenuItems}
+ />
+ );
+ });
}
-} \ No newline at end of file
+}