aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/CollectionTreeView.tsx
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2024-03-01 08:23:06 -0500
committerbobzel <zzzman@gmail.com>2024-03-01 08:23:06 -0500
commit25474b83f908732b2618cb7110f1e410030f9280 (patch)
treea942453765eb876ffaa3899d623fa77e13a196b4 /src/client/views/collections/CollectionTreeView.tsx
parent4e837a73f5fae06368416f99c047d78f6b94565b (diff)
parent3179048be75fb7662fc472249798b2d103dc5544 (diff)
Merge branch 'master' into info-ui-observable
Diffstat (limited to 'src/client/views/collections/CollectionTreeView.tsx')
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx100
1 files changed, 66 insertions, 34 deletions
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 18e0b98ef..4d60cbefc 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -8,8 +8,8 @@ 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, returnAll, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnNone, returnOne, returnTrue, returnZero } from '../../../Utils';
-import { DocUtils } from '../../documents/Documents';
+import { emptyFunction, returnAll, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnNone, returnOne, returnTrue, returnZero, Utils } from '../../../Utils';
+import { Docs, DocUtils } from '../../documents/Documents';
import { DocumentManager } from '../../util/DocumentManager';
import { DragManager, dropActionType } from '../../util/DragManager';
import { SelectionManager } from '../../util/SelectionManager';
@@ -27,6 +27,7 @@ import { CollectionFreeFormView } from './collectionFreeForm';
import { CollectionSubView } from './CollectionSubView';
import './CollectionTreeView.scss';
import { TreeView } from './TreeView';
+import { ScriptingGlobals } from '../../util/ScriptingGlobals';
const _global = (window /* browser */ || global) /* node */ as any;
export type collectionTreeViewProps = {
@@ -51,6 +52,7 @@ export enum TreeViewType {
@observer
export class CollectionTreeView extends CollectionSubView<Partial<collectionTreeViewProps>>() {
+ public static AddTreeFunc = 'addTreeFolder(this.embedContainer)';
private _treedropDisposer?: DragManager.DragDropDisposer;
private _mainEle?: HTMLDivElement;
private _titleRef?: HTMLDivElement | HTMLInputElement | null;
@@ -140,20 +142,35 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
if ((this._mainEle = ele)) this._treedropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.Document, this.onInternalPreDrop.bind(this));
};
- protected onInternalPreDrop = (e: Event, de: DragManager.DropEvent) => {
- const dropAction = this.layoutDoc.dropAction as dropActionType;
+ protected onInternalDrop(e: Event, de: DragManager.DropEvent) {
+ const res = super.onInternalDrop(e, de);
+ if (res && de.complete.docDragData) {
+ if (this.Document !== Doc.MyRecentlyClosed)
+ de.complete.docDragData.droppedDocuments.forEach(doc => {
+ if (this.Document !== Doc.MyRecentlyClosed) Doc.RemoveDocFromList(Doc.MyRecentlyClosed, undefined, doc);
+ });
+ }
+ return res;
+ }
+
+ protected onInternalPreDrop = (e: Event, de: DragManager.DropEvent, targetDropAction: dropActionType) => {
const dragData = de.complete.docDragData;
if (dragData) {
- const sameTree = Doc.AreProtosEqual(dragData.treeViewDoc, this.Document) ? true : false;
+ const sourceDragAction = dragData.dropAction;
+ const sameTree = () => Doc.AreProtosEqual(dragData.treeViewDoc, this.Document);
const isAlreadyInTree = () => sameTree || dragData.draggedDocuments.some(d => d.embedContainer === this.Document && this.childDocs.includes(d));
- if (isAlreadyInTree() !== sameTree) {
- console.log('WHAAAT');
- }
- dragData.dropAction = dropAction && !isAlreadyInTree() ? dropAction : sameTree && dragData.dropAction !== 'inSame' ? 'same' : dragData.dropAction;
+ dragData.dropAction =
+ targetDropAction && !isAlreadyInTree() // if dropped document is not in the tree
+ ? targetDropAction // then use the target's drop action if it's specified
+ : !sameTree() || sourceDragAction === dropActionType.inPlace // if doc from another tree, or a non inPlace source drag action is specified
+ ? sourceDragAction // use the source dragAction
+ : dropActionType.same; // otherwise use same tree semantics to move within tree
e.stopPropagation();
}
};
+ dragConfig = (dragData: DragManager.DocumentDragData) => (dragData.treeViewDoc = this.Document);
+
screenToLocalTransform = () => this.ScreenToLocalBoxXf().translate(0, -this._headerHeight);
@action
@@ -163,34 +180,41 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
const value = DocListCast(targetDataDoc[this._props.fieldKey]);
const result = value.filter(v => !docs.includes(v));
if ((doc instanceof Doc ? [doc] : doc).some(doc => SelectionManager.Views.some(dv => Doc.AreProtosEqual(dv.Document, doc)))) SelectionManager.DeselectAll();
- if (result.length !== value.length && doc instanceof Doc) {
- const ind = DocListCast(targetDataDoc[this._props.fieldKey]).indexOf(doc);
- const prev = ind && DocListCast(targetDataDoc[this._props.fieldKey])[ind - 1];
- this._props.removeDocument?.(doc);
- if (ind > 0 && prev) {
- FormattedTextBox.SetSelectOnLoad(prev);
- DocumentManager.Instance.getDocumentView(prev, this._props.DocumentView?.())?.select(false);
+ if (result.length !== value.length) {
+ if (doc instanceof Doc) {
+ const ind = DocListCast(targetDataDoc[this._props.fieldKey]).indexOf(doc);
+ const prev = ind && DocListCast(targetDataDoc[this._props.fieldKey])[ind - 1];
+ this._props.removeDocument?.(doc);
+ if (ind > 0 && prev) {
+ FormattedTextBox.SetSelectOnLoad(prev);
+ DocumentManager.Instance.getDocumentView(prev, this.DocumentView?.())?.select(false);
+ }
+ return true;
}
- return true;
+ return this._props.removeDocument?.(doc) ?? false;
}
return false;
};
@action
addDoc = (docs: Doc | Doc[], relativeTo: Opt<Doc>, before?: boolean): boolean => {
- const doAddDoc = (doc: Doc | Doc[]) =>
- (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => {
- const res = flg && Doc.AddDocToList(this.Document[DocData], this._props.fieldKey, doc, relativeTo, before);
- res && Doc.SetContainer(doc, this.Document);
- return res;
- }, true);
+ const doclist = docs instanceof Doc ? [docs] : docs;
+ const addDocRelativeTo = (doc: Doc | Doc[]) => doclist.reduce((flg, doc) => flg && Doc.AddDocToList(this.Document[DocData], this._props.fieldKey, doc, relativeTo, before), true);
if (this.Document.resolvedDataDoc instanceof Promise) return false;
- return relativeTo === undefined ? this._props.addDocument?.(docs) || false : doAddDoc(docs);
+ const res = relativeTo === undefined ? this._props.addDocument?.(docs) || false : addDocRelativeTo(docs);
+ res &&
+ doclist.forEach(doc => {
+ Doc.SetContainer(doc, this.Document);
+ if (this.Document !== Doc.MyRecentlyClosed) Doc.RemoveDocFromList(Doc.MyRecentlyClosed, undefined, doc);
+ });
+ return res;
};
onContextMenu = (e: React.MouseEvent): void => {
// need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout
+ const layoutItems: ContextMenuProps[] = [];
+ const menuDoc = ScriptCast(Cast(this.layoutDoc.layout_headerButton, Doc, null)?.onClick).script.originalScript === CollectionTreeView.AddTreeFunc;
+ menuDoc && layoutItems.push({ description: 'Create new folder', event: () => CollectionTreeView.addTreeFolder(this.Document), icon: 'paint-brush' });
if (!Doc.noviceMode) {
- const layoutItems: ContextMenuProps[] = [];
layoutItems.push({
description: 'Make tree state ' + (this.Document.treeView_OpenIsTransient ? 'persistent' : 'transient'),
event: () => (this.Document.treeView_OpenIsTransient = !this.Document.treeView_OpenIsTransient),
@@ -198,7 +222,9 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
});
layoutItems.push({ description: (this.Document.treeView_HideHeaderFields ? 'Show' : 'Hide') + ' Header Fields', event: () => (this.Document.treeView_HideHeaderFields = !this.Document.treeView_HideHeaderFields), icon: 'paint-brush' });
layoutItems.push({ description: (this.Document.treeView_HideTitle ? 'Show' : 'Hide') + ' Title', event: () => (this.Document.treeView_HideTitle = !this.Document.treeView_HideTitle), icon: 'paint-brush' });
- ContextMenu.Instance.addItem({ description: 'Options...', subitems: layoutItems, icon: 'eye' });
+ }
+ ContextMenu.Instance.addItem({ description: 'Options...', subitems: layoutItems, icon: 'eye' });
+ if (!Doc.noviceMode) {
const existingOnClick = ContextMenu.Instance.findByDescription('OnClick...');
const onClicks: ContextMenuProps[] = existingOnClick && 'subitems' in existingOnClick ? existingOnClick.subitems : [];
onClicks.push({ description: 'Edit onChecked Script', event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.Document, undefined, 'onCheckedClick'), 'edit onCheckedClick'), icon: 'edit' });
@@ -254,7 +280,6 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
moveDocument={returnFalse}
removeDocument={returnFalse}
whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
- bringToFront={returnFalse}
/>
);
}
@@ -268,7 +293,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
@observable _renderCount = 1;
@computed get treeViewElements() {
TraceMobx();
- const dragAction = StrCast(this.Document.childDragAction) as dropActionType;
+ const dragAction = StrCast(this.Document.childDragAction) as any 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))));
@@ -347,9 +372,8 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
renderDepth={this._props.renderDepth + 1}
focus={emptyFunction}
styleProvider={this._props.styleProvider}
- docViewPath={returnEmptyDoclist}
+ containerViewPath={returnEmptyDoclist}
whenChildContentsActiveChanged={emptyFunction}
- bringToFront={emptyFunction}
childFilters={this._props.childFilters}
childFiltersByRanges={this._props.childFiltersByRanges}
searchFilterDocs={this._props.searchFilterDocs}
@@ -447,20 +471,19 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
{!(this.Document instanceof Doc) || !this.treeChildren ? null : this.Document.treeView_HasOverlay ? (
<CollectionFreeFormView
{...this._props}
- setContentView={emptyFunction}
+ setContentViewBox={emptyFunction}
NativeWidth={returnZero}
NativeHeight={returnZero}
pointerEvents={this._props.isContentActive() && SnappingManager.IsDragging ? returnAll : returnNone}
isAnnotationOverlay={true}
isAnnotationOverlayScrollable={true}
- childDocumentsActive={this._props.isDocumentActive}
+ childDocumentsActive={this._props.isContentActive}
fieldKey={this._props.fieldKey + '_annotations'}
- dropAction="move"
+ dropAction={dropActionType.move}
select={emptyFunction}
addDocument={this.addAnnotationDocument}
removeDocument={this.remAnnotationDocument}
moveDocument={this.moveAnnotationDocument}
- bringToFront={emptyFunction}
renderDepth={this._props.renderDepth + 1}>
{this.content}
</CollectionFreeFormView>
@@ -470,4 +493,13 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
</div>
);
}
+ static addTreeFolder(container: Doc) {
+ TreeView._editTitleOnLoad = { id: Utils.GenerateGuid(), parent: undefined };
+ const opts = { title: 'Untitled folder', _dragOnlyWithinContainer: true, isFolder: true };
+ return Doc.AddDocToList(container, 'data', Docs.Create.TreeDocument([], opts, TreeView._editTitleOnLoad.id));
+ }
}
+
+ScriptingGlobals.add(function addTreeFolder(doc: Doc) {
+ CollectionTreeView.addTreeFolder(doc);
+});