aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/TabDocView.tsx
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2024-05-02 00:39:31 -0400
committerbobzel <zzzman@gmail.com>2024-05-02 00:39:31 -0400
commitdd08c20ec6df3fad6ecd6b16c787f10b0c23feb4 (patch)
tree11f2b1b741369997af567983df0316923e08d780 /src/client/views/collections/TabDocView.tsx
parent76838b7b3842c9b184e6459e29796dd14de37e8d (diff)
lots more dependency cycle unwinding.
Diffstat (limited to 'src/client/views/collections/TabDocView.tsx')
-rw-r--r--src/client/views/collections/TabDocView.tsx216
1 files changed, 116 insertions, 100 deletions
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 2d900bb73..2d8b2564d 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -9,7 +9,7 @@ import * as ReactDOM from 'react-dom/client';
import { ClientUtils, DashColor, lightOrDark, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick } from '../../../ClientUtils';
import { emptyFunction } from '../../../Utils';
import { Doc, Opt } from '../../../fields/Doc';
-import { DocData } from '../../../fields/DocSymbols';
+import { DocData, DocViews } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
import { List } from '../../../fields/List';
import { FieldId } from '../../../fields/RefField';
@@ -18,10 +18,8 @@ import { Cast, DocCast, NumCast, StrCast, toList } from '../../../fields/Types';
import { DocServer } from '../../DocServer';
import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
import { Docs } from '../../documents/Documents';
-import { DocumentManager } from '../../util/DocumentManager';
import { DragManager } from '../../util/DragManager';
import { dropActionType } from '../../util/DropActionTypes';
-import { SelectionManager } from '../../util/SelectionManager';
import { SnappingManager } from '../../util/SnappingManager';
import { Transform } from '../../util/Transform';
import { UndoManager, undoable } from '../../util/UndoManager';
@@ -29,7 +27,8 @@ import { DashboardView } from '../DashboardView';
import { LightboxView } from '../LightboxView';
import { ObservableReactComponent } from '../ObservableReactComponent';
import { PinDocView, PinProps } from '../PinFuncs';
-import { DefaultStyleProvider, StyleProp } from '../StyleProvider';
+import { StyleProp } from '../StyleProp';
+import { DefaultStyleProvider } from '../StyleProvider';
import { Colors } from '../global/globalEnums';
import { DocumentView, returnEmptyDocViewList } from '../nodes/DocumentView';
import { FieldViewProps } from '../nodes/FieldView';
@@ -194,9 +193,101 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
_mainCont: HTMLDivElement | null = null;
_tabReaction: IReactionDisposer | undefined;
+ /**
+ * Adds a document to the presentation view
+ * */
+ @action
+ public static PinDoc(docIn: Doc | Doc[], pinProps: PinProps) {
+ const docs = toList(docIn);
+
+ const batch = UndoManager.StartBatch('Pin doc to pres trail');
+ const curPres = Doc.ActivePresentation ?? Doc.MakeCopy(Doc.UserDoc().emptyTrail as Doc, true);
+
+ if (!Doc.ActivePresentation) {
+ Doc.AddDocToList(Doc.MyTrails, 'data', curPres);
+ Doc.ActivePresentation = curPres;
+ }
+
+ docs.forEach(doc => {
+ // Edge Case 1: Cannot pin document to itself
+ if (doc === curPres) {
+ alert('Cannot pin presentation document to itself');
+ return;
+ }
+ const anchorDoc = DocumentView.getDocumentView(doc)?.ComponentView?.getAnchor?.(false, pinProps);
+ const pinDoc = anchorDoc?.type === DocumentType.CONFIG ? anchorDoc : Docs.Create.ConfigDocument({});
+ const targDoc = (pinDoc.presentation_targetDoc = anchorDoc ?? doc);
+ pinDoc.title = doc.title + ' - Slide';
+ pinDoc.data = targDoc.type === DocumentType.PRES ? ComputedField.MakeFunction('copyField(this.presentation_targetDoc.data') : new List<Doc>(); // the children of the embedding's layout are the presentation slide children. the embedding's data field might be children of a collection, PDF data, etc -- in any case we don't want the tree view to "see" this data
+ pinDoc.presentation_movement = doc.type === DocumentType.SCRIPTING || pinProps?.pinDocLayout ? PresMovement.None : PresMovement.Zoom;
+ pinDoc.presentation_duration = pinDoc.presentation_duration ?? 1000;
+ pinDoc.presentation_groupWithUp = false;
+ Doc.SetContainer(pinDoc, curPres);
+ // these should potentially all be props passed down by the CollectionTreeView to the TreeView elements. That way the PresBox could configure all of its children at render time
+ pinDoc.treeView = ''; // not really needed, but makes key value pane look better
+ pinDoc.treeView_RenderAsBulletHeader = true; // forces a tree view to render the document next to the bullet in the header area
+ pinDoc.treeView_HeaderWidth = '100%'; // forces the header to grow to be the same size as its largest sibling.
+ pinDoc.treeView_FieldKey = 'data'; // tree view will treat the 'data' field as the field where the hierarchical children are located instead of using the document's layout string field
+ pinDoc.treeView_ExpandedView = 'data'; // in case the data doc has an expandedView set, this will mask that field and use the 'data' field when expanding the tree view
+ pinDoc.treeView_HideHeaderIfTemplate = true; // this will force the document to render itself as the tree view header
+ const duration = NumCast(doc[`${Doc.LayoutFieldKey(pinDoc)}_duration`], null);
+
+ if (pinProps.pinViewport) PinDocView(pinDoc, pinProps, anchorDoc ?? doc);
+ if (!pinProps?.audioRange && duration !== undefined) {
+ pinDoc.presentation_mediaStart = 'manual';
+ pinDoc.presentation_mediaStop = 'manual';
+ }
+ if (pinProps?.activeFrame !== undefined) {
+ pinDoc.config_activeFrame = pinProps?.activeFrame;
+ pinDoc.title = doc.title + ' (move)';
+ pinDoc.presentation_movement = PresMovement.Pan;
+ }
+ if (pinProps?.currentFrame !== undefined) {
+ pinDoc.config_currentFrame = pinProps?.currentFrame;
+ pinDoc.title = doc.title + ' (move)';
+ pinDoc.presentation_movement = PresMovement.Pan;
+ }
+ if (pinDoc.stroke_isInkMask) {
+ pinDoc.presentation_hideAfter = true;
+ pinDoc.presentation_hideBefore = true;
+ pinDoc.presentation_movement = PresMovement.None;
+ }
+ if (curPres.expandBoolean) pinDoc.presentation_expandInlineButton = true;
+ Doc.AddDocToList(curPres, 'data', pinDoc, PresBox.Instance?.sortArray()?.lastElement());
+ PresBox.Instance?.clearSelectedArray();
+ pinDoc && PresBox.Instance?.addToSelectedArray(pinDoc); // Update selected array
+ });
+ if (
+ // open the presentation trail if it's not already opened
+ !Array.from(CollectionDockingView.Instance?.tabMap ?? [])
+ .map(d => d.DashDoc)
+ .includes(curPres)
+ ) {
+ if (Doc.IsInMyOverlay(curPres)) Doc.RemFromMyOverlay(curPres);
+ CollectionDockingView.AddSplit(curPres, OpenWhereMod.right);
+ setTimeout(() => DocumentView.showDocument(docs.lastElement(), { willPan: true }), 100); // keeps the pinned doc in view since the sidebar shifts things
+ }
+ setTimeout(batch.end, 500); // need to wait until dockingview (goldenlayout) updates all its structurs
+ }
+
+ static Activate = (tabDoc: Doc) => {
+ const tab = Array.from(CollectionDockingView.Instance?.tabMap!).find(findTab => findTab.DashDoc === tabDoc && !findTab.contentItem.config.props.keyValue);
+ tab?.header.parent.setActiveContentItem(tab.contentItem); // glr: Panning does not work when this is set - (this line is for trying to make a tab that is not topmost become topmost)
+ return tab !== undefined;
+ };
+ // static ActivateTabView(doc: Doc) {
+ // const tabView = Array.from(TabDocView._allTabs).find(view => view._document === doc);
+ // if (!tabView?._activated && tabView?._document) {
+ // TabDocView.Activate(tabView?._document);
+ // return tabView;
+ // }
+ // return undefined;
+ // }
constructor(props: any) {
super(props);
makeObservable(this);
+ DocumentView.activateTabView = TabDocView.Activate;
+ DocumentView.PinDoc = TabDocView.PinDoc;
}
@observable _activated: boolean = false;
@@ -205,8 +296,14 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
@observable _hovering = false;
@observable _isActive: boolean = false;
@observable _isAnyChildContentActive = false;
+ public static IsSelected = (doc?: Doc) => {
+ if (Array.from(doc?.[DocViews] ?? []).some(dv => dv?.IsSelected)) {
+ return true;
+ }
+ return false;
+ };
@computed get _isUserActivated() {
- return SelectionManager.IsSelected(this._document) || this._isAnyChildContentActive;
+ return TabDocView.IsSelected(this._document) || this._isAnyChildContentActive;
}
get _isContentActive() {
return this._isUserActivated || this._hovering;
@@ -279,12 +376,12 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
returnFalse,
action(clickEv => {
if (this.view) {
- SelectionManager.SelectView(this.view, false);
+ DocumentView.SelectView(this.view, false);
const child = getChild();
simulateMouseClick(child, clickEv.clientX, clickEv.clientY + 30, clickEv.screenX, clickEv.screenY + 30);
} else {
this._activated = true;
- setTimeout(() => this.view && SelectionManager.SelectView(this.view, false));
+ setTimeout(() => this.view && DocumentView.SelectView(this.view, false));
}
})
);
@@ -350,7 +447,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
// select the tab document when the tab is directly clicked and activate the tab whenver the tab document is selected
titleEle.onpointerdown = action((e: any) => {
if (e.target.className !== 'lm_iconWrap') {
- if (this.view) SelectionManager.SelectView(this.view, false);
+ if (this.view) DocumentView.SelectView(this.view, false);
else this._activated = true;
if (Date.now() - titleEle.lastClick < 1000) titleEle.select();
titleEle.lastClick = Date.now();
@@ -358,7 +455,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
}
});
tab._disposers.selectionDisposer = reaction(
- () => SelectionManager.IsSelected(this._document),
+ () => TabDocView.IsSelected(this._document),
action(selected => {
if (selected) this._activated = true;
if (selected && tab.contentItem !== tab.header.parent.getActiveContentItem()) {
@@ -382,89 +479,12 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
.off('click') // unbind the current click handler
.click(() => {
Object.values(tab._disposers).forEach((disposer: any) => disposer?.());
- SelectionManager.DeselectAll();
+ DocumentView.DeselectAll();
UndoManager.RunInBatch(() => tab.contentItem.remove(), 'delete tab');
});
}
};
- /**
- * Adds a document to the presentation view
- * */
- @action
- public static PinDoc(docIn: Doc | Doc[], pinProps: PinProps) {
- const docs = toList(docIn);
-
- const batch = UndoManager.StartBatch('Pin doc to pres trail');
- const curPres = Doc.ActivePresentation ?? Doc.MakeCopy(Doc.UserDoc().emptyTrail as Doc, true);
-
- if (!Doc.ActivePresentation) {
- Doc.AddDocToList(Doc.MyTrails, 'data', curPres);
- Doc.ActivePresentation = curPres;
- }
-
- docs.forEach(doc => {
- // Edge Case 1: Cannot pin document to itself
- if (doc === curPres) {
- alert('Cannot pin presentation document to itself');
- return;
- }
- const anchorDoc = DocumentManager.Instance.getDocumentView(doc)?.ComponentView?.getAnchor?.(false, pinProps);
- const pinDoc = anchorDoc?.type === DocumentType.CONFIG ? anchorDoc : Docs.Create.ConfigDocument({});
- const targDoc = (pinDoc.presentation_targetDoc = anchorDoc ?? doc);
- pinDoc.title = doc.title + ' - Slide';
- pinDoc.data = targDoc.type === DocumentType.PRES ? ComputedField.MakeFunction('copyField(this.presentation_targetDoc.data') : new List<Doc>(); // the children of the embedding's layout are the presentation slide children. the embedding's data field might be children of a collection, PDF data, etc -- in any case we don't want the tree view to "see" this data
- pinDoc.presentation_movement = doc.type === DocumentType.SCRIPTING || pinProps?.pinDocLayout ? PresMovement.None : PresMovement.Zoom;
- pinDoc.presentation_duration = pinDoc.presentation_duration ?? 1000;
- pinDoc.presentation_groupWithUp = false;
- Doc.SetContainer(pinDoc, curPres);
- // these should potentially all be props passed down by the CollectionTreeView to the TreeView elements. That way the PresBox could configure all of its children at render time
- pinDoc.treeView = ''; // not really needed, but makes key value pane look better
- pinDoc.treeView_RenderAsBulletHeader = true; // forces a tree view to render the document next to the bullet in the header area
- pinDoc.treeView_HeaderWidth = '100%'; // forces the header to grow to be the same size as its largest sibling.
- pinDoc.treeView_FieldKey = 'data'; // tree view will treat the 'data' field as the field where the hierarchical children are located instead of using the document's layout string field
- pinDoc.treeView_ExpandedView = 'data'; // in case the data doc has an expandedView set, this will mask that field and use the 'data' field when expanding the tree view
- pinDoc.treeView_HideHeaderIfTemplate = true; // this will force the document to render itself as the tree view header
- const duration = NumCast(doc[`${Doc.LayoutFieldKey(pinDoc)}_duration`], null);
-
- if (pinProps.pinViewport) PinDocView(pinDoc, pinProps, anchorDoc ?? doc);
- if (!pinProps?.audioRange && duration !== undefined) {
- pinDoc.presentation_mediaStart = 'manual';
- pinDoc.presentation_mediaStop = 'manual';
- }
- if (pinProps?.activeFrame !== undefined) {
- pinDoc.config_activeFrame = pinProps?.activeFrame;
- pinDoc.title = doc.title + ' (move)';
- pinDoc.presentation_movement = PresMovement.Pan;
- }
- if (pinProps?.currentFrame !== undefined) {
- pinDoc.config_currentFrame = pinProps?.currentFrame;
- pinDoc.title = doc.title + ' (move)';
- pinDoc.presentation_movement = PresMovement.Pan;
- }
- if (pinDoc.stroke_isInkMask) {
- pinDoc.presentation_hideAfter = true;
- pinDoc.presentation_hideBefore = true;
- pinDoc.presentation_movement = PresMovement.None;
- }
- if (curPres.expandBoolean) pinDoc.presentation_expandInlineButton = true;
- Doc.AddDocToList(curPres, 'data', pinDoc, PresBox.Instance?.sortArray()?.lastElement());
- PresBox.Instance?.clearSelectedArray();
- pinDoc && PresBox.Instance?.addToSelectedArray(pinDoc); // Update selected array
- });
- if (
- // open the presentation trail if it's not already opened
- !Array.from(CollectionDockingView.Instance?.tabMap ?? [])
- .map(d => d.DashDoc)
- .includes(curPres)
- ) {
- if (Doc.IsInMyOverlay(curPres)) Doc.RemFromMyOverlay(curPres);
- CollectionDockingView.AddSplit(curPres, OpenWhereMod.right);
- setTimeout(() => DocumentManager.Instance.showDocument(docs.lastElement(), { willPan: true }), 100); // keeps the pinned doc in view since the sidebar shifts things
- }
- setTimeout(batch.end, 500); // need to wait until dockingview (goldenlayout) updates all its structurs
- }
-
componentDidMount() {
new _global.ResizeObserver(
action((entries: any) => {
@@ -484,12 +504,12 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
}
componentDidUpdate(prevProps: Readonly<TabDocViewProps>) {
super.componentDidUpdate(prevProps);
- this._view && DocumentManager.Instance.AddView(this._view);
+ this._view && DocumentView.addView(this._view);
}
componentWillUnmount() {
this._tabReaction?.();
- this._view && DocumentManager.Instance.RemoveView(this._view);
+ this._view && DocumentView.removeView(this._view);
runInAction(() => TabDocView._allTabs.delete(this));
this._props.glContainer.layoutManager.off('activeContentItemChanged', this.onActiveContentItemChanged);
@@ -503,7 +523,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
private onActiveContentItemChanged(contentItem: any) {
if (!contentItem || (this.stack === contentItem.parent && ((contentItem?.tab === this.tab && !this._isActive) || (contentItem?.tab !== this.tab && this._isActive)))) {
this._activated = this._isActive = !contentItem || contentItem?.tab === this.tab;
- if (!this._view && this.tab?.contentItem?.config?.props?.panelName !== TabDocView.DontSelectOnActivate) setTimeout(() => SelectionManager.SelectView(this._view, false));
+ if (!this._view && this.tab?.contentItem?.config?.props?.panelName !== TabDocView.DontSelectOnActivate) setTimeout(() => DocumentView.SelectView(this._view, false));
!this._isActive && this._document && Doc.UnBrushDoc(this._document); // bcz: bad -- trying to simulate a pointer leave event when a new tab is opened up on top of an existing one.
}
}
@@ -517,7 +537,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
// lightbox - will add the document to any collection along the path from the document to the docking view that has a field isLightbox. if none is found, it adds to the full screen lightbox
addDocTab = (docsIn: Doc | Doc[], location: OpenWhere) => {
const docs = toList(docsIn);
- SelectionManager.DeselectAll();
+ DocumentView.DeselectAll();
const whereFields = location.split(':');
const keyValue = whereFields.includes(OpenWhereMod.keyvalue);
const whereMods = whereFields.length > 1 ? (whereFields[1] as OpenWhereMod) : OpenWhereMod.none;
@@ -527,7 +547,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
switch (whereFields[0]) {
case undefined:
case OpenWhere.lightbox: if (this.layoutDoc?._isLightbox) {
- const lightboxView = !docs[0].annotationOn && DocCast(docs[0].embedContainer) ? DocumentManager.Instance.getFirstDocumentView(DocCast(docs[0].embedContainer)) : undefined;
+ const lightboxView = !docs[0].annotationOn && DocCast(docs[0].embedContainer) ? DocumentView.getFirstDocumentView(DocCast(docs[0].embedContainer)) : undefined;
const data = lightboxView?.dataDoc[Doc.LayoutFieldKey(lightboxView.Document)];
if (lightboxView && (!data || data instanceof List)) {
lightboxView.layoutDoc[Doc.LayoutFieldKey(lightboxView.Document)] = new List<Doc>(docs);
@@ -543,7 +563,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
};
remDocTab = (doc: Doc | Doc[]) => {
if (doc === this._document) {
- SelectionManager.DeselectAll();
+ DocumentView.DeselectAll();
CollectionDockingView.CloseSplit(this._document);
return true;
}
@@ -551,11 +571,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
};
getCurrentFrame = () => NumCast(Cast(PresBox.Instance.activeItem.presentation_targetDoc, Doc, null)._currentFrame);
- static Activate = (tabDoc: Doc) => {
- const tab = Array.from(CollectionDockingView.Instance?.tabMap!).find(findTab => findTab.DashDoc === tabDoc && !findTab.contentItem.config.props.keyValue);
- tab?.header.parent.setActiveContentItem(tab.contentItem); // glr: Panning does not work when this is set - (this line is for trying to make a tab that is not topmost become topmost)
- return tab !== undefined;
- };
+
@action
focusFunc = () => {
if (!this.tab.header.parent._activeContentItem || this.tab.header.parent._activeContentItem !== this.tab.contentItem) {
@@ -586,7 +602,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
<DocumentView
key={this._document[Id]}
ref={action((r: DocumentView) => {
- this._lastView && DocumentManager.Instance.RemoveView(this._lastView);
+ this._lastView && DocumentView.removeView(this._lastView);
this._view = r;
this._lastView = this._view;
})}
@@ -635,7 +651,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
this._mainCont = ref;
if (this._mainCont) {
if (this._lastTab) {
- this._view && DocumentManager.Instance.RemoveView(this._view);
+ this._view && DocumentView.removeView(this._view);
}
this._lastTab = this.tab;
(this._mainCont as any).InitTab = (tab: any) => this.init(tab, this._document);