aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/TreeView.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/collections/TreeView.tsx')
-rw-r--r--src/client/views/collections/TreeView.tsx70
1 files changed, 41 insertions, 29 deletions
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 7f2128230..eedb353e3 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -81,7 +81,7 @@ export class TreeView extends React.Component<TreeViewProps> {
static _openLevelScript: Opt<ScriptField | undefined>;
private _header: React.RefObject<HTMLDivElement> = React.createRef();
private _tref = React.createRef<HTMLDivElement>();
- private _docRef: Opt<DocumentView>;
+ @observable _docRef: Opt<DocumentView>;
private _selDisposer: Opt<IReactionDisposer>;
private _editTitleScript: (() => ScriptField) | undefined;
private _openScript: (() => ScriptField) | undefined;
@@ -116,7 +116,8 @@ export class TreeView extends React.Component<TreeViewProps> {
@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.Views().lastElement()?.props.Document === this.props.document; }
+ @computed get selected() { return SelectionManager.IsSelected(this._docRef); }
+ // SelectionManager.Views().lastElement()?.props.Document === this.props.document; }
childDocList(field: string) {
const layout = Cast(Doc.LayoutField(this.doc), Doc, null);
@@ -125,7 +126,12 @@ export class TreeView extends React.Component<TreeViewProps> {
DocListCastOrNull(this.doc[field]); // otherwise use the document's data field
}
@undoBatch move = (doc: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => {
- return this.doc !== target && this.props.removeDoc?.(doc) === true && addDoc(doc);
+ 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);
@@ -141,8 +147,10 @@ export class TreeView extends React.Component<TreeViewProps> {
this._editTitle = false;
}
else if (docView.isSelected()) {
+ const doc = docView.Document;
+ SelectionManager.SelectSchemaViewDoc(doc);
this._editTitle = true;
- this._selDisposer = reaction(() => docView.isSelected(), sel => !sel && this.setEditTitle(undefined));
+ this._selDisposer = reaction(() => SelectionManager.SelectedSchemaDoc(), seldoc => seldoc !== doc && this.setEditTitle(undefined));
} else {
docView.select(false);
}
@@ -213,16 +221,18 @@ export class TreeView extends React.Component<TreeViewProps> {
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";
- 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 (!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";
+ }
e.stopPropagation();
}
public static makeTextBullet() {
const bullet = Docs.Create.TextDocument("-text-", {
layout: CollectionView.LayoutString("data"),
- title: "-title-", "sidebarColor": "transparent", "sidebarViewType": CollectionViewType.Freeform,
+ title: "-title-",
treeViewExpandedViewLock: true, treeViewExpandedView: "data",
_viewType: CollectionViewType.Tree, hideLinkButton: true, _showSidebar: true, treeViewType: "outline",
x: 0, y: 0, _xMargin: 0, _yMargin: 0, _autoHeight: true, _singleLine: true, backgroundColor: "transparent", _width: 1000, _height: 10
@@ -244,9 +254,7 @@ export class TreeView extends React.Component<TreeViewProps> {
TreeView._editTitleOnLoad = { id: folder[Id], parent: this.props.parentTreeView };
return this.props.addDocument(folder);
}
- deleteFolder = () => {
- return this.props.removeDoc?.(this.doc);
- }
+ deleteItem = () => this.props.removeDoc?.(this.doc);
preTreeDrop = (e: Event, de: DragManager.DropEvent, targetAction: dropActionType) => {
const dragData = de.complete.docDragData;
@@ -266,23 +274,25 @@ export class TreeView extends React.Component<TreeViewProps> {
e.stopPropagation();
}
const docDragData = de.complete.docDragData;
- if (docDragData) {
- e.stopPropagation();
+ if (docDragData && pt[0] < rect.left + rect.width) {
if (docDragData.draggedDocuments[0] === this.doc) return true;
- this.dropDocuments(docDragData.droppedDocuments, before, inside, docDragData.dropAction, docDragData.moveDocument, docDragData.treeViewDoc === this.props.treeView.props.Document);
+ if (this.dropDocuments(docDragData.droppedDocuments, before, inside, docDragData.dropAction, docDragData.moveDocument, docDragData.treeViewDoc === this.props.treeView.props.Document)) {
+ 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 = !StrCast((inside ? this.props.document : this.props.containerCollection)?.freezeChildren).includes("add") || forceAdd;
+ 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) {
- 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;
}
refTransform = (ref: HTMLDivElement | undefined | null) => {
@@ -432,7 +442,7 @@ export class TreeView extends React.Component<TreeViewProps> {
</div>
</ul>;
}
- return <ul>{this.renderEmbeddedDocument(false)}</ul>; // "layout"
+ return <ul onPointerDown={e => { e.preventDefault(); e.stopPropagation(); }}>{this.renderEmbeddedDocument(false, returnFalse)}</ul>; // "layout"
}
get onCheckedClick() { return this.doc.type === DocumentType.COL ? undefined : this.props.onCheckedClick?.() ?? ScriptCast(this.doc.onCheckedClick); }
@@ -519,16 +529,16 @@ export class TreeView extends React.Component<TreeViewProps> {
}
contextMenuItems = () => {
const makeFolder = { script: ScriptField.MakeFunction(`scriptContext.makeFolder()`, { scriptContext: "any" })!, icon: "folder-plus", label: "New Folder" };
- const deleteFolder = { script: ScriptField.MakeFunction(`scriptContext.deleteFolder()`, { scriptContext: "any" })!, icon: "folder-plus", label: "Delete Folder" };
- const folderOp = this.childDocs?.length ? makeFolder : deleteFolder;
+ 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] :
+ 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 ? [] :
- [openAlias, focusDoc])];
+ [deleteItem, openAlias, focusDoc])];
}
childContextMenuItems = () => {
const customScripts = Cast(this.doc.childContextMenuScripts, listSpec(ScriptField), []);
@@ -581,6 +591,7 @@ export class TreeView extends React.Component<TreeViewProps> {
}
titleWidth = () => Math.max(20, Math.min(this.props.treeView.truncateTitleWidth(), this.props.panelWidth() - 2 * treeBulletWidth()));
+ return18 = () => 18;
/**
* Renders the EditableView title element for placement into the tree.
*/
@@ -636,10 +647,10 @@ export class TreeView extends React.Component<TreeViewProps> {
moveDocument={this.move}
removeDocument={this.props.removeDoc}
ScreenToLocalTransform={this.getTransform}
- NativeHeight={() => 18}
+ NativeHeight={this.return18}
NativeWidth={this.titleWidth}
PanelWidth={this.titleWidth}
- PanelHeight={() => 18}
+ PanelHeight={this.return18}
contextMenuItems={this.contextMenuItems}
renderDepth={1}
isContentActive={this.props.isContentActive}
@@ -679,6 +690,7 @@ export class TreeView extends React.Component<TreeViewProps> {
renderBulletHeader = (contents: JSX.Element, editing: boolean) => {
return <>
<div className={`treeView-header` + (editing ? "-editing" : "")} key="titleheader"
+ style={{ width: "max-content" }}
ref={this._header}
onClick={this.ignoreEvent}
onPointerDown={this.ignoreEvent}
@@ -691,7 +703,7 @@ export class TreeView extends React.Component<TreeViewProps> {
}
- renderEmbeddedDocument = (asText: boolean) => {
+ renderEmbeddedDocument = (asText: boolean, isActive: () => boolean | undefined) => {
const layout = StrCast(Doc.LayoutField(this.layoutDoc));
const isExpandable = layout.includes(FormattedTextBox.name) || layout.includes(SliderBox.name);
const panelWidth = asText || isExpandable ? this.rtfWidth : this.expandPanelWidth;
@@ -704,8 +716,8 @@ export class TreeView extends React.Component<TreeViewProps> {
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}
- isContentActive={asText ? this.props.isContentActive : returnFalse}
- isDocumentActive={asText ? this.props.isContentActive : returnFalse}
+ isContentActive={isActive}
+ isDocumentActive={isActive}
styleProvider={asText ? this.titleStyleProvider : this.embeddedStyleProvider}
hideTitle={asText}
fitContentsToDoc={returnTrue}
@@ -749,7 +761,7 @@ export class TreeView extends React.Component<TreeViewProps> {
@computed get renderDocumentAsHeader() {
return <>
{this.renderBullet}
- {this.renderEmbeddedDocument(true)}
+ {this.renderEmbeddedDocument(true, this.props.isContentActive)}
</>;
}
@@ -770,19 +782,19 @@ export class TreeView extends React.Component<TreeViewProps> {
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.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" : ""}`}
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}>
<li className="collection-child">
{hideTitle && this.doc.type !== DocumentType.RTF ?
- this.renderEmbeddedDocument(false) :
+ this.renderEmbeddedDocument(false, returnFalse) :
this.renderBulletHeader(hideTitle ? this.renderDocumentAsHeader : this.renderTitleAsHeader, this._editTitle)}
</li>
</div>;