diff --git a/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts b/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts index c6dc7a038..fd5981b78 100644 --- a/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts +++ b/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts @@ -3708,16 +3708,16 @@ describe('dockviewComponent', () => { floatingGroups: [ { data: { - views: ['panelB'], - activeView: 'panelB', + views: ['panelC'], + activeView: 'panelC', id: '3', }, position: { left: 0, top: 0, height: 100, width: 100 }, }, { data: { - views: ['panelC'], - activeView: 'panelC', + views: ['panelD'], + activeView: 'panelD', id: '4', }, position: { left: 0, top: 0, height: 100, width: 100 }, diff --git a/packages/dockview-core/src/dockview/dockviewComponent.ts b/packages/dockview-core/src/dockview/dockviewComponent.ts index 9d49df053..152285f39 100644 --- a/packages/dockview-core/src/dockview/dockviewComponent.ts +++ b/packages/dockview-core/src/dockview/dockviewComponent.ts @@ -73,6 +73,7 @@ import { OverlayRenderContainer, } from '../overlay/overlayRenderContainer'; import { PopoutWindow } from '../popoutWindow'; +import { StrictEventsSequencing } from './strictEventsSequencing'; const DEFAULT_ROOT_OVERLAY_MODEL: DroptargetOverlayModel = { activationSize: { type: 'pixels', value: 10 }, @@ -388,6 +389,10 @@ export class DockviewComponent toggleClass(this.gridview.element, 'dv-dockview', true); toggleClass(this.element, 'dv-debug', !!options.debug); + if (options.debug) { + this.addDisposables(new StrictEventsSequencing(this)); + } + this.addDisposables( this.overlayRenderContainer, this._onWillDragPanel, @@ -1309,6 +1314,7 @@ export class DockviewComponent locked: !!locked, hideHeader: !!hideHeader, }); + this._onDidAddGroup.fire(group); const createdPanels: IDockviewPanel[] = []; @@ -1325,8 +1331,6 @@ export class DockviewComponent createdPanels.push(panel); } - this._onDidAddGroup.fire(group); - for (let i = 0; i < views.length; i++) { const panel = createdPanels[i]; @@ -1413,6 +1417,7 @@ export class DockviewComponent 'dockview: failed to deserialize layout. Reverting changes', err ); + /** * Takes all the successfully created groups and remove all of their panels. */ diff --git a/packages/dockview-core/src/dockview/strictEventsSequencing.ts b/packages/dockview-core/src/dockview/strictEventsSequencing.ts new file mode 100644 index 000000000..60f91e613 --- /dev/null +++ b/packages/dockview-core/src/dockview/strictEventsSequencing.ts @@ -0,0 +1,54 @@ +import { CompositeDisposable } from '../lifecycle'; +import { DockviewComponent } from './dockviewComponent'; + +export class StrictEventsSequencing extends CompositeDisposable { + constructor(private readonly accessor: DockviewComponent) { + super(); + + this.init(); + } + + private init(): void { + const panels = new Set(); + const groups = new Set(); + + this.addDisposables( + this.accessor.onDidAddPanel((panel) => { + if (panels.has(panel.api.id)) { + throw new Error( + `dockview: Invalid event sequence. [onDidAddPanel] called for panel ${panel.api.id} but panel already exists` + ); + } else { + panels.add(panel.api.id); + } + }), + this.accessor.onDidRemovePanel((panel) => { + if (!panels.has(panel.api.id)) { + throw new Error( + `dockview: Invalid event sequence. [onDidRemovePanel] called for panel ${panel.api.id} but panel does not exists` + ); + } else { + panels.delete(panel.api.id); + } + }), + this.accessor.onDidAddGroup((group) => { + if (groups.has(group.api.id)) { + throw new Error( + `dockview: Invalid event sequence. [onDidAddGroup] called for group ${group.api.id} but group already exists` + ); + } else { + groups.add(group.api.id); + } + }), + this.accessor.onDidRemoveGroup((group) => { + if (!groups.has(group.api.id)) { + throw new Error( + `dockview: Invalid event sequence. [onDidRemoveGroup] called for group ${group.api.id} but group does not exists` + ); + } else { + groups.delete(group.api.id); + } + }) + ); + } +}