From da0ffe5d9293bf27c219bbd3c351e11265c89911 Mon Sep 17 00:00:00 2001 From: mathuo <6710312+mathuo@users.noreply.github.com> Date: Sat, 30 Nov 2024 19:52:17 +0000 Subject: [PATCH] feat: experimental work --- .../dockview-core/src/api/component.api.ts | 7 +- .../src/dockview/dockviewComponent.ts | 81 ++++++++++++++++--- .../src/dockview/dockviewPanel.ts | 23 +++++- .../react/dockview/demo-dockview/src/app.tsx | 8 ++ .../demo-dockview/src/gridActions.tsx | 19 +++++ 5 files changed, 121 insertions(+), 17 deletions(-) diff --git a/packages/dockview-core/src/api/component.api.ts b/packages/dockview-core/src/api/component.api.ts index fe7d5c2d3..13af839c0 100644 --- a/packages/dockview-core/src/api/component.api.ts +++ b/packages/dockview-core/src/api/component.api.ts @@ -854,8 +854,11 @@ export class DockviewApi implements CommonApi { /** * Create a component from a serialized object. */ - fromJSON(data: SerializedDockview): void { - this.component.fromJSON(data); + fromJSON( + data: SerializedDockview, + options?: { keepExistingPanels: boolean } + ): void { + this.component.fromJSON(data, options); } /** diff --git a/packages/dockview-core/src/dockview/dockviewComponent.ts b/packages/dockview-core/src/dockview/dockviewComponent.ts index 5a20f5b84..9564dede7 100644 --- a/packages/dockview-core/src/dockview/dockviewComponent.ts +++ b/packages/dockview-core/src/dockview/dockviewComponent.ts @@ -147,6 +147,7 @@ type MoveGroupOrPanelOptions = { position: Position; index?: number; }; + keepEmptyGroups?: boolean; }; export interface FloatingGroupOptions { @@ -219,6 +220,7 @@ export interface IDockviewComponent extends IBaseGrid { onWillClose?: (event: { id: string; window: Window }) => void; } ): Promise; + fromJSON(data: any, options?: { keepExistingPanels: boolean }): void; } export class DockviewComponent @@ -1219,7 +1221,41 @@ export class DockviewComponent return result; } - fromJSON(data: SerializedDockview): void { + fromJSON( + data: SerializedDockview, + options?: { keepExistingPanels: boolean } + ): void { + const existingPanels = new Map(); + const tempGroup = this.createGroup(); + this._groups.delete(tempGroup.api.id); + + if (options?.keepExistingPanels) { + const newPanels = Object.keys(data.panels); + + for (const panel of this.panels) { + if (newPanels.includes(panel.api.id)) { + existingPanels.set(panel.api.id, panel); + } + } + + this.movingLock(() => { + Array.from(existingPanels.values()).forEach((panel) => { + this.moveGroupOrPanel({ + from: { + groupId: panel.api.group.api.id, + panelId: panel.api.id, + }, + to: { + group: tempGroup, + position: 'center', + }, + keepEmptyGroups: true, + }); + // panel.api.moveTo({ group: tempGroup }); + }); + }); + } + this.clear(); if (typeof data !== 'object' || data === null) { @@ -1260,11 +1296,23 @@ export class DockviewComponent * In running this section first we avoid firing lots of 'add' events in the event of a failure * due to a corruption of input data. */ - const panel = this._deserializer.fromJSON( - panels[child], - group - ); - createdPanels.push(panel); + + const existingPanel = existingPanels.get(child); + + if (existingPanel) { + this.movingLock(() => { + tempGroup.model.removePanel(existingPanel); + }); + + createdPanels.push(existingPanel); + existingPanel.updateFromStateModel(panels[child]); + } else { + const panel = this._deserializer.fromJSON( + panels[child], + group + ); + createdPanels.push(panel); + } } this._onDidAddGroup.fire(group); @@ -1276,10 +1324,21 @@ export class DockviewComponent typeof activeView === 'string' && activeView === panel.id; - group.model.openPanel(panel, { - skipSetActive: !isActive, - skipSetGroupActive: true, - }); + const hasExisting = existingPanels.has(panel.api.id); + + if (hasExisting) { + this.movingLock(() => { + group.model.openPanel(panel, { + skipSetActive: !isActive, + skipSetGroupActive: true, + }); + }); + } else { + group.model.openPanel(panel, { + skipSetActive: !isActive, + skipSetGroupActive: true, + }); + } } if (!group.activePanel && group.panels.length > 0) { @@ -1952,7 +2011,7 @@ export class DockviewComponent throw new Error(`No panel with id ${sourceItemId}`); } - if (sourceGroup.model.size === 0) { + if (!options.keepEmptyGroups && sourceGroup.model.size === 0) { // remove the group and do not set a new group as active this.doRemoveGroup(sourceGroup, { skipActive: true }); } diff --git a/packages/dockview-core/src/dockview/dockviewPanel.ts b/packages/dockview-core/src/dockview/dockviewPanel.ts index bf71ca6c1..c070a9c71 100644 --- a/packages/dockview-core/src/dockview/dockviewPanel.ts +++ b/packages/dockview-core/src/dockview/dockviewPanel.ts @@ -27,6 +27,7 @@ export interface IDockviewPanel extends IDisposable, IPanel { group: DockviewGroupPanel, options?: { skipSetActive?: boolean } ): void; + updateFromStateModel(state: GroupviewPanelState): void; init(params: IGroupPanelInitParameters): void; toJSON(): GroupviewPanelState; setTitle(title: string): void; @@ -45,10 +46,10 @@ export class DockviewPanel private _title: string | undefined; private _renderer: DockviewPanelRenderer | undefined; - private readonly _minimumWidth: number | undefined; - private readonly _minimumHeight: number | undefined; - private readonly _maximumWidth: number | undefined; - private readonly _maximumHeight: number | undefined; + private _minimumWidth: number | undefined; + private _minimumHeight: number | undefined; + private _maximumWidth: number | undefined; + private _maximumHeight: number | undefined; get params(): Parameters | undefined { return this._params; @@ -209,6 +210,20 @@ export class DockviewPanel }); } + updateFromStateModel(state: GroupviewPanelState): void { + this._maximumHeight = state.maximumHeight; + this._minimumHeight = state.minimumHeight; + this._maximumWidth = state.maximumWidth; + this._minimumWidth = state.minimumWidth; + + this.update({ params: state.params ?? {} }); + this.setTitle(state.title ?? this.id); + this.setRenderer(state.renderer ?? this.accessor.renderer); + + // state.contentComponent; + // state.tabComponent; + } + public updateParentGroup( group: DockviewGroupPanel, options?: { skipSetActive?: boolean } diff --git a/packages/docs/sandboxes/react/dockview/demo-dockview/src/app.tsx b/packages/docs/sandboxes/react/dockview/demo-dockview/src/app.tsx index e2449a4ab..fbae859b0 100644 --- a/packages/docs/sandboxes/react/dockview/demo-dockview/src/app.tsx +++ b/packages/docs/sandboxes/react/dockview/demo-dockview/src/app.tsx @@ -35,6 +35,12 @@ const components = { const isDebug = React.useContext(DebugContext); const metadata = usePanelApiMetadata(props.api); + const [firstRender, setFirstRender] = React.useState(''); + + React.useEffect(() => { + setFirstRender(new Date().toISOString()); + }, []); + return (
+
{firstRender}
+ {isDebug && (