diff --git a/packages/dockview/src/__tests__/dockview/dockviewComponent.spec.ts b/packages/dockview/src/__tests__/dockview/dockviewComponent.spec.ts index 2e1789f73..4590e8b9f 100644 --- a/packages/dockview/src/__tests__/dockview/dockviewComponent.spec.ts +++ b/packages/dockview/src/__tests__/dockview/dockviewComponent.spec.ts @@ -154,18 +154,12 @@ class TestGroupPanel implements IGroupPanel { } describe('dockviewComponent', () => { - let root: HTMLElement; let container: HTMLElement; let dockview: DockviewComponent; beforeEach(() => { - root = document.createElement('div'); // dockview container must have parent element container = document.createElement('div'); - root.appendChild(container); - root.className = 'root'; - container.className = 'container'; - dockview = new DockviewComponent(container, { components: { default: PanelContentPartTest, @@ -1038,4 +1032,31 @@ describe('dockviewComponent', () => { disposable.dispose(); }); + + test('dispose of dockviewComponent', () => { + dockview.layout(500, 1000); + + dockview.addPanel({ + id: 'panel1', + component: 'default', + }); + dockview.addPanel({ + id: 'panel2', + component: 'default', + }); + dockview.addPanel({ + id: 'panel3', + component: 'default', + }); + dockview.addPanel({ + id: 'panel4', + component: 'default', + }); + + expect(container.childNodes.length).toBe(1); + + dockview.dispose(); + + expect(container.childNodes.length).toBe(0); + }); }); diff --git a/packages/dockview/src/__tests__/gridview/gridview.spec.ts b/packages/dockview/src/__tests__/gridview/gridview.spec.ts index a9e85b62a..9574f8069 100644 --- a/packages/dockview/src/__tests__/gridview/gridview.spec.ts +++ b/packages/dockview/src/__tests__/gridview/gridview.spec.ts @@ -1,31 +1,6 @@ -import { - GroupChangeEvent, - GroupChangeKind, -} from '../../gridview/baseComponentGridview'; -import { GridviewComponent } from '../../gridview/gridviewComponent'; -import { GridviewPanel } from '../../gridview/gridviewPanel'; -import { IFrameworkPart } from '../../panel/types'; +import { Gridview } from '../../gridview/gridview'; import { Orientation } from '../../splitview/core/splitview'; -class TestGridview extends GridviewPanel { - constructor(id: string, componentName: string) { - super(id, componentName); - - this.element.id = id; - } - - getComponent(): IFrameworkPart { - return { - update: (params) => { - // - }, - dispose: () => { - // - }, - }; - } -} - describe('gridview', () => { let container: HTMLElement; @@ -33,1584 +8,21 @@ describe('gridview', () => { container = document.createElement('div'); }); - test('added views are visible by default', () => { - const gridview = new GridviewComponent(container, { - proportionalLayout: false, - orientation: Orientation.VERTICAL, - components: { default: TestGridview }, - }); + test('dispose of gridview', () => { + expect(container.childNodes.length).toBe(0); - gridview.layout(800, 400); + const gridview = new Gridview( + false, + { separatorBorder: '' }, + Orientation.HORIZONTAL + ); - gridview.addPanel({ - id: 'panel_1', - component: 'default', - }); + container.appendChild(gridview.element); - const panel = gridview.getPanel('panel_1'); + expect(container.childNodes.length).toBe(1); - expect(panel?.api.isVisible).toBeTruthy(); - }); + gridview.dispose(); - test('remove panel', () => { - const gridview = new GridviewComponent(container, { - proportionalLayout: false, - orientation: Orientation.VERTICAL, - components: { default: TestGridview }, - }); - - gridview.layout(800, 400); - - gridview.addPanel({ - id: 'panel1', - component: 'default', - }); - - expect(gridview.size).toBe(1); - - const panel1 = gridview.getPanel('panel1'); - - gridview.removePanel(panel1); - - expect(gridview.size).toBe(0); - - gridview.addPanel({ - id: 'panel1', - component: 'default', - }); - - expect(gridview.size).toBe(1); - }); - - test('active panel', () => { - const gridview = new GridviewComponent(container, { - proportionalLayout: false, - orientation: Orientation.VERTICAL, - components: { default: TestGridview }, - }); - - gridview.layout(800, 400); - - gridview.addPanel({ - id: 'panel1', - component: 'default', - }); - gridview.addPanel({ - id: 'panel2', - component: 'default', - }); - gridview.addPanel({ - id: 'panel3', - component: 'default', - }); - - const panel1 = gridview.getPanel('panel1'); - const panel2 = gridview.getPanel('panel2'); - const panel3 = gridview.getPanel('panel3'); - - expect(panel1.api.isActive).toBeFalsy(); - expect(panel2.api.isActive).toBeFalsy(); - expect(panel3.api.isActive).toBeTruthy(); - - panel1.api.setActive(); - - expect(panel1.api.isActive).toBeTruthy(); - expect(panel2.api.isActive).toBeFalsy(); - expect(panel3.api.isActive).toBeFalsy(); - - panel2.api.setActive(); - - expect(panel1.api.isActive).toBeFalsy(); - expect(panel2.api.isActive).toBeTruthy(); - expect(panel3.api.isActive).toBeFalsy(); - - panel3.api.setActive(); - - expect(panel1.api.isActive).toBeFalsy(); - expect(panel2.api.isActive).toBeFalsy(); - expect(panel3.api.isActive).toBeTruthy(); - - gridview.removePanel(panel3); - - expect(panel1.api.isActive).toBeTruthy(); - expect(panel2.api.isActive).toBeFalsy(); - - gridview.removePanel(panel1); - - expect(panel2.api.isActive).toBeTruthy(); - - gridview.removePanel(panel2); - }); - - test('deserialize and serialize a layout', () => { - const gridview = new GridviewComponent(container, { - proportionalLayout: false, - orientation: Orientation.VERTICAL, - components: { default: TestGridview }, - }); - - gridview.layout(800, 400); - gridview.fromJSON({ - grid: { - height: 400, - width: 800, - orientation: Orientation.HORIZONTAL, - root: { - type: 'branch', - size: 400, - data: [ - { - type: 'leaf', - size: 300, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 300, - visible: false, - data: { - id: 'panel_2', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 200, - visible: true, - data: { - id: 'panel_3', - component: 'default', - snap: true, - }, - }, - ], - }, - }, - activePanel: 'panel_1', - }); - gridview.layout(800, 400, true); - - const panel1 = gridview.getPanel('panel_1'); - const panel2 = gridview.getPanel('panel_2'); - const panel3 = gridview.getPanel('panel_3'); - - expect(panel1?.api.isVisible).toBeTruthy(); - expect(panel1?.api.id).toBe('panel_1'); - expect(panel1?.api.isActive).toBeTruthy(); - expect(panel1?.api.isFocused).toBeFalsy(); - expect(panel1?.api.height).toBe(400); - expect(panel1?.api.width).toBe(300); - - expect(panel2?.api.isVisible).toBeFalsy(); - expect(panel2?.api.id).toBe('panel_2'); - expect(panel2?.api.isActive).toBeFalsy(); - expect(panel2?.api.isFocused).toBeFalsy(); - expect(panel2?.api.height).toBe(400); - expect(panel2?.api.width).toBe(0); - - expect(panel3?.api.isVisible).toBeTruthy(); - expect(panel3?.api.id).toBe('panel_3'); - expect(panel3?.api.isActive).toBeFalsy(); - expect(panel3?.api.isFocused).toBeFalsy(); - expect(panel3?.api.height).toBe(400); - expect(panel3?.api.width).toBe(500); - - panel2.api.setActive(); - expect(panel1.api.isActive).toBeFalsy(); - expect(panel2.api.isActive).toBeTruthy(); - expect(panel3.api.isActive).toBeFalsy(); - - expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({ - grid: { - height: 400, - width: 800, - orientation: Orientation.HORIZONTAL, - root: { - type: 'branch', - size: 400, - data: [ - { - type: 'leaf', - size: 300, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 300, - visible: false, - data: { - id: 'panel_2', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 500, - data: { - id: 'panel_3', - component: 'default', - snap: true, - }, - }, - ], - }, - }, - activePanel: 'panel_1', - }); - }); - - test('toJSON shouldnt fire any layout events', () => { - const gridview = new GridviewComponent(container, { - proportionalLayout: false, - orientation: Orientation.VERTICAL, - components: { default: TestGridview }, - }); - - gridview.layout(1000, 1000); - - gridview.addPanel({ - id: 'panel1', - component: 'default', - }); - gridview.addPanel({ - id: 'panel2', - component: 'default', - }); - gridview.addPanel({ - id: 'panel3', - component: 'default', - }); - gridview.addPanel({ - id: 'panel4', - component: 'default', - }); - - const disposable = gridview.onDidLayoutChange(() => { - fail('onDidLayoutChange shouldnt have been called'); - }); - - const result = gridview.toJSON(); - expect(result).toBeTruthy(); - - disposable.dispose(); - }); - - test('gridview events', () => { - const gridview = new GridviewComponent(container, { - proportionalLayout: false, - orientation: Orientation.VERTICAL, - components: { default: TestGridview }, - }); - - gridview.layout(800, 400); - - let events: GroupChangeEvent[] = []; - const disposable = gridview.onGridEvent((e) => events.push(e)); - - gridview.addPanel({ - id: 'panel_1', - component: 'default', - }); - - expect(events).toEqual([ - { - kind: GroupChangeKind.ADD_GROUP, - }, - { - kind: GroupChangeKind.GROUP_ACTIVE, - }, - ]); - events = []; - - gridview.addPanel({ - id: 'panel_2', - component: 'default', - }); - - expect(events).toEqual([ - { - kind: GroupChangeKind.ADD_GROUP, - }, - { - kind: GroupChangeKind.GROUP_ACTIVE, - }, - ]); - events = []; - - gridview.addPanel({ - id: 'panel_3', - component: 'default', - }); - - expect(events).toEqual([ - { - kind: GroupChangeKind.ADD_GROUP, - }, - { - kind: GroupChangeKind.GROUP_ACTIVE, - }, - ]); - events = []; - - const panel1 = gridview.getPanel('panel_1'); - const panel2 = gridview.getPanel('panel_2'); - const panel3 = gridview.getPanel('panel_3'); - - gridview.removePanel(panel2); - - expect(events).toEqual([ - { - kind: GroupChangeKind.REMOVE_GROUP, - }, - ]); - events = []; - - gridview.removePanel(panel3); - expect(events).toEqual([ - { - kind: GroupChangeKind.REMOVE_GROUP, - }, - { - kind: GroupChangeKind.GROUP_ACTIVE, - }, - ]); - events = []; - - gridview.removePanel(panel1); - - expect(events).toEqual([ - { - kind: GroupChangeKind.REMOVE_GROUP, - }, - { - kind: GroupChangeKind.GROUP_ACTIVE, - }, - ]); - events = []; - - disposable.dispose(); - }); - - test('#1/VERTICAL', () => { - const gridview = new GridviewComponent(container, { - proportionalLayout: true, - orientation: Orientation.VERTICAL, - components: { default: TestGridview }, - }); - - gridview.fromJSON({ - grid: { - height: 400, - width: 800, - orientation: Orientation.VERTICAL, - root: { - type: 'branch', - size: 800, - data: [ - { - type: 'leaf', - size: 400, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - }, - activePanel: 'panel_1', - }); - - expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({ - grid: { - height: 400, - width: 800, - orientation: Orientation.VERTICAL, - root: { - type: 'branch', - size: 800, - data: [ - { - type: 'leaf', - size: 400, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - }, - activePanel: 'panel_1', - }); - }); - - test('#2/HORIZONTAL', () => { - const gridview = new GridviewComponent(container, { - proportionalLayout: true, - orientation: Orientation.HORIZONTAL, - components: { default: TestGridview }, - }); - - // gridview.layout(800, 400); - gridview.fromJSON({ - grid: { - height: 400, - width: 800, - orientation: Orientation.HORIZONTAL, - root: { - type: 'branch', - size: 400, - data: [ - { - type: 'leaf', - size: 800, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - }, - activePanel: 'panel_1', - }); - // gridview.layout(800, 400, true); - - expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({ - grid: { - height: 400, - width: 800, - orientation: Orientation.HORIZONTAL, - root: { - type: 'branch', - size: 400, - data: [ - { - type: 'leaf', - size: 800, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - }, - activePanel: 'panel_1', - }); - }); - - test('#3/HORIZONTAL', () => { - const gridview = new GridviewComponent(container, { - proportionalLayout: true, - orientation: Orientation.HORIZONTAL, - components: { default: TestGridview }, - }); - - // gridview.layout(800, 400); - gridview.fromJSON({ - grid: { - height: 400, - width: 800, - orientation: Orientation.HORIZONTAL, - root: { - type: 'branch', - size: 400, - data: [ - { - type: 'leaf', - size: 400, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 400, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - }, - activePanel: 'panel_1', - }); - // gridview.layout(800, 400, true); - - expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({ - grid: { - height: 400, - width: 800, - orientation: Orientation.HORIZONTAL, - root: { - type: 'branch', - size: 400, - data: [ - { - type: 'leaf', - size: 400, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 400, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - }, - activePanel: 'panel_1', - }); - }); - - test('#4/HORIZONTAL', () => { - const gridview = new GridviewComponent(container, { - proportionalLayout: true, - orientation: Orientation.HORIZONTAL, - components: { default: TestGridview }, - }); - - // gridview.layout(800, 400); - gridview.fromJSON({ - grid: { - height: 400, - width: 800, - orientation: Orientation.HORIZONTAL, - root: { - type: 'branch', - size: 400, - data: [ - { - type: 'leaf', - size: 400, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 200, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 200, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - }, - activePanel: 'panel_1', - }); - // gridview.layout(800, 400, true); - - expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({ - grid: { - height: 400, - width: 800, - orientation: Orientation.HORIZONTAL, - root: { - type: 'branch', - size: 400, - data: [ - { - type: 'leaf', - size: 400, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 200, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 200, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - }, - activePanel: 'panel_1', - }); - }); - - test('#5/VERTICAL', () => { - const gridview = new GridviewComponent(container, { - proportionalLayout: true, - orientation: Orientation.VERTICAL, - components: { default: TestGridview }, - }); - - // gridview.layout(800, 400); - gridview.fromJSON({ - grid: { - height: 400, - width: 800, - orientation: Orientation.VERTICAL, - root: { - type: 'branch', - size: 800, - data: [ - { - type: 'leaf', - size: 100, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 200, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 100, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - }, - activePanel: 'panel_1', - }); - // gridview.layout(800, 400, true); - - expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({ - grid: { - height: 400, - width: 800, - orientation: Orientation.VERTICAL, - root: { - type: 'branch', - size: 800, - data: [ - { - type: 'leaf', - size: 100, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 200, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 100, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - }, - activePanel: 'panel_1', - }); - }); - - test('#5/VERTICAL/proportional/false', () => { - const gridview = new GridviewComponent(container, { - proportionalLayout: false, - orientation: Orientation.VERTICAL, - components: { default: TestGridview }, - }); - - gridview.fromJSON({ - grid: { - height: 400, - width: 800, - orientation: Orientation.VERTICAL, - root: { - type: 'branch', - size: 800, - data: [ - { - type: 'leaf', - size: 100, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 200, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 100, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - }, - activePanel: 'panel_1', - }); - gridview.layout(800, 400, true); - - expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({ - grid: { - height: 400, - width: 800, - orientation: Orientation.VERTICAL, - root: { - type: 'branch', - size: 800, - data: [ - { - type: 'leaf', - size: 100, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 200, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 100, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - }, - activePanel: 'panel_1', - }); - }); - - test('#6/VERTICAL', () => { - const gridview = new GridviewComponent(container, { - proportionalLayout: true, - orientation: Orientation.VERTICAL, - components: { default: TestGridview }, - }); - - // gridview.layout(800, 400); - gridview.fromJSON({ - grid: { - height: 400, - width: 800, - orientation: Orientation.VERTICAL, - root: { - type: 'branch', - size: 800, - data: [ - { - type: 'leaf', - size: 100, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'branch', - size: 200, - data: [ - { - type: 'leaf', - size: 500, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 300, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - { - type: 'leaf', - size: 100, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - }, - activePanel: 'panel_1', - }); - // gridview.layout(800, 400, true); - - expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({ - grid: { - height: 400, - width: 800, - orientation: Orientation.VERTICAL, - root: { - type: 'branch', - size: 800, - data: [ - { - type: 'leaf', - size: 100, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'branch', - size: 200, - data: [ - { - type: 'leaf', - size: 500, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 300, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - { - type: 'leaf', - size: 100, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - }, - activePanel: 'panel_1', - }); - }); - - test('#7/VERTICAL layout first', () => { - const gridview = new GridviewComponent(container, { - proportionalLayout: true, - orientation: Orientation.VERTICAL, - components: { default: TestGridview }, - }); - - gridview.layout(800, 400); - - gridview.fromJSON({ - grid: { - height: 400, - width: 800, - orientation: Orientation.VERTICAL, - root: { - type: 'branch', - size: 800, - data: [ - { - type: 'leaf', - size: 100, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'branch', - size: 200, - data: [ - { - type: 'leaf', - size: 500, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 300, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - { - type: 'leaf', - size: 100, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - }, - activePanel: 'panel_1', - }); - - expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({ - grid: { - height: 400, - width: 800, - orientation: Orientation.VERTICAL, - root: { - type: 'branch', - size: 800, - data: [ - { - type: 'leaf', - size: 100, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'branch', - size: 200, - data: [ - { - type: 'leaf', - size: 500, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 300, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - { - type: 'leaf', - size: 100, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - }, - activePanel: 'panel_1', - }); - }); - - test('#8/VERTICAL layout after', () => { - const gridview = new GridviewComponent(container, { - proportionalLayout: true, - orientation: Orientation.VERTICAL, - components: { default: TestGridview }, - }); - - gridview.fromJSON({ - grid: { - height: 400, - width: 800, - orientation: Orientation.VERTICAL, - root: { - type: 'branch', - size: 800, - data: [ - { - type: 'leaf', - size: 100, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'branch', - size: 200, - data: [ - { - type: 'leaf', - size: 500, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 300, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - { - type: 'leaf', - size: 100, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - }, - activePanel: 'panel_1', - }); - gridview.layout(800, 400, true); - - expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({ - grid: { - height: 400, - width: 800, - orientation: Orientation.VERTICAL, - root: { - type: 'branch', - size: 800, - data: [ - { - type: 'leaf', - size: 100, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'branch', - size: 200, - data: [ - { - type: 'leaf', - size: 500, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 300, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - { - type: 'leaf', - size: 100, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - }, - activePanel: 'panel_1', - }); - }); - - test('#9/HORIZONTAL', () => { - const gridview = new GridviewComponent(container, { - proportionalLayout: true, - orientation: Orientation.HORIZONTAL, - components: { default: TestGridview }, - }); - - gridview.fromJSON({ - grid: { - height: 400, - width: 800, - orientation: Orientation.HORIZONTAL, - root: { - type: 'branch', - size: 400, - data: [ - { - type: 'leaf', - size: 200, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'branch', - size: 400, - data: [ - { - type: 'leaf', - size: 250, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 150, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - { - type: 'leaf', - size: 200, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - }, - activePanel: 'panel_1', - }); - - expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({ - grid: { - height: 400, - width: 800, - orientation: Orientation.HORIZONTAL, - root: { - type: 'branch', - size: 400, - data: [ - { - type: 'leaf', - size: 200, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'branch', - size: 400, - data: [ - { - type: 'leaf', - size: 250, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 150, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - { - type: 'leaf', - size: 200, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - }, - activePanel: 'panel_1', - }); - }); - - test('#9/HORIZONTAL/proportional/false', () => { - const gridview = new GridviewComponent(container, { - proportionalLayout: false, - orientation: Orientation.HORIZONTAL, - components: { default: TestGridview }, - }); - - gridview.fromJSON({ - grid: { - height: 400, - width: 800, - orientation: Orientation.HORIZONTAL, - root: { - type: 'branch', - size: 400, - data: [ - { - type: 'leaf', - size: 200, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'branch', - size: 400, - data: [ - { - type: 'leaf', - size: 250, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 150, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - { - type: 'leaf', - size: 200, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - }, - activePanel: 'panel_1', - }); - - expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({ - grid: { - height: 400, - width: 800, - orientation: Orientation.HORIZONTAL, - root: { - type: 'branch', - size: 400, - data: [ - { - type: 'leaf', - size: 200, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'branch', - size: 400, - data: [ - { - type: 'leaf', - size: 250, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 150, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - { - type: 'leaf', - size: 200, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - }, - activePanel: 'panel_1', - }); - }); - - test('#10/HORIZONTAL scale x:1.5 y:2', () => { - const gridview = new GridviewComponent(container, { - proportionalLayout: true, - orientation: Orientation.HORIZONTAL, - components: { default: TestGridview }, - }); - - gridview.fromJSON({ - grid: { - height: 400, - width: 800, - orientation: Orientation.HORIZONTAL, - root: { - type: 'branch', - size: 400, - data: [ - { - type: 'leaf', - size: 200, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'branch', - size: 400, - data: [ - { - type: 'leaf', - size: 250, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 150, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - { - type: 'leaf', - size: 200, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - }, - activePanel: 'panel_1', - }); - - // relayout to a few random sizes - gridview.layout(234, 654); - gridview.layout(4532, 34562); - gridview.layout(1200, 800); - - expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({ - grid: { - height: 800, - width: 1200, - orientation: Orientation.HORIZONTAL, - root: { - type: 'branch', - size: 800, - data: [ - { - type: 'leaf', - size: 300, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'branch', - size: 600, - data: [ - { - type: 'leaf', - size: 500, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - { - type: 'leaf', - size: 300, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - { - type: 'leaf', - size: 300, - data: { - id: 'panel_1', - component: 'default', - snap: false, - }, - }, - ], - }, - }, - activePanel: 'panel_1', - }); + expect(container.childNodes.length).toBe(0); }); }); diff --git a/packages/dockview/src/__tests__/gridview/gridviewComponent.spec.ts b/packages/dockview/src/__tests__/gridview/gridviewComponent.spec.ts new file mode 100644 index 000000000..a0f0b8919 --- /dev/null +++ b/packages/dockview/src/__tests__/gridview/gridviewComponent.spec.ts @@ -0,0 +1,1647 @@ +import { + GroupChangeEvent, + GroupChangeKind, +} from '../../gridview/baseComponentGridview'; +import { GridviewComponent } from '../../gridview/gridviewComponent'; +import { GridviewPanel } from '../../gridview/gridviewPanel'; +import { IFrameworkPart } from '../../panel/types'; +import { Orientation } from '../../splitview/core/splitview'; + +class TestGridview extends GridviewPanel { + constructor(id: string, componentName: string) { + super(id, componentName); + + this.element.id = id; + } + + getComponent(): IFrameworkPart { + return { + update: (params) => { + // + }, + dispose: () => { + // + }, + }; + } +} + +describe('gridview', () => { + let container: HTMLElement; + + beforeEach(() => { + container = document.createElement('div'); + }); + + test('added views are visible by default', () => { + const gridview = new GridviewComponent(container, { + proportionalLayout: false, + orientation: Orientation.VERTICAL, + components: { default: TestGridview }, + }); + + gridview.layout(800, 400); + + gridview.addPanel({ + id: 'panel_1', + component: 'default', + }); + + const panel = gridview.getPanel('panel_1'); + + expect(panel?.api.isVisible).toBeTruthy(); + }); + + test('remove panel', () => { + const gridview = new GridviewComponent(container, { + proportionalLayout: false, + orientation: Orientation.VERTICAL, + components: { default: TestGridview }, + }); + + gridview.layout(800, 400); + + gridview.addPanel({ + id: 'panel1', + component: 'default', + }); + + expect(gridview.size).toBe(1); + + const panel1 = gridview.getPanel('panel1'); + + gridview.removePanel(panel1); + + expect(gridview.size).toBe(0); + + gridview.addPanel({ + id: 'panel1', + component: 'default', + }); + + expect(gridview.size).toBe(1); + }); + + test('active panel', () => { + const gridview = new GridviewComponent(container, { + proportionalLayout: false, + orientation: Orientation.VERTICAL, + components: { default: TestGridview }, + }); + + gridview.layout(800, 400); + + gridview.addPanel({ + id: 'panel1', + component: 'default', + }); + gridview.addPanel({ + id: 'panel2', + component: 'default', + }); + gridview.addPanel({ + id: 'panel3', + component: 'default', + }); + + const panel1 = gridview.getPanel('panel1'); + const panel2 = gridview.getPanel('panel2'); + const panel3 = gridview.getPanel('panel3'); + + expect(panel1.api.isActive).toBeFalsy(); + expect(panel2.api.isActive).toBeFalsy(); + expect(panel3.api.isActive).toBeTruthy(); + + panel1.api.setActive(); + + expect(panel1.api.isActive).toBeTruthy(); + expect(panel2.api.isActive).toBeFalsy(); + expect(panel3.api.isActive).toBeFalsy(); + + panel2.api.setActive(); + + expect(panel1.api.isActive).toBeFalsy(); + expect(panel2.api.isActive).toBeTruthy(); + expect(panel3.api.isActive).toBeFalsy(); + + panel3.api.setActive(); + + expect(panel1.api.isActive).toBeFalsy(); + expect(panel2.api.isActive).toBeFalsy(); + expect(panel3.api.isActive).toBeTruthy(); + + gridview.removePanel(panel3); + + expect(panel1.api.isActive).toBeTruthy(); + expect(panel2.api.isActive).toBeFalsy(); + + gridview.removePanel(panel1); + + expect(panel2.api.isActive).toBeTruthy(); + + gridview.removePanel(panel2); + }); + + test('deserialize and serialize a layout', () => { + const gridview = new GridviewComponent(container, { + proportionalLayout: false, + orientation: Orientation.VERTICAL, + components: { default: TestGridview }, + }); + + gridview.layout(800, 400); + gridview.fromJSON({ + grid: { + height: 400, + width: 800, + orientation: Orientation.HORIZONTAL, + root: { + type: 'branch', + size: 400, + data: [ + { + type: 'leaf', + size: 300, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 300, + visible: false, + data: { + id: 'panel_2', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 200, + visible: true, + data: { + id: 'panel_3', + component: 'default', + snap: true, + }, + }, + ], + }, + }, + activePanel: 'panel_1', + }); + gridview.layout(800, 400, true); + + const panel1 = gridview.getPanel('panel_1'); + const panel2 = gridview.getPanel('panel_2'); + const panel3 = gridview.getPanel('panel_3'); + + expect(panel1?.api.isVisible).toBeTruthy(); + expect(panel1?.api.id).toBe('panel_1'); + expect(panel1?.api.isActive).toBeTruthy(); + expect(panel1?.api.isFocused).toBeFalsy(); + expect(panel1?.api.height).toBe(400); + expect(panel1?.api.width).toBe(300); + + expect(panel2?.api.isVisible).toBeFalsy(); + expect(panel2?.api.id).toBe('panel_2'); + expect(panel2?.api.isActive).toBeFalsy(); + expect(panel2?.api.isFocused).toBeFalsy(); + expect(panel2?.api.height).toBe(400); + expect(panel2?.api.width).toBe(0); + + expect(panel3?.api.isVisible).toBeTruthy(); + expect(panel3?.api.id).toBe('panel_3'); + expect(panel3?.api.isActive).toBeFalsy(); + expect(panel3?.api.isFocused).toBeFalsy(); + expect(panel3?.api.height).toBe(400); + expect(panel3?.api.width).toBe(500); + + panel2.api.setActive(); + expect(panel1.api.isActive).toBeFalsy(); + expect(panel2.api.isActive).toBeTruthy(); + expect(panel3.api.isActive).toBeFalsy(); + + expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({ + grid: { + height: 400, + width: 800, + orientation: Orientation.HORIZONTAL, + root: { + type: 'branch', + size: 400, + data: [ + { + type: 'leaf', + size: 300, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 300, + visible: false, + data: { + id: 'panel_2', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 500, + data: { + id: 'panel_3', + component: 'default', + snap: true, + }, + }, + ], + }, + }, + activePanel: 'panel_1', + }); + }); + + test('toJSON shouldnt fire any layout events', () => { + const gridview = new GridviewComponent(container, { + proportionalLayout: false, + orientation: Orientation.VERTICAL, + components: { default: TestGridview }, + }); + + gridview.layout(1000, 1000); + + gridview.addPanel({ + id: 'panel1', + component: 'default', + }); + gridview.addPanel({ + id: 'panel2', + component: 'default', + }); + gridview.addPanel({ + id: 'panel3', + component: 'default', + }); + gridview.addPanel({ + id: 'panel4', + component: 'default', + }); + + const disposable = gridview.onDidLayoutChange(() => { + fail('onDidLayoutChange shouldnt have been called'); + }); + + const result = gridview.toJSON(); + expect(result).toBeTruthy(); + + disposable.dispose(); + }); + + test('gridview events', () => { + const gridview = new GridviewComponent(container, { + proportionalLayout: false, + orientation: Orientation.VERTICAL, + components: { default: TestGridview }, + }); + + gridview.layout(800, 400); + + let events: GroupChangeEvent[] = []; + const disposable = gridview.onGridEvent((e) => events.push(e)); + + gridview.addPanel({ + id: 'panel_1', + component: 'default', + }); + + expect(events).toEqual([ + { + kind: GroupChangeKind.ADD_GROUP, + }, + { + kind: GroupChangeKind.GROUP_ACTIVE, + }, + ]); + events = []; + + gridview.addPanel({ + id: 'panel_2', + component: 'default', + }); + + expect(events).toEqual([ + { + kind: GroupChangeKind.ADD_GROUP, + }, + { + kind: GroupChangeKind.GROUP_ACTIVE, + }, + ]); + events = []; + + gridview.addPanel({ + id: 'panel_3', + component: 'default', + }); + + expect(events).toEqual([ + { + kind: GroupChangeKind.ADD_GROUP, + }, + { + kind: GroupChangeKind.GROUP_ACTIVE, + }, + ]); + events = []; + + const panel1 = gridview.getPanel('panel_1'); + const panel2 = gridview.getPanel('panel_2'); + const panel3 = gridview.getPanel('panel_3'); + + gridview.removePanel(panel2); + + expect(events).toEqual([ + { + kind: GroupChangeKind.REMOVE_GROUP, + }, + ]); + events = []; + + gridview.removePanel(panel3); + expect(events).toEqual([ + { + kind: GroupChangeKind.REMOVE_GROUP, + }, + { + kind: GroupChangeKind.GROUP_ACTIVE, + }, + ]); + events = []; + + gridview.removePanel(panel1); + + expect(events).toEqual([ + { + kind: GroupChangeKind.REMOVE_GROUP, + }, + { + kind: GroupChangeKind.GROUP_ACTIVE, + }, + ]); + events = []; + + disposable.dispose(); + }); + + test('dispose of gridviewComponent', () => { + expect(container.childNodes.length).toBe(0); + + const gridview = new GridviewComponent(container, { + proportionalLayout: false, + orientation: Orientation.VERTICAL, + components: { default: TestGridview }, + }); + + gridview.layout(800, 400); + + gridview.addPanel({ + id: 'panel1', + component: 'default', + }); + gridview.addPanel({ + id: 'panel2', + component: 'default', + }); + gridview.addPanel({ + id: 'panel3', + component: 'default', + }); + + expect(container.childNodes.length).toBeGreaterThan(0); + + gridview.dispose(); + + expect(container.childNodes.length).toBe(0); + }); + + test('#1/VERTICAL', () => { + const gridview = new GridviewComponent(container, { + proportionalLayout: true, + orientation: Orientation.VERTICAL, + components: { default: TestGridview }, + }); + + gridview.fromJSON({ + grid: { + height: 400, + width: 800, + orientation: Orientation.VERTICAL, + root: { + type: 'branch', + size: 800, + data: [ + { + type: 'leaf', + size: 400, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + }, + activePanel: 'panel_1', + }); + + expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({ + grid: { + height: 400, + width: 800, + orientation: Orientation.VERTICAL, + root: { + type: 'branch', + size: 800, + data: [ + { + type: 'leaf', + size: 400, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + }, + activePanel: 'panel_1', + }); + }); + + test('#2/HORIZONTAL', () => { + const gridview = new GridviewComponent(container, { + proportionalLayout: true, + orientation: Orientation.HORIZONTAL, + components: { default: TestGridview }, + }); + + // gridview.layout(800, 400); + gridview.fromJSON({ + grid: { + height: 400, + width: 800, + orientation: Orientation.HORIZONTAL, + root: { + type: 'branch', + size: 400, + data: [ + { + type: 'leaf', + size: 800, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + }, + activePanel: 'panel_1', + }); + // gridview.layout(800, 400, true); + + expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({ + grid: { + height: 400, + width: 800, + orientation: Orientation.HORIZONTAL, + root: { + type: 'branch', + size: 400, + data: [ + { + type: 'leaf', + size: 800, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + }, + activePanel: 'panel_1', + }); + }); + + test('#3/HORIZONTAL', () => { + const gridview = new GridviewComponent(container, { + proportionalLayout: true, + orientation: Orientation.HORIZONTAL, + components: { default: TestGridview }, + }); + + // gridview.layout(800, 400); + gridview.fromJSON({ + grid: { + height: 400, + width: 800, + orientation: Orientation.HORIZONTAL, + root: { + type: 'branch', + size: 400, + data: [ + { + type: 'leaf', + size: 400, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 400, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + }, + activePanel: 'panel_1', + }); + // gridview.layout(800, 400, true); + + expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({ + grid: { + height: 400, + width: 800, + orientation: Orientation.HORIZONTAL, + root: { + type: 'branch', + size: 400, + data: [ + { + type: 'leaf', + size: 400, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 400, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + }, + activePanel: 'panel_1', + }); + }); + + test('#4/HORIZONTAL', () => { + const gridview = new GridviewComponent(container, { + proportionalLayout: true, + orientation: Orientation.HORIZONTAL, + components: { default: TestGridview }, + }); + + // gridview.layout(800, 400); + gridview.fromJSON({ + grid: { + height: 400, + width: 800, + orientation: Orientation.HORIZONTAL, + root: { + type: 'branch', + size: 400, + data: [ + { + type: 'leaf', + size: 400, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 200, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 200, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + }, + activePanel: 'panel_1', + }); + // gridview.layout(800, 400, true); + + expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({ + grid: { + height: 400, + width: 800, + orientation: Orientation.HORIZONTAL, + root: { + type: 'branch', + size: 400, + data: [ + { + type: 'leaf', + size: 400, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 200, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 200, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + }, + activePanel: 'panel_1', + }); + }); + + test('#5/VERTICAL', () => { + const gridview = new GridviewComponent(container, { + proportionalLayout: true, + orientation: Orientation.VERTICAL, + components: { default: TestGridview }, + }); + + // gridview.layout(800, 400); + gridview.fromJSON({ + grid: { + height: 400, + width: 800, + orientation: Orientation.VERTICAL, + root: { + type: 'branch', + size: 800, + data: [ + { + type: 'leaf', + size: 100, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 200, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 100, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + }, + activePanel: 'panel_1', + }); + // gridview.layout(800, 400, true); + + expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({ + grid: { + height: 400, + width: 800, + orientation: Orientation.VERTICAL, + root: { + type: 'branch', + size: 800, + data: [ + { + type: 'leaf', + size: 100, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 200, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 100, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + }, + activePanel: 'panel_1', + }); + }); + + test('#5/VERTICAL/proportional/false', () => { + const gridview = new GridviewComponent(container, { + proportionalLayout: false, + orientation: Orientation.VERTICAL, + components: { default: TestGridview }, + }); + + gridview.fromJSON({ + grid: { + height: 400, + width: 800, + orientation: Orientation.VERTICAL, + root: { + type: 'branch', + size: 800, + data: [ + { + type: 'leaf', + size: 100, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 200, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 100, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + }, + activePanel: 'panel_1', + }); + gridview.layout(800, 400, true); + + expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({ + grid: { + height: 400, + width: 800, + orientation: Orientation.VERTICAL, + root: { + type: 'branch', + size: 800, + data: [ + { + type: 'leaf', + size: 100, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 200, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 100, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + }, + activePanel: 'panel_1', + }); + }); + + test('#6/VERTICAL', () => { + const gridview = new GridviewComponent(container, { + proportionalLayout: true, + orientation: Orientation.VERTICAL, + components: { default: TestGridview }, + }); + + // gridview.layout(800, 400); + gridview.fromJSON({ + grid: { + height: 400, + width: 800, + orientation: Orientation.VERTICAL, + root: { + type: 'branch', + size: 800, + data: [ + { + type: 'leaf', + size: 100, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'branch', + size: 200, + data: [ + { + type: 'leaf', + size: 500, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 300, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + { + type: 'leaf', + size: 100, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + }, + activePanel: 'panel_1', + }); + // gridview.layout(800, 400, true); + + expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({ + grid: { + height: 400, + width: 800, + orientation: Orientation.VERTICAL, + root: { + type: 'branch', + size: 800, + data: [ + { + type: 'leaf', + size: 100, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'branch', + size: 200, + data: [ + { + type: 'leaf', + size: 500, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 300, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + { + type: 'leaf', + size: 100, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + }, + activePanel: 'panel_1', + }); + }); + + test('#7/VERTICAL layout first', () => { + const gridview = new GridviewComponent(container, { + proportionalLayout: true, + orientation: Orientation.VERTICAL, + components: { default: TestGridview }, + }); + + gridview.layout(800, 400); + + gridview.fromJSON({ + grid: { + height: 400, + width: 800, + orientation: Orientation.VERTICAL, + root: { + type: 'branch', + size: 800, + data: [ + { + type: 'leaf', + size: 100, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'branch', + size: 200, + data: [ + { + type: 'leaf', + size: 500, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 300, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + { + type: 'leaf', + size: 100, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + }, + activePanel: 'panel_1', + }); + + expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({ + grid: { + height: 400, + width: 800, + orientation: Orientation.VERTICAL, + root: { + type: 'branch', + size: 800, + data: [ + { + type: 'leaf', + size: 100, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'branch', + size: 200, + data: [ + { + type: 'leaf', + size: 500, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 300, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + { + type: 'leaf', + size: 100, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + }, + activePanel: 'panel_1', + }); + }); + + test('#8/VERTICAL layout after', () => { + const gridview = new GridviewComponent(container, { + proportionalLayout: true, + orientation: Orientation.VERTICAL, + components: { default: TestGridview }, + }); + + gridview.fromJSON({ + grid: { + height: 400, + width: 800, + orientation: Orientation.VERTICAL, + root: { + type: 'branch', + size: 800, + data: [ + { + type: 'leaf', + size: 100, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'branch', + size: 200, + data: [ + { + type: 'leaf', + size: 500, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 300, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + { + type: 'leaf', + size: 100, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + }, + activePanel: 'panel_1', + }); + gridview.layout(800, 400, true); + + expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({ + grid: { + height: 400, + width: 800, + orientation: Orientation.VERTICAL, + root: { + type: 'branch', + size: 800, + data: [ + { + type: 'leaf', + size: 100, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'branch', + size: 200, + data: [ + { + type: 'leaf', + size: 500, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 300, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + { + type: 'leaf', + size: 100, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + }, + activePanel: 'panel_1', + }); + }); + + test('#9/HORIZONTAL', () => { + const gridview = new GridviewComponent(container, { + proportionalLayout: true, + orientation: Orientation.HORIZONTAL, + components: { default: TestGridview }, + }); + + gridview.fromJSON({ + grid: { + height: 400, + width: 800, + orientation: Orientation.HORIZONTAL, + root: { + type: 'branch', + size: 400, + data: [ + { + type: 'leaf', + size: 200, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'branch', + size: 400, + data: [ + { + type: 'leaf', + size: 250, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 150, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + { + type: 'leaf', + size: 200, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + }, + activePanel: 'panel_1', + }); + + expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({ + grid: { + height: 400, + width: 800, + orientation: Orientation.HORIZONTAL, + root: { + type: 'branch', + size: 400, + data: [ + { + type: 'leaf', + size: 200, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'branch', + size: 400, + data: [ + { + type: 'leaf', + size: 250, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 150, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + { + type: 'leaf', + size: 200, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + }, + activePanel: 'panel_1', + }); + }); + + test('#9/HORIZONTAL/proportional/false', () => { + const gridview = new GridviewComponent(container, { + proportionalLayout: false, + orientation: Orientation.HORIZONTAL, + components: { default: TestGridview }, + }); + + gridview.fromJSON({ + grid: { + height: 400, + width: 800, + orientation: Orientation.HORIZONTAL, + root: { + type: 'branch', + size: 400, + data: [ + { + type: 'leaf', + size: 200, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'branch', + size: 400, + data: [ + { + type: 'leaf', + size: 250, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 150, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + { + type: 'leaf', + size: 200, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + }, + activePanel: 'panel_1', + }); + + expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({ + grid: { + height: 400, + width: 800, + orientation: Orientation.HORIZONTAL, + root: { + type: 'branch', + size: 400, + data: [ + { + type: 'leaf', + size: 200, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'branch', + size: 400, + data: [ + { + type: 'leaf', + size: 250, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 150, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + { + type: 'leaf', + size: 200, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + }, + activePanel: 'panel_1', + }); + }); + + test('#10/HORIZONTAL scale x:1.5 y:2', () => { + const gridview = new GridviewComponent(container, { + proportionalLayout: true, + orientation: Orientation.HORIZONTAL, + components: { default: TestGridview }, + }); + + gridview.fromJSON({ + grid: { + height: 400, + width: 800, + orientation: Orientation.HORIZONTAL, + root: { + type: 'branch', + size: 400, + data: [ + { + type: 'leaf', + size: 200, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'branch', + size: 400, + data: [ + { + type: 'leaf', + size: 250, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 150, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + { + type: 'leaf', + size: 200, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + }, + activePanel: 'panel_1', + }); + + // relayout to a few random sizes + gridview.layout(234, 654); + gridview.layout(4532, 34562); + gridview.layout(1200, 800); + + expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({ + grid: { + height: 800, + width: 1200, + orientation: Orientation.HORIZONTAL, + root: { + type: 'branch', + size: 800, + data: [ + { + type: 'leaf', + size: 300, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'branch', + size: 600, + data: [ + { + type: 'leaf', + size: 500, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + { + type: 'leaf', + size: 300, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + { + type: 'leaf', + size: 300, + data: { + id: 'panel_1', + component: 'default', + snap: false, + }, + }, + ], + }, + }, + activePanel: 'panel_1', + }); + }); +}); diff --git a/packages/dockview/src/__tests__/paneview/paneview.spec.ts b/packages/dockview/src/__tests__/paneview/paneview.spec.ts index df8eda12e..1abefcf0c 100644 --- a/packages/dockview/src/__tests__/paneview/paneview.spec.ts +++ b/packages/dockview/src/__tests__/paneview/paneview.spec.ts @@ -102,4 +102,38 @@ describe('paneview', () => { disposable.dispose(); }); + + test('dispose of paneview', () => { + expect(container.childNodes.length).toBe(0); + + const paneview = new Paneview(container, { + orientation: Orientation.HORIZONTAL, + }); + + const view1 = new TestPanel( + 'id', + 'component', + 'headerComponent', + Orientation.VERTICAL, + true, + true + ); + const view2 = new TestPanel( + 'id2', + 'component', + 'headerComponent', + Orientation.VERTICAL, + true, + true + ); + + paneview.addPane(view1); + paneview.addPane(view2); + + expect(container.childNodes.length).toBeGreaterThan(0); + + paneview.dispose(); + + expect(container.childNodes.length).toBe(0); + }); }); diff --git a/packages/dockview/src/__tests__/paneview/paneviewComponent.spec.ts b/packages/dockview/src/__tests__/paneview/paneviewComponent.spec.ts index 86ecdd552..0c2b81c96 100644 --- a/packages/dockview/src/__tests__/paneview/paneviewComponent.spec.ts +++ b/packages/dockview/src/__tests__/paneview/paneviewComponent.spec.ts @@ -276,4 +276,33 @@ describe('componentPaneview', () => { disposable.dispose(); }); + + test('dispose of paneviewComponent', () => { + expect(container.childNodes.length).toBe(0); + + const paneview = new PaneviewComponent(container, { + components: { + testPanel: TestPanel, + }, + }); + + paneview.layout(1000, 1000); + + paneview.addPanel({ + id: 'panel1', + component: 'testPanel', + title: 'Panel 1', + }); + paneview.addPanel({ + id: 'panel2', + component: 'testPanel', + title: 'Panel 2', + }); + + expect(container.childNodes.length).toBeGreaterThan(0); + + paneview.dispose(); + + expect(container.childNodes.length).toBe(0); + }); }); diff --git a/packages/dockview/src/__tests__/splitview/core/splitview.spec.ts b/packages/dockview/src/__tests__/splitview/core/splitview.spec.ts index e8f0e4fe3..ef4f607d2 100644 --- a/packages/dockview/src/__tests__/splitview/core/splitview.spec.ts +++ b/packages/dockview/src/__tests__/splitview/core/splitview.spec.ts @@ -565,4 +565,25 @@ describe('splitview', () => { disposable.dispose(); }); + + test('dispose of splitview', () => { + expect(container.childNodes.length).toBe(0); + + const splitview = new Splitview(container, { + orientation: Orientation.HORIZONTAL, + proportionalLayout: false, + }); + + const view1 = new Testview(0, 100); + const view2 = new Testview(0, 100); + + splitview.addView(view1); + splitview.addView(view2); + + expect(container.childNodes.length).toBeGreaterThan(0); + + splitview.dispose(); + + expect(container.childNodes.length).toBe(0); + }); }); diff --git a/packages/dockview/src/__tests__/splitview/splitviewComponent.spec.ts b/packages/dockview/src/__tests__/splitview/splitviewComponent.spec.ts index 25f70b75d..884ca5849 100644 --- a/packages/dockview/src/__tests__/splitview/splitviewComponent.spec.ts +++ b/packages/dockview/src/__tests__/splitview/splitviewComponent.spec.ts @@ -358,37 +358,31 @@ describe('componentSplitview', () => { disposable.dispose(); }); - class EventListenerTracker { - private events = new Map>(); + test('dispose of splitviewComponent', () => { + expect(container.childNodes.length).toBe(0); - get size() { - return this.events.size; - } + const splitview = new SplitviewComponent(container, { + orientation: Orientation.HORIZONTAL, + components: { + testPanel: TestPanel, + }, + }); - constructor() { - const originalAddEventListener = document.addEventListener; - const originalRemoveEventListener = document.removeEventListener; + splitview.layout(1000, 1000); - document.addEventListener = jest.fn((event, callback, options) => { - if (!this.events.has(event)) { - this.events.set(event, new Set()); - } - this.events.get(event).add(callback); - originalAddEventListener(event, callback, options); - }); + splitview.addPanel({ + id: 'panel1', + component: 'testPanel', + }); + splitview.addPanel({ + id: 'panel2', + component: 'testPanel', + }); - document.removeEventListener = jest.fn( - (event, callback, options) => { - if (this.events.has(event)) { - this.events.get(event).delete(callback); - if (this.events.get(event).size === 0) { - this.events.delete(event); - } - } + expect(container.childNodes.length).toBeGreaterThan(0); - originalRemoveEventListener(event, callback, options); - } - ); - } - } + splitview.dispose(); + + expect(container.childNodes.length).toBe(0); + }); }); diff --git a/packages/dockview/src/gridview/gridview.ts b/packages/dockview/src/gridview/gridview.ts index 3fd7a756a..1d67a183c 100644 --- a/packages/dockview/src/gridview/gridview.ts +++ b/packages/dockview/src/gridview/gridview.ts @@ -287,6 +287,8 @@ export class Gridview implements IDisposable { this.disposable.dispose(); this._onDidChange.dispose(); this.root.dispose(); + + this.element.remove(); } public clear() { diff --git a/packages/dockview/src/paneview/paneview.ts b/packages/dockview/src/paneview/paneview.ts index 8e09033c4..73742e3a2 100644 --- a/packages/dockview/src/paneview/paneview.ts +++ b/packages/dockview/src/paneview/paneview.ts @@ -189,8 +189,6 @@ export class Paneview extends CompositeDisposable implements IDisposable { public dispose() { super.dispose(); - this.splitview.dispose(); - if (this.animationTimer) { clearTimeout(this.animationTimer); this.animationTimer = undefined; @@ -201,6 +199,7 @@ export class Paneview extends CompositeDisposable implements IDisposable { }); this.paneItems = []; + this.splitview.dispose(); this.element.remove(); } } diff --git a/packages/dockview/src/paneview/paneviewComponent.ts b/packages/dockview/src/paneview/paneviewComponent.ts index 642b8a730..2b5c72a2b 100644 --- a/packages/dockview/src/paneview/paneviewComponent.ts +++ b/packages/dockview/src/paneview/paneviewComponent.ts @@ -452,4 +452,10 @@ export class PaneviewComponent queue.forEach((f) => f()); } } + + public dispose(): void { + super.dispose(); + + this.paneview.dispose(); + } } diff --git a/packages/dockview/src/react/dockview/dockview.tsx b/packages/dockview/src/react/dockview/dockview.tsx index 76dee4f85..38f7726e3 100644 --- a/packages/dockview/src/react/dockview/dockview.tsx +++ b/packages/dockview/src/react/dockview/dockview.tsx @@ -155,6 +155,7 @@ export const DockviewReact = React.forwardRef( return () => { disposable.dispose(); dockview.dispose(); + element.remove(); }; }, []); diff --git a/packages/dockview/src/react/gridview/gridview.tsx b/packages/dockview/src/react/gridview/gridview.tsx index 33a2dfa97..65860da3c 100644 --- a/packages/dockview/src/react/gridview/gridview.tsx +++ b/packages/dockview/src/react/gridview/gridview.tsx @@ -96,6 +96,7 @@ export const GridviewReact = React.forwardRef( return () => { gridview.dispose(); + element.remove(); }; }, []); diff --git a/packages/dockview/src/splitview/core/splitview.ts b/packages/dockview/src/splitview/core/splitview.ts index 72b1c78c9..47fcfe0ff 100644 --- a/packages/dockview/src/splitview/core/splitview.ts +++ b/packages/dockview/src/splitview/core/splitview.ts @@ -1038,12 +1038,13 @@ export class Splitview { this._onDidAddView.dispose(); this._onDidRemoveView.dispose(); - this.element.remove(); for (let i = 0; i < this.element.children.length; i++) { if (this.element.children.item(i) === this.element) { this.element.removeChild(this.element); break; } } + + this.element.remove(); } } diff --git a/packages/dockview/src/splitview/splitviewComponent.ts b/packages/dockview/src/splitview/splitviewComponent.ts index fd3c34733..66775a33c 100644 --- a/packages/dockview/src/splitview/splitviewComponent.ts +++ b/packages/dockview/src/splitview/splitviewComponent.ts @@ -421,6 +421,8 @@ export class SplitviewComponent }); this.panels.clear(); + this.splitview.dispose(); + super.dispose(); } }