diff --git a/packages/dockview-core/src/__tests__/api/api.spec.ts b/packages/dockview-core/src/__tests__/api/api.spec.ts index 5b40a6aa9..d596c2052 100644 --- a/packages/dockview-core/src/__tests__/api/api.spec.ts +++ b/packages/dockview-core/src/__tests__/api/api.spec.ts @@ -5,7 +5,7 @@ describe('api', () => { let api: PanelApiImpl; beforeEach(() => { - api = new PanelApiImpl('dummy_id'); + api = new PanelApiImpl('dummy_id', 'fake-component'); }); test('updateParameters', () => { diff --git a/packages/dockview-core/src/__tests__/api/dockviewPanelApi.spec.ts b/packages/dockview-core/src/__tests__/api/dockviewPanelApi.spec.ts index 33ebe05d9..c883a20f8 100644 --- a/packages/dockview-core/src/__tests__/api/dockviewPanelApi.spec.ts +++ b/packages/dockview-core/src/__tests__/api/dockviewPanelApi.spec.ts @@ -31,7 +31,8 @@ describe('groupPanelApi', () => { const cut = new DockviewPanelApiImpl( panel, group, - accessor + accessor, + 'fake-component' ); cut.setTitle('test_title'); @@ -59,7 +60,8 @@ describe('groupPanelApi', () => { const cut = new DockviewPanelApiImpl( groupPanel, groupViewPanel, - accessor + accessor, + 'fake-component' ); cut.updateParameters({ keyA: 'valueA' }); @@ -89,7 +91,8 @@ describe('groupPanelApi', () => { const cut = new DockviewPanelApiImpl( groupPanel, groupViewPanel, - accessor + accessor, + 'fake-component' ); let events = 0; diff --git a/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts b/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts index f002e9af6..1ec04ab90 100644 --- a/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts +++ b/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts @@ -8,7 +8,7 @@ import { PanelUpdateEvent } from '../../panel/types'; import { Orientation } from '../../splitview/splitview'; import { CompositeDisposable } from '../../lifecycle'; import { Emitter } from '../../events'; -import { IDockviewPanel } from '../../dockview/dockviewPanel'; +import { DockviewPanel, IDockviewPanel } from '../../dockview/dockviewPanel'; import { DockviewGroupPanel } from '../../dockview/dockviewGroupPanel'; import { fireEvent } from '@testing-library/dom'; import { getPanelData } from '../../dnd/dataTransfer'; @@ -4598,6 +4598,64 @@ describe('dockviewComponent', () => { }); }); + describe('that emits onDidLayoutChange', () => { + let dockview: DockviewComponent; + let panel1: DockviewPanel; + + beforeEach(() => { + jest.useFakeTimers(); + + dockview = new DockviewComponent({ + parentElement: container, + components: { + default: PanelContentPartTest, + }, + tabComponents: { + test_tab_id: PanelTabPartTest, + }, + orientation: Orientation.HORIZONTAL, + }); + + panel1 = dockview.addPanel({ + id: 'panel_1', + component: 'default', + }); + }); + + afterEach(() => { + jest.runAllTimers(); + jest.useRealTimers(); + }); + + test('that emits onDidPanelTitleChange and onDidLayoutChange when the panel set a title', () => { + const didLayoutChangeHandler = jest.fn(); + const { dispose: disposeDidLayoutChangeHandler } = + dockview.onDidLayoutChange(didLayoutChangeHandler); + + panel1.setTitle('new title'); + + jest.runAllTimers(); + + expect(didLayoutChangeHandler).toHaveBeenCalledTimes(1); + + disposeDidLayoutChangeHandler(); + }); + + test('that emits onDidPanelParametersChange and onDidLayoutChange when the panel updates parameters', () => { + const didLayoutChangeHandler = jest.fn(); + const { dispose: disposeDidLayoutChangeHandler } = + dockview.onDidLayoutChange(didLayoutChangeHandler); + + panel1.api.updateParameters({ keyA: 'valueA' }); + + jest.runAllTimers(); + + expect(didLayoutChangeHandler).toHaveBeenCalledTimes(1); + + disposeDidLayoutChangeHandler(); + }); + }); + test('that setVisible toggles visiblity', () => { const container = document.createElement('div'); diff --git a/packages/dockview-core/src/__tests__/dockview/dockviewGroupPanelModel.spec.ts b/packages/dockview-core/src/__tests__/dockview/dockviewGroupPanelModel.spec.ts index b1963dbe5..939380ec6 100644 --- a/packages/dockview-core/src/__tests__/dockview/dockviewGroupPanelModel.spec.ts +++ b/packages/dockview-core/src/__tests__/dockview/dockviewGroupPanelModel.spec.ts @@ -9,19 +9,40 @@ import { } from '../../dockview/types'; import { PanelUpdateEvent, Parameters } from '../../panel/types'; import { + DockviewGroupLocation, DockviewGroupPanelModel, GroupOptions, } from '../../dockview/dockviewGroupPanelModel'; import { fireEvent } from '@testing-library/dom'; import { LocalSelectionTransfer, PanelTransfer } from '../../dnd/dataTransfer'; import { CompositeDisposable } from '../../lifecycle'; -import { DockviewPanelApi } from '../../api/dockviewPanelApi'; +import { + ActiveGroupEvent, + DockviewPanelApi, + GroupChangedEvent, + RendererChangedEvent, +} from '../../api/dockviewPanelApi'; import { IDockviewPanel } from '../../dockview/dockviewPanel'; import { IDockviewPanelModel } from '../../dockview/dockviewPanelModel'; import { DockviewGroupPanel } from '../../dockview/dockviewGroupPanel'; import { WatermarkRendererInitParameters } from '../../dockview/types'; import { createOffsetDragOverEvent } from '../__test_utils__/utils'; -import { OverlayRenderContainer } from '../../overlayRenderContainer'; +import { + DockviewPanelRenderer, + OverlayRenderContainer, +} from '../../overlayRenderContainer'; +import { DockviewGroupPanelFloatingChangeEvent } from '../../api/dockviewGroupPanelApi'; +import { SizeEvent } from '../../api/gridviewPanelApi'; +import { + PanelDimensionChangeEvent, + FocusEvent, + VisibilityEvent, + ActiveEvent, + WillFocusEvent, +} from '../../api/panelApi'; +import { Position } from '../../dnd/droptarget'; +import { Emitter, Event } from '../../events'; +import { fromPartial } from '@total-typescript/shoehorn'; enum GroupChangeKind2 { ADD_PANEL, @@ -240,12 +261,20 @@ describe('dockviewGroupPanelModel', () => { let removePanelMock: jest.Mock; let removeGroupMock: jest.Mock; + let panelApi: DockviewPanelApi; + beforeEach(() => { removePanelMock = jest.fn(); removeGroupMock = jest.fn(); options = {}; + panelApi = fromPartial({ + renderer: 'onlyWhenVisibile', + onDidTitleChange: new Emitter().event, + onDidParametersChange: new Emitter().event, + }); + dockview = (>{ options: { parentElement: document.createElement('div') }, createWatermarkComponent: () => new Watermark(), @@ -265,15 +294,9 @@ describe('dockviewGroupPanelModel', () => { }); test('panel events are captured during de-serialization', () => { - const panel1 = new TestPanel('panel1', { - renderer: 'onlyWhenVisibile', - } as any); - const panel2 = new TestPanel('panel2', { - renderer: 'onlyWhenVisibile', - } as any); - const panel3 = new TestPanel('panel3', { - renderer: 'onlyWhenVisibile', - } as any); + const panel1 = new TestPanel('panel1', panelApi); + const panel2 = new TestPanel('panel2', panelApi); + const panel3 = new TestPanel('panel3', panelApi); const groupview2 = new DockviewGroupPanel(dockview, 'groupview-2', { panels: [panel1, panel2, panel3], @@ -357,15 +380,9 @@ describe('dockviewGroupPanelModel', () => { }) ); - const panel1 = new TestPanel('panel1', { - renderer: 'onlyWhenVisibile', - } as any); - const panel2 = new TestPanel('panel2', { - renderer: 'onlyWhenVisibile', - } as any); - const panel3 = new TestPanel('panel3', { - renderer: 'onlyWhenVisibile', - } as any); + const panel1 = new TestPanel('panel1', panelApi); + const panel2 = new TestPanel('panel2', panelApi); + const panel3 = new TestPanel('panel3', panelApi); expect(events.length).toBe(0); @@ -443,15 +460,9 @@ describe('dockviewGroupPanelModel', () => { }); test('moveToPrevious and moveToNext', () => { - const panel1 = new TestPanel('panel1', { - renderer: 'onlyWhenVisibile', - } as any); - const panel2 = new TestPanel('panel2', { - renderer: 'onlyWhenVisibile', - } as any); - const panel3 = new TestPanel('panel3', { - renderer: 'onlyWhenVisibile', - } as any); + const panel1 = new TestPanel('panel1', panelApi); + const panel2 = new TestPanel('panel2', panelApi); + const panel3 = new TestPanel('panel3', panelApi); groupview.model.openPanel(panel1); groupview.model.openPanel(panel2); @@ -495,15 +506,9 @@ describe('dockviewGroupPanelModel', () => { }); test('closeAllPanels with panels', () => { - const panel1 = new TestPanel('panel1', { - renderer: 'onlyWhenVisibile', - } as any); - const panel2 = new TestPanel('panel2', { - renderer: 'onlyWhenVisibile', - } as any); - const panel3 = new TestPanel('panel3', { - renderer: 'onlyWhenVisibile', - } as any); + const panel1 = new TestPanel('panel1', panelApi); + const panel2 = new TestPanel('panel2', panelApi); + const panel3 = new TestPanel('panel3', panelApi); groupview.model.openPanel(panel1); groupview.model.openPanel(panel2); @@ -608,25 +613,19 @@ describe('dockviewGroupPanelModel', () => { .getElementsByClassName('content-container') .item(0)!.childNodes; - const panel1 = new TestPanel('id_1', { - renderer: 'onlyWhenVisibile', - } as any); + const panel1 = new TestPanel('id_1', panelApi); cut.openPanel(panel1); expect(contentContainer.length).toBe(1); expect(contentContainer.item(0)).toBe(panel1.view.content.element); - const panel2 = new TestPanel('id_2', { - renderer: 'onlyWhenVisibile', - } as any); + const panel2 = new TestPanel('id_2', panelApi); cut.openPanel(panel2); expect(contentContainer.length).toBe(1); expect(contentContainer.item(0)).toBe(panel2.view.content.element); - const panel3 = new TestPanel('id_2', { - renderer: 'onlyWhenVisibile', - } as any); + const panel3 = new TestPanel('id_2', panelApi); cut.openPanel(panel3, { skipSetActive: true }); expect(contentContainer.length).toBe(1); @@ -834,11 +833,7 @@ describe('dockviewGroupPanelModel', () => { new groupPanelMock() as DockviewGroupPanel ); - cut.openPanel( - new TestPanel('panel1', { - renderer: 'onlyWhenVisibile', - } as any) - ); + cut.openPanel(new TestPanel('panel1', panelApi)); const element = container .getElementsByClassName('content-container') @@ -908,16 +903,8 @@ describe('dockviewGroupPanelModel', () => { new groupPanelMock() as DockviewGroupPanel ); - cut.openPanel( - new TestPanel('panel1', { - renderer: 'onlyWhenVisibile', - } as any) - ); - cut.openPanel( - new TestPanel('panel2', { - renderer: 'onlyWhenVisibile', - } as any) - ); + cut.openPanel(new TestPanel('panel1', panelApi)); + cut.openPanel(new TestPanel('panel2', panelApi)); const element = container .getElementsByClassName('content-container') @@ -987,16 +974,8 @@ describe('dockviewGroupPanelModel', () => { new groupPanelMock() as DockviewGroupPanel ); - cut.openPanel( - new TestPanel('panel1', { - renderer: 'onlyWhenVisibile', - } as any) - ); - cut.openPanel( - new TestPanel('panel2', { - renderer: 'onlyWhenVisibile', - } as any) - ); + cut.openPanel(new TestPanel('panel1', panelApi)); + cut.openPanel(new TestPanel('panel2', panelApi)); const element = container .getElementsByClassName('content-container') @@ -1097,11 +1076,7 @@ describe('dockviewGroupPanelModel', () => { container.getElementsByClassName('watermark-test-container').length ).toBe(1); - cut.openPanel( - new TestPanel('panel1', { - renderer: 'onlyWhenVisibile', - } as any) - ); + cut.openPanel(new TestPanel('panel1', panelApi)); expect( container.getElementsByClassName('watermark-test-container').length @@ -1111,11 +1086,7 @@ describe('dockviewGroupPanelModel', () => { .length ).toBe(1); - cut.openPanel( - new TestPanel('panel2', { - renderer: 'onlyWhenVisibile', - } as any) - ); + cut.openPanel(new TestPanel('panel2', panelApi)); expect( container.getElementsByClassName('watermark-test-container').length @@ -1133,11 +1104,7 @@ describe('dockviewGroupPanelModel', () => { container.getElementsByClassName('watermark-test-container').length ).toBe(1); - cut.openPanel( - new TestPanel('panel1', { - renderer: 'onlyWhenVisibile', - } as any) - ); + cut.openPanel(new TestPanel('panel1', panelApi)); expect( container.getElementsByClassName('watermark-test-container').length diff --git a/packages/dockview-core/src/__tests__/dockview/dockviewPanel.spec.ts b/packages/dockview-core/src/__tests__/dockview/dockviewPanel.spec.ts index 0a6dc8e64..24bbb2f9d 100644 --- a/packages/dockview-core/src/__tests__/dockview/dockviewPanel.spec.ts +++ b/packages/dockview-core/src/__tests__/dockview/dockviewPanel.spec.ts @@ -34,9 +34,18 @@ describe('dockviewPanel', () => { }); const model = new panelModelMock(); - const cut = new DockviewPanel('fake-id', accessor, api, group, model, { - renderer: 'onlyWhenVisibile', - }); + const cut = new DockviewPanel( + 'fake-id', + 'fake-component', + undefined, + accessor, + api, + group, + model, + { + renderer: 'onlyWhenVisibile', + } + ); let latestTitle: string | undefined = undefined; @@ -84,9 +93,18 @@ describe('dockviewPanel', () => { }); const model = new panelModelMock(); - const cut = new DockviewPanel('fake-id', accessor, api, group, model, { - renderer: 'onlyWhenVisibile', - }); + const cut = new DockviewPanel( + 'fake-id', + 'fake-component', + undefined, + accessor, + api, + group, + model, + { + renderer: 'onlyWhenVisibile', + } + ); cut.init({ title: 'myTitle', params: {} }); expect(cut.title).toBe('myTitle'); @@ -130,9 +148,18 @@ describe('dockviewPanel', () => { }); const model = new panelModelMock(); - const cut = new DockviewPanel('fake-id', accessor, api, group, model, { - renderer: 'onlyWhenVisibile', - }); + const cut = new DockviewPanel( + 'fake-id', + 'fake-component', + undefined, + accessor, + api, + group, + model, + { + renderer: 'onlyWhenVisibile', + } + ); cut.init({ params: {}, title: 'title' }); @@ -167,9 +194,18 @@ describe('dockviewPanel', () => { }); const model = new panelModelMock(); - const cut = new DockviewPanel('fake-id', accessor, api, group, model, { - renderer: 'onlyWhenVisibile', - }); + const cut = new DockviewPanel( + 'fake-id', + 'fake-component', + undefined, + accessor, + api, + group, + model, + { + renderer: 'onlyWhenVisibile', + } + ); expect(cut.params).toEqual(undefined); @@ -205,9 +241,18 @@ describe('dockviewPanel', () => { }); const model = new panelModelMock(); - const cut = new DockviewPanel('fake-id', accessor, api, group, model, { - renderer: 'onlyWhenVisibile', - }); + const cut = new DockviewPanel( + 'fake-id', + 'fake-component', + undefined, + accessor, + api, + group, + model, + { + renderer: 'onlyWhenVisibile', + } + ); cut.api.setSize({ height: 123, width: 456 }); @@ -241,9 +286,18 @@ describe('dockviewPanel', () => { }); const model = new panelModelMock(); - const cut = new DockviewPanel('fake-id', accessor, api, group, model, { - renderer: 'onlyWhenVisibile', - }); + const cut = new DockviewPanel( + 'fake-id', + 'fake-component', + undefined, + accessor, + api, + group, + model, + { + renderer: 'onlyWhenVisibile', + } + ); cut.init({ params: { a: '1', b: '2' }, title: 'A title' }); expect(cut.params).toEqual({ a: '1', b: '2' }); diff --git a/packages/dockview-core/src/api/dockviewGroupPanelApi.ts b/packages/dockview-core/src/api/dockviewGroupPanelApi.ts index 2f299b6ee..c72d990f6 100644 --- a/packages/dockview-core/src/api/dockviewGroupPanelApi.ts +++ b/packages/dockview-core/src/api/dockviewGroupPanelApi.ts @@ -42,7 +42,7 @@ export class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl { } constructor(id: string, private readonly accessor: DockviewComponent) { - super(id); + super(id, '__dockviewgroup__'); this.addDisposables(this._onDidLocationChange); } diff --git a/packages/dockview-core/src/api/dockviewPanelApi.ts b/packages/dockview-core/src/api/dockviewPanelApi.ts index 06a4ebc22..574983bb6 100644 --- a/packages/dockview-core/src/api/dockviewPanelApi.ts +++ b/packages/dockview-core/src/api/dockviewPanelApi.ts @@ -37,6 +37,7 @@ export interface DockviewPanelApi readonly title: string | undefined; readonly onDidActiveGroupChange: Event; readonly onDidGroupChange: Event; + readonly onDidTitleChange: Event; readonly onDidRendererChange: Event; readonly location: DockviewGroupLocation; readonly onDidLocationChange: Event; @@ -62,6 +63,7 @@ export class DockviewPanelApiImpl implements DockviewPanelApi { private _group: DockviewGroupPanel; + private _tabComponent: string | undefined; readonly _onDidTitleChange = new Emitter(); readonly onDidTitleChange = this._onDidTitleChange.event; @@ -118,12 +120,20 @@ export class DockviewPanelApiImpl return this._group; } + get tabComponent(): string | undefined { + return this._tabComponent; + } + constructor( private panel: DockviewPanel, group: DockviewGroupPanel, - private readonly accessor: DockviewComponent + private readonly accessor: DockviewComponent, + component: string, + tabComponent?: string ) { - super(panel.id); + super(panel.id, component); + + this._tabComponent = tabComponent; this.initialize(panel); diff --git a/packages/dockview-core/src/api/gridviewPanelApi.ts b/packages/dockview-core/src/api/gridviewPanelApi.ts index 4a7e50424..8c661a4fe 100644 --- a/packages/dockview-core/src/api/gridviewPanelApi.ts +++ b/packages/dockview-core/src/api/gridviewPanelApi.ts @@ -44,8 +44,8 @@ export class GridviewPanelApiImpl private readonly _onDidSizeChange = new Emitter(); readonly onDidSizeChange: Event = this._onDidSizeChange.event; - constructor(id: string, panel?: IPanel) { - super(id); + constructor(id: string, component: string, panel?: IPanel) { + super(id, component); this.addDisposables( this._onDidConstraintsChangeInternal, diff --git a/packages/dockview-core/src/api/panelApi.ts b/packages/dockview-core/src/api/panelApi.ts index 698c480e9..ec8c753e5 100644 --- a/packages/dockview-core/src/api/panelApi.ts +++ b/packages/dockview-core/src/api/panelApi.ts @@ -24,6 +24,7 @@ export interface PanelApi { readonly onDidFocusChange: Event; readonly onDidVisibilityChange: Event; readonly onDidActiveChange: Event; + readonly onDidParametersChange: Event; setActive(): void; setVisible(isVisible: boolean): void; updateParameters(parameters: Parameters): void; @@ -53,6 +54,8 @@ export interface PanelApi { readonly height: number; readonly onWillFocus: Event; + + getParameters(): T; } export class WillFocusEvent extends DockviewEvent { @@ -70,6 +73,7 @@ export class PanelApiImpl extends CompositeDisposable implements PanelApi { private _isVisible = true; private _width = 0; private _height = 0; + private _parameters: Parameters = {}; private readonly panelUpdatesDisposable = new MutableDisposable(); @@ -97,9 +101,9 @@ export class PanelApiImpl extends CompositeDisposable implements PanelApi { readonly _onActiveChange = new Emitter(); readonly onActiveChange: Event = this._onActiveChange.event; - readonly _onUpdateParameters = new Emitter(); - readonly onUpdateParameters: Event = - this._onUpdateParameters.event; + readonly _onDidParametersChange = new Emitter(); + readonly onDidParametersChange: Event = + this._onDidParametersChange.event; get isFocused(): boolean { return this._isFocused; @@ -121,7 +125,7 @@ export class PanelApiImpl extends CompositeDisposable implements PanelApi { return this._height; } - constructor(readonly id: string) { + constructor(readonly id: string, readonly component: string) { super(); this.addDisposables( @@ -145,16 +149,20 @@ export class PanelApiImpl extends CompositeDisposable implements PanelApi { this._onDidActiveChange, this._onWillFocus, this._onActiveChange, - this._onUpdateParameters, this._onWillFocus, this._onWillVisibilityChange, - this._onUpdateParameters + this._onDidParametersChange ); } + getParameters(): T { + return this._parameters as T; + } + public initialize(panel: IPanel): void { - this.panelUpdatesDisposable.value = this._onUpdateParameters.event( + this.panelUpdatesDisposable.value = this._onDidParametersChange.event( (parameters) => { + this._parameters = parameters; panel.update({ params: parameters, }); @@ -171,6 +179,6 @@ export class PanelApiImpl extends CompositeDisposable implements PanelApi { } updateParameters(parameters: Parameters): void { - this._onUpdateParameters.fire(parameters); + this._onDidParametersChange.fire(parameters); } } diff --git a/packages/dockview-core/src/api/paneviewPanelApi.ts b/packages/dockview-core/src/api/paneviewPanelApi.ts index c90a70db4..c387fd9c0 100644 --- a/packages/dockview-core/src/api/paneviewPanelApi.ts +++ b/packages/dockview-core/src/api/paneviewPanelApi.ts @@ -35,8 +35,8 @@ export class PaneviewPanelApiImpl this._pane = pane; } - constructor(id: string) { - super(id); + constructor(id: string, component: string) { + super(id, component); this.addDisposables( this._onDidExpansionChange, diff --git a/packages/dockview-core/src/api/splitviewPanelApi.ts b/packages/dockview-core/src/api/splitviewPanelApi.ts index cfe3cd103..089d9e4ec 100644 --- a/packages/dockview-core/src/api/splitviewPanelApi.ts +++ b/packages/dockview-core/src/api/splitviewPanelApi.ts @@ -45,8 +45,8 @@ export class SplitviewPanelApiImpl this._onDidSizeChange.event; // - constructor(id: string) { - super(id); + constructor(id: string, component: string) { + super(id, component); this.addDisposables( this._onDidConstraintsChangeInternal, diff --git a/packages/dockview-core/src/dockview/deserializer.ts b/packages/dockview-core/src/dockview/deserializer.ts index 3b9ab8e96..41a4a0102 100644 --- a/packages/dockview-core/src/dockview/deserializer.ts +++ b/packages/dockview-core/src/dockview/deserializer.ts @@ -49,6 +49,8 @@ export class DefaultDockviewDeserialzier implements IPanelDeserializer { const panel = new DockviewPanel( panelId, + contentComponent, + tabComponent, this.accessor, new DockviewApi(this.accessor), group, diff --git a/packages/dockview-core/src/dockview/dockviewComponent.ts b/packages/dockview-core/src/dockview/dockviewComponent.ts index a5fdacf39..e37c96863 100644 --- a/packages/dockview-core/src/dockview/dockviewComponent.ts +++ b/packages/dockview-core/src/dockview/dockviewComponent.ts @@ -65,6 +65,7 @@ import { OverlayRenderContainer, } from '../overlayRenderContainer'; import { PopoutWindow } from '../popoutWindow'; +import { TitleEvent } from '../api/dockviewPanelApi'; const DEFAULT_ROOT_OVERLAY_MODEL: DroptargetOverlayModel = { activationSize: { type: 'pixels', value: 10 }, @@ -2175,6 +2176,12 @@ export class DockviewComponent if (this._onDidActivePanelChange.value !== event.panel) { this._onDidActivePanelChange.fire(event.panel); } + }), + Event.any( + view.model.onDidPanelTitleChange, + view.model.onDidPanelParametersChange + )(() => { + this._bufferOnDidLayoutChange.fire(); }) ); @@ -2204,6 +2211,8 @@ export class DockviewComponent const panel = new DockviewPanel( options.id, + contentComponent, + tabComponent, this, this._api, group, diff --git a/packages/dockview-core/src/dockview/dockviewGroupPanelModel.ts b/packages/dockview-core/src/dockview/dockviewGroupPanelModel.ts index d690d0f4c..e1989dd68 100644 --- a/packages/dockview-core/src/dockview/dockviewGroupPanelModel.ts +++ b/packages/dockview-core/src/dockview/dockviewGroupPanelModel.ts @@ -11,8 +11,13 @@ import { IDockviewEvent, } from '../events'; import { IViewSize } from '../gridview/gridview'; -import { CompositeDisposable } from '../lifecycle'; -import { IPanel, PanelInitParameters, PanelUpdateEvent } from '../panel/types'; +import { CompositeDisposable, IDisposable } from '../lifecycle'; +import { + IPanel, + PanelInitParameters, + PanelUpdateEvent, + Parameters, +} from '../panel/types'; import { ContentContainer, IContentContainer, @@ -28,6 +33,7 @@ import { DockviewGroupPanel } from './dockviewGroupPanel'; import { IDockviewPanel } from './dockviewPanel'; import { IHeaderActionsRenderer } from './options'; import { OverlayRenderContainer } from '../overlayRenderContainer'; +import { TitleEvent } from '../api/dockviewPanelApi'; interface GroupMoveEvent { groupId: string; @@ -245,6 +251,7 @@ export class DockviewGroupPanelModel private _height = 0; private _panels: IDockviewPanel[] = []; + private readonly _panelDisposables = new Map(); private readonly _onMove = new Emitter(); readonly onMove: Event = this._onMove.event; @@ -271,6 +278,14 @@ export class DockviewGroupPanelModel readonly onDidAddPanel: Event = this._onDidAddPanel.event; + private readonly _onDidPanelTitleChange = new Emitter(); + readonly onDidPanelTitleChange: Event = + this._onDidPanelTitleChange.event; + + private readonly _onDidPanelParametersChange = new Emitter(); + readonly onDidPanelParametersChange: Event = + this._onDidPanelParametersChange.event; + private readonly _onDidRemovePanel = new Emitter(); readonly onDidRemovePanel: Event = @@ -826,6 +841,12 @@ export class DockviewGroupPanelModel ); } + const disposable = this._panelDisposables.get(panel.id); + if (disposable) { + disposable.dispose(); + this._panelDisposables.delete(panel.id); + } + this._onDidRemovePanel.fire({ panel }); } @@ -856,6 +877,18 @@ export class DockviewGroupPanelModel this.updateMru(panel); this.panels.splice(index, 0, panel); + this._panelDisposables.set( + panel.id, + new CompositeDisposable( + panel.api.onDidTitleChange((event) => + this._onDidPanelTitleChange.fire(event) + ), + panel.api.onDidParametersChange((event) => + this._onDidPanelParametersChange.fire(event) + ) + ) + ); + this._onDidAddPanel.fire({ panel }); } diff --git a/packages/dockview-core/src/dockview/dockviewPanel.ts b/packages/dockview-core/src/dockview/dockviewPanel.ts index 72ae1ca72..fdc3656e7 100644 --- a/packages/dockview-core/src/dockview/dockviewPanel.ts +++ b/packages/dockview-core/src/dockview/dockviewPanel.ts @@ -58,6 +58,8 @@ export class DockviewPanel constructor( public readonly id: string, + component: string, + tabComponent: string | undefined, private readonly accessor: DockviewComponent, private readonly containerApi: DockviewApi, group: DockviewGroupPanel, @@ -68,7 +70,13 @@ export class DockviewPanel this._renderer = options.renderer; this._group = group; - this.api = new DockviewPanelApiImpl(this, this._group, accessor); + this.api = new DockviewPanelApiImpl( + this, + this._group, + accessor, + component, + tabComponent + ); this.addDisposables( this.api.onActiveChange(() => { diff --git a/packages/dockview-core/src/gridview/gridviewPanel.ts b/packages/dockview-core/src/gridview/gridviewPanel.ts index 799395f0c..f398f5b7a 100644 --- a/packages/dockview-core/src/gridview/gridviewPanel.ts +++ b/packages/dockview-core/src/gridview/gridviewPanel.ts @@ -140,7 +140,7 @@ export abstract class GridviewPanel< }, api?: T ) { - super(id, component, api ?? new GridviewPanelApiImpl(id)); + super(id, component, api ?? new GridviewPanelApiImpl(id, component)); if (typeof options?.minimumWidth === 'number') { this._minimumWidth = options.minimumWidth; diff --git a/packages/dockview-core/src/paneview/paneviewPanel.ts b/packages/dockview-core/src/paneview/paneviewPanel.ts index d07490d48..6d3d7254a 100644 --- a/packages/dockview-core/src/paneview/paneviewPanel.ts +++ b/packages/dockview-core/src/paneview/paneviewPanel.ts @@ -164,7 +164,7 @@ export abstract class PaneviewPanel isExpanded: boolean, isHeaderVisible: boolean ) { - super(id, component, new PaneviewPanelApiImpl(id)); + super(id, component, new PaneviewPanelApiImpl(id, component)); this.api.pane = this; // TODO cannot use 'this' before 'super' this.api.initialize(this); diff --git a/packages/dockview-core/src/splitview/splitviewPanel.ts b/packages/dockview-core/src/splitview/splitviewPanel.ts index f9e834068..e96275aba 100644 --- a/packages/dockview-core/src/splitview/splitviewPanel.ts +++ b/packages/dockview-core/src/splitview/splitviewPanel.ts @@ -83,7 +83,7 @@ export abstract class SplitviewPanel } constructor(id: string, componentName: string) { - super(id, componentName, new SplitviewPanelApiImpl(id)); + super(id, componentName, new SplitviewPanelApiImpl(id, componentName)); this.api.initialize(this);