diff options
| author | bobzel <zzzman@gmail.com> | 2023-06-23 21:44:01 -0400 |
|---|---|---|
| committer | bobzel <zzzman@gmail.com> | 2023-06-23 21:44:01 -0400 |
| commit | 85c017527f209c9d007d67ac70958843ab45e729 (patch) | |
| tree | e2649860002e0c60e98d84439a67235002ddd9a4 /src/client/views/collections/CollectionDockingView.tsx | |
| parent | e9d5dbeef2bf1dab9dfb863d970b70b3074e3d0a (diff) | |
| parent | 1429ab79eac9aa316082f52c14c576f6b3a97111 (diff) | |
Merge branch 'master' into heartbeat
Diffstat (limited to 'src/client/views/collections/CollectionDockingView.tsx')
| -rw-r--r-- | src/client/views/collections/CollectionDockingView.tsx | 166 |
1 files changed, 94 insertions, 72 deletions
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 92319d080..a5d7e7864 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -6,7 +6,7 @@ import { Doc, DocListCast, Opt } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; import { InkTool } from '../../../fields/InkField'; import { List } from '../../../fields/List'; -import { Cast, ImageCast, NumCast, StrCast } from '../../../fields/Types'; +import { ImageCast, NumCast, StrCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; import { inheritParentAcls } from '../../../fields/util'; import { emptyFunction, incrementTitleCopy } from '../../../Utils'; @@ -20,6 +20,10 @@ import { SelectionManager } from '../../util/SelectionManager'; import { undoBatch, UndoManager } from '../../util/UndoManager'; import { DashboardView } from '../DashboardView'; import { LightboxView } from '../LightboxView'; +import { OpenWhere, OpenWhereMod } from '../nodes/DocumentView'; +import { OverlayView } from '../OverlayView'; +import { ScriptingRepl } from '../ScriptingRepl'; +import { UndoStack } from '../UndoStack'; import './CollectionDockingView.scss'; import { CollectionFreeFormView } from './collectionFreeForm'; import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView'; @@ -30,7 +34,7 @@ const _global = (window /* browser */ || global) /* node */ as any; @observer export class CollectionDockingView extends CollectionSubView() { @observable public static Instance: CollectionDockingView | undefined; - public static makeDocumentConfig(document: Doc, panelName?: string, width?: number) { + public static makeDocumentConfig(document: Doc, panelName?: string, width?: number, keyValue?: boolean) { return { type: 'react-component', component: 'DocumentFrameRenderer', @@ -38,6 +42,7 @@ export class CollectionDockingView extends CollectionSubView() { width: width, props: { documentId: document[Id], + keyValue, panelName, // name of tab that can be used to close or replace its contents }, }; @@ -81,6 +86,7 @@ export class CollectionDockingView extends CollectionSubView() { tabItemDropped = () => DragManager.CompleteWindowDrag?.(false); tabDragStart = (proxy: any, finishDrag?: (aborted: boolean) => void) => { + this._flush = this._flush ?? UndoManager.StartBatch('tab move'); const dashDoc = proxy?._contentItem?.tab?.DashDoc as Doc; dashDoc && (DragManager.DocDragData = new DragManager.DocumentDragData([proxy._contentItem.tab.DashDoc])); DragManager.CompleteWindowDrag = (aborted: boolean) => { @@ -88,12 +94,12 @@ export class CollectionDockingView extends CollectionSubView() { proxy._dragListener.AbortDrag(); if (this._flush) { this._flush.cancel(); // cancel the undo change being logged - this._flush = undefined; this.setupGoldenLayout(); // restore golden layout to where it was before the drag (this is a no-op when using StartOtherDrag because the proxy dragged item was never in the golden layout) } DragManager.CompleteWindowDrag = undefined; } finishDrag?.(aborted); + setTimeout(this.endUndoBatch, 100); }; }; @undoBatch @@ -123,12 +129,12 @@ export class CollectionDockingView extends CollectionSubView() { SelectionManager.DeselectAll(); const instance = CollectionDockingView.Instance; if (instance) { - if (doc._viewType === CollectionViewType.Docking && doc.layoutKey === 'layout') { + if (doc._type_collection === CollectionViewType.Docking && doc.layout_fieldKey === 'layout') { return DashboardView.openDashboard(doc); } const newItemStackConfig = { type: 'stack', - content: [CollectionDockingView.makeDocumentConfig(Doc.MakeAlias(doc))], + content: [CollectionDockingView.makeDocumentConfig(Doc.MakeEmbedding(doc))], }; const docconfig = instance._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, instance._goldenLayout); instance._goldenLayout.root.contentItems[0].addChild(docconfig); @@ -142,10 +148,10 @@ export class CollectionDockingView extends CollectionSubView() { @undoBatch @action - public static ReplaceTab(document: Doc, panelName: string, stack: any, addToSplit?: boolean): boolean { + public static ReplaceTab(document: Doc, panelName: OpenWhereMod, stack: any, addToSplit?: boolean, keyValue?: boolean): boolean { const instance = CollectionDockingView.Instance; if (!instance) return false; - const newConfig = CollectionDockingView.makeDocumentConfig(document, panelName); + const newConfig = CollectionDockingView.makeDocumentConfig(document, panelName, undefined, keyValue); if (!panelName && stack) { const activeContentItemIndex = stack.contentItems.findIndex((item: any) => item.config === stack._activeContentItem.config); const newContentItem = stack.layoutManager.createContentItem(newConfig, instance._goldenLayout); @@ -155,30 +161,30 @@ export class CollectionDockingView extends CollectionSubView() { } const tab = Array.from(instance.tabMap.keys()).find(tab => tab.contentItem.config.props.panelName === panelName); if (tab) { - tab.header.parent.addChild(newConfig, undefined); const j = tab.header.parent.contentItems.indexOf(tab.contentItem); - !addToSplit && j !== -1 && tab.header.parent.contentItems[j].remove(); - return instance.layoutChanged(); + if (newConfig.props.documentId !== tab.header.parent.contentItems[j].config.props.documentId) { + tab.header.parent.addChild(newConfig, undefined); + !addToSplit && j !== -1 && tab.header.parent.contentItems[j].remove(); + return instance.layoutChanged(); + } + return false; } return CollectionDockingView.AddSplit(document, panelName, stack, panelName); } @undoBatch - public static ToggleSplit(doc: Doc, location: string, stack?: any, panelName?: string) { - return CollectionDockingView.Instance && Array.from(CollectionDockingView.Instance.tabMap.keys()).findIndex(tab => tab.DashDoc === doc) !== -1 - ? CollectionDockingView.CloseSplit(doc) - : CollectionDockingView.AddSplit(doc, location, stack, panelName); + public static ToggleSplit(doc: Doc, location: OpenWhereMod, stack?: any, panelName?: string, keyValue?: boolean) { + return Array.from(CollectionDockingView.Instance?.tabMap.keys() ?? []).findIndex(tab => tab.DashDoc === doc) !== -1 ? CollectionDockingView.CloseSplit(doc) : CollectionDockingView.AddSplit(doc, location, stack, panelName, keyValue); } // // Creates a split on any side of the docking view based on the passed input pullSide and then adds the Document to the requested side // - @undoBatch @action - public static AddSplit(document: Doc, pullSide: string, stack?: any, panelName?: string) { - if (document?._viewType === CollectionViewType.Docking) return DashboardView.openDashboard(document); + public static AddSplit(document: Doc, pullSide: OpenWhereMod, stack?: any, panelName?: string, keyValue?: boolean) { + if (document?._type_collection === CollectionViewType.Docking && !keyValue) return DashboardView.openDashboard(document); if (!CollectionDockingView.Instance) return false; - const tab = Array.from(CollectionDockingView.Instance.tabMap).find(tab => tab.DashDoc === document); + const tab = Array.from(CollectionDockingView.Instance.tabMap).find(tab => tab.DashDoc === document && !keyValue); if (tab) { tab.header.parent.setActiveContentItem(tab.contentItem); return true; @@ -186,11 +192,13 @@ export class CollectionDockingView extends CollectionSubView() { const instance = CollectionDockingView.Instance; const glayRoot = instance._goldenLayout.root; if (!instance) return false; - const docContentConfig = CollectionDockingView.makeDocumentConfig(document, panelName); + const docContentConfig = CollectionDockingView.makeDocumentConfig(document, panelName, undefined, keyValue); + CollectionDockingView.Instance._flush = CollectionDockingView.Instance._flush ?? UndoManager.StartBatch('Add Split'); + setTimeout(CollectionDockingView.Instance.endUndoBatch, 100); if (!pullSide && stack) { stack.addChild(docContentConfig, undefined); - stack.setActiveContentItem(stack.contentItems[stack.contentItems.length - 1]); + setTimeout(() => stack.setActiveContentItem(stack.contentItems[stack.contentItems.length - 1])); } else { const newContentItem = () => { const newItem = glayRoot.layoutManager.createContentItem({ type: 'stack', content: [docContentConfig] }, instance._goldenLayout); @@ -208,14 +216,15 @@ export class CollectionDockingView extends CollectionSubView() { // if row switch (pullSide) { default: - case 'right': + case OpenWhereMod.none: + case OpenWhereMod.right: glayRoot.contentItems[0].addChild(newContentItem()); break; - case 'left': + case OpenWhereMod.left: glayRoot.contentItems[0].addChild(newContentItem(), 0); break; - case 'top': - case 'bottom': + case OpenWhereMod.top: + case OpenWhereMod.bottom: // if not going in a row layout, must add already existing content into column const rowlayout = glayRoot.contentItems[0]; const newColumn = rowlayout.layoutManager.createContentItem({ type: 'column' }, instance._goldenLayout); @@ -362,16 +371,30 @@ export class CollectionDockingView extends CollectionSubView() { !LightboxView.LightboxDoc && cur && this._goldenLayout?.updateSize(cur.getBoundingClientRect().width, cur.getBoundingClientRect().height); }; + endUndoBatch = () => { + const json = JSON.stringify(this._goldenLayout.toConfig()); + const matches = json.match(/\"documentId\":\"[a-z0-9-]+\"/g); + const docids = matches?.map(m => m.replace('"documentId":"', '').replace('"', '')); + const docs = !docids + ? [] + : docids + .map(id => DocServer.GetCachedRefField(id)) + .filter(f => f) + .map(f => f as Doc); + const changesMade = this.props.Document.dockingConfig !== json; + if (changesMade) { + this.props.Document.dockingConfig = json; + this.props.Document.data = new List<Doc>(docs); + } + this._flush?.end(); + this._flush = undefined; + }; + @action onPointerUp = (e: MouseEvent): void => { window.removeEventListener('pointerup', this.onPointerUp); - const flush = this._flush; - this._flush = undefined; - if (flush) { - DragManager.CompleteWindowDrag = undefined; - if (!this.stateChanged()) flush.cancel(); - else flush.end(); - } + DragManager.CompleteWindowDrag = undefined; + setTimeout(this.endUndoBatch, 100); }; @action @@ -385,9 +408,8 @@ export class CollectionDockingView extends CollectionSubView() { window.addEventListener('mouseup', this.onPointerUp); if (!htmlTarget.closest('*.lm_content') && (htmlTarget.closest('*.lm_tab') || htmlTarget.closest('*.lm_stack'))) { const className = typeof htmlTarget.className === 'string' ? htmlTarget.className : ''; - if (!className.includes('lm_close') && !className.includes('lm_maximise')) { - this._flush = UndoManager.StartBatch('golden layout edit'); - } + if (className.includes('lm_maximise')) this._flush = UndoManager.StartBatch('tab maximize'); + else if (!className.includes('lm_close')) DocServer.UPDATE_SERVER_CACHE(); } } if (!InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE) && !InteractionUtils.IsType(e, InteractionUtils.PENTYPE) && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) { @@ -401,11 +423,10 @@ export class CollectionDockingView extends CollectionSubView() { const _width = Number(getComputedStyle(content).width.replace('px', '')); const _height = Number(getComputedStyle(content).height.replace('px', '')); return CollectionFreeFormView.UpdateIcon(this.layoutDoc[Id] + '-icon' + new Date().getTime(), content, _width, _height, _width, _height, 0, 1, true, this.layoutDoc[Id] + '-icon', (iconFile, _nativeWidth, _nativeHeight) => { - const img = Docs.Create.ImageDocument(new ImageField(iconFile), { title: this.rootDoc.title + '-icon', _width, _height, _nativeWidth, _nativeHeight }); const proto = this.dataDoc; // Cast(img.proto, Doc, null)!; - proto['thumb-nativeWidth'] = _width; - proto['thumb-nativeHeight'] = _height; - this.dataDoc.thumb = new ImageField(iconFile); + proto['thumb_nativeWidth'] = _width; + proto['thumb_nativeHeight'] = _height; + proto.thumb = new ImageField(iconFile); }); } } @@ -426,11 +447,11 @@ export class CollectionDockingView extends CollectionSubView() { .map(f => f as Doc); const newtabs = origtabs.map(origtab => { const origtabdocs = DocListCast(origtab.data); - const newtab = origtabdocs.length ? Doc.MakeCopy(origtab, true, undefined, true) : Doc.MakeAlias(origtab); - const newtabdocs = origtabdocs.map(origtabdoc => Doc.MakeAlias(origtabdoc)); + const newtab = origtabdocs.length ? Doc.MakeCopy(origtab, true, undefined, true) : Doc.MakeEmbedding(origtab); + const newtabdocs = origtabdocs.map(origtabdoc => Doc.MakeEmbedding(origtabdoc)); if (newtabdocs.length) { Doc.GetProto(newtab).data = new List<Doc>(newtabdocs); - newtabdocs.forEach(ntab => (ntab.context = newtab)); + newtabdocs.forEach(ntab => (ntab.embedContainer = newtab)); } json = json.replace(origtab[Id], newtab[Id]); return newtab; @@ -444,26 +465,13 @@ export class CollectionDockingView extends CollectionSubView() { stateChanged = () => { this._ignoreStateChange = JSON.stringify(this._goldenLayout.toConfig()); const json = JSON.stringify(this._goldenLayout.toConfig()); - const matches = json.match(/\"documentId\":\"[a-z0-9-]+\"/g); - const docids = matches?.map(m => m.replace('"documentId":"', '').replace('"', '')); - const docs = !docids - ? [] - : docids - .map(id => DocServer.GetCachedRefField(id)) - .filter(f => f) - .map(f => f as Doc); - const changesMade = this.props.Document.dockcingConfig !== json; - if (changesMade && !this._flush) { - UndoManager.RunInBatch(() => { - this.props.Document.dockingConfig = json; - this.props.Document.data = new List<Doc>(docs); - }, 'state changed'); - } + const changesMade = this.props.Document.dockingConfig !== json; return changesMade; }; tabDestroyed = (tab: any) => { - if (tab.DashDoc && ![DocumentType.KVP, DocumentType.PRES].includes(tab.DashDoc?.type)) { + this._flush = this._flush ?? UndoManager.StartBatch('tab movement'); + if (tab.DashDoc && ![DocumentType.PRES].includes(tab.DashDoc?.type) && !tab.contentItem.config.props.keyValue) { Doc.AddDocToList(Doc.MyHeaderBar, 'data', tab.DashDoc); Doc.AddDocToList(Doc.MyRecentlyClosed, 'data', tab.DashDoc, undefined, true, true); } @@ -473,7 +481,6 @@ export class CollectionDockingView extends CollectionSubView() { Doc.RemoveDocFromList(dview, fieldKey, tab.DashDoc); this.tabMap.delete(tab); tab._disposers && Object.values(tab._disposers).forEach((disposer: any) => disposer?.()); - //tab.reactComponents?.forEach((ele: any) => ReactDOM.unmountComponentAtNode(ele)); this.stateChanged(); } }; @@ -491,12 +498,12 @@ export class CollectionDockingView extends CollectionSubView() { const docToAdd = Docs.Create.FreeformDocument([], { _width: this.props.PanelWidth(), _height: this.props.PanelHeight(), - _backgroundGridShow: true, - _fitWidth: true, + _freeform_backgroundGrid: true, + _layout_fitWidth: true, title: `Untitled Tab ${NumCast(dashboard['pane-count'])}`, }); this.props.Document.isShared && inheritParentAcls(this.props.Document, docToAdd); - CollectionDockingView.AddSplit(docToAdd, '', stack); + CollectionDockingView.AddSplit(docToAdd, OpenWhereMod.none, stack); } }); @@ -507,7 +514,12 @@ export class CollectionDockingView extends CollectionSubView() { action(() => { //if (confirm('really close this?')) { if ((!stack.parent.isRoot && !stack.parent.parent.isRoot) || stack.parent.contentItems.length > 1) { + const batch = UndoManager.StartBatch('close stack'); stack.remove(); + setTimeout(() => { + this.stateChanged(); + batch.end(); + }); } else { alert('cant delete the last stack'); } @@ -529,12 +541,12 @@ export class CollectionDockingView extends CollectionSubView() { const docToAdd = Docs.Create.FreeformDocument([], { _width: this.props.PanelWidth(), _height: this.props.PanelHeight(), - _fitWidth: true, - _backgroundGridShow: true, + _layout_fitWidth: true, + _freeform_backgroundGrid: true, title: `Untitled Tab ${NumCast(dashboard['pane-count'])}`, }); this.props.Document.isShared && inheritParentAcls(this.props.Document, docToAdd); - CollectionDockingView.AddSplit(docToAdd, '', stack); + CollectionDockingView.AddSplit(docToAdd, OpenWhereMod.none, stack); } }) ); @@ -563,25 +575,35 @@ export class CollectionDockingView extends CollectionSubView() { ScriptingGlobals.add( function openInLightbox(doc: any) { - LightboxView.AddDocTab(doc, 'lightbox'); + LightboxView.AddDocTab(doc, OpenWhere.lightbox); }, 'opens up document in a lightbox', '(doc: any)' ); ScriptingGlobals.add( - function openOnRight(doc: any) { - return CollectionDockingView.AddSplit(doc, 'right'); + function openDoc(doc: any, where: OpenWhere) { + switch (where) { + case OpenWhere.addRight: + return CollectionDockingView.AddSplit(doc, OpenWhereMod.right); + case OpenWhere.overlay: + // prettier-ignore + switch (doc) { + case '<ScriptingRepl />': return OverlayView.Instance.addWindow(<ScriptingRepl />, { x: 300, y: 100, width: 200, height: 200, title: 'Scripting REPL' }); + case "<UndoStack>": return OverlayView.Instance.addWindow(<UndoStack />, { x: 300, y: 100, width: 200, height: 200, title: 'Scripting REPL' }); + } + Doc.AddToMyOverlay(doc); + } }, - 'opens up document in tab on right side of the screen', + 'opens up document in location specified', '(doc: any)' ); ScriptingGlobals.add( - function openInOverlay(doc: any) { - return Doc.AddDocToList(Doc.MyOverlayDocs, undefined, doc); + function openRepl() { + return 'openRepl'; }, 'opens up document in screen overlay layer', '(doc: any)' ); -ScriptingGlobals.add(function useRightSplit(doc: any, shiftKey?: boolean) { - CollectionDockingView.ReplaceTab(doc, 'right', undefined, shiftKey); +ScriptingGlobals.add(function useRightSplit(doc: any, addToRightSplit?: boolean) { + CollectionDockingView.ReplaceTab(doc, OpenWhereMod.right, undefined, addToRightSplit); }); |
