Merge pull request #194 from mathuo/191-dockview-watermark-fixes

feat: attach watermark seperately from groups
This commit is contained in:
mathuo 2023-02-25 18:36:55 +08:00 committed by GitHub
commit 417cdf875f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 142 additions and 62 deletions

View File

@ -7,7 +7,6 @@ import {
import { PanelUpdateEvent } from '../../panel/types'; import { PanelUpdateEvent } from '../../panel/types';
import { Orientation } from '../../splitview/core/splitview'; import { Orientation } from '../../splitview/core/splitview';
import { ReactPanelDeserialzier } from '../../react/deserializer'; import { ReactPanelDeserialzier } from '../../react/deserializer';
import { Position } from '../../dnd/droptarget';
import { GroupPanel } from '../../groupview/groupviewPanel'; import { GroupPanel } from '../../groupview/groupviewPanel';
import { CompositeDisposable } from '../../lifecycle'; import { CompositeDisposable } from '../../lifecycle';
import { import {
@ -459,7 +458,7 @@ describe('dockviewComponent', () => {
await panel2.api.close(); await panel2.api.close();
expect(dockview.size).toBe(1); // watermark expect(dockview.size).toBe(0);
expect(dockview.totalPanels).toBe(0); expect(dockview.totalPanels).toBe(0);
}); });
@ -1206,55 +1205,6 @@ describe('dockviewComponent', () => {
expect(dockview.totalPanels).toBe(0); expect(dockview.totalPanels).toBe(0);
}); });
test('last group is retained for watermark', () => {
const container = document.createElement('div');
const dockview = new DockviewComponent(container, {
components: { default: PanelContentPartTest },
});
dockview.layout(500, 1000);
const panel1 = dockview.addPanel({
id: 'panel1',
component: 'default',
tabComponent: 'default',
});
expect(dockview.size).toBe(1);
expect(dockview.totalPanels).toBe(1);
const group = panel1.group;
dockview.removePanel(panel1);
expect(group.model.hasWatermark).toBeTruthy();
expect(dockview.size).toBe(1);
expect(dockview.totalPanels).toBe(0);
const panel2 = dockview.addPanel({
id: 'panel2',
component: 'default',
tabComponent: 'default',
});
expect(group.model.hasWatermark).toBeFalsy();
const panel3 = dockview.addPanel({
id: 'panel3',
component: 'default',
tabComponent: 'default',
});
expect(dockview.size).toBe(1);
expect(dockview.totalPanels).toBe(2);
panel2.api.close();
expect(group.model.hasWatermark).toBeFalsy();
panel3.api.close();
expect(group.model.hasWatermark).toBeTruthy();
});
test('panel is disposed of when removed', () => { test('panel is disposed of when removed', () => {
const container = document.createElement('div'); const container = document.createElement('div');
@ -2392,4 +2342,91 @@ describe('dockviewComponent', () => {
options: {}, options: {},
}); });
}); });
test('that a empty component has no groups', () => {
const container = document.createElement('div');
const dockview = new DockviewComponent(container, {
components: {
default: PanelContentPartTest,
},
tabComponents: {
test_tab_id: PanelTabPartTest,
},
orientation: Orientation.HORIZONTAL,
});
dockview.deserializer = new ReactPanelDeserialzier(dockview);
expect(dockview.groups.length).toBe(0);
});
test('that deserializing an empty layout has zero groups and a watermark', () => {
const container = document.createElement('div');
const dockview = new DockviewComponent(container, {
components: {
default: PanelContentPartTest,
},
tabComponents: {
test_tab_id: PanelTabPartTest,
},
orientation: Orientation.HORIZONTAL,
});
dockview.deserializer = new ReactPanelDeserialzier(dockview);
expect(dockview.groups.length).toBe(0);
expect(
dockview.element.querySelectorAll('.dv-watermark-container').length
).toBe(1);
dockview.fromJSON({
grid: {
orientation: Orientation.HORIZONTAL,
root: {
type: 'branch',
data: [],
},
height: 100,
width: 100,
},
panels: {},
});
expect(dockview.groups.length).toBe(0);
expect(
dockview.element.querySelectorAll('.dv-watermark-container').length
).toBe(1);
});
test('empty', () => {
const container = document.createElement('div');
const dockview = new DockviewComponent(container, {
components: {
default: PanelContentPartTest,
},
tabComponents: {
test_tab_id: PanelTabPartTest,
},
orientation: Orientation.HORIZONTAL,
});
dockview.deserializer = new ReactPanelDeserialzier(dockview);
expect(JSON.parse(JSON.stringify(dockview.toJSON()))).toEqual({
grid: {
height: 0,
width: 0,
orientation: Orientation.HORIZONTAL,
root: {
data: [],
type: 'branch',
size: 0,
},
},
options: {},
panels: {},
});
});
}); });

View File

@ -1,3 +1,16 @@
.dv-dockview {
position: relative;
background-color: var(--dv-group-view-background-color);
.dv-watermark-container {
position: absolute;
top: 0px;
left: 0px;
height: 100%;
width: 100%;
}
}
.groupview { .groupview {
&.active-group { &.active-group {
> .tabs-and-actions-container > .tabs-container > .tab { > .tabs-and-actions-container > .tabs-container > .tab {

View File

@ -131,6 +131,7 @@ export class DockviewComponent
private _deserializer: IPanelDeserializer | undefined; private _deserializer: IPanelDeserializer | undefined;
private _api: DockviewApi; private _api: DockviewApi;
private _options: Exclude<DockviewComponentOptions, 'orientation'>; private _options: Exclude<DockviewComponentOptions, 'orientation'>;
private watermark: IWatermarkRenderer | null = null;
private readonly _onDidDrop = new Emitter<DockviewDropEvent>(); private readonly _onDidDrop = new Emitter<DockviewDropEvent>();
readonly onDidDrop: Event<DockviewDropEvent> = this._onDidDrop.event; readonly onDidDrop: Event<DockviewDropEvent> = this._onDidDrop.event;
@ -203,8 +204,16 @@ export class DockviewComponent
styles: options.styles, styles: options.styles,
}); });
this.element.classList.add('dv-dockview');
this.addDisposables( this.addDisposables(
this._onDidDrop, this._onDidDrop,
Event.any(
this.onDidAddGroup,
this.onDidRemoveGroup
)(() => {
this.updateWatermark();
}),
Event.any( Event.any(
this.onDidAddPanel, this.onDidAddPanel,
this.onDidRemovePanel, this.onDidRemovePanel,
@ -288,6 +297,8 @@ export class DockviewComponent
); );
this._api = new DockviewApi(this); this._api = new DockviewApi(this);
this.updateWatermark();
} }
private orthogonalize(position: Position): GroupPanel { private orthogonalize(position: Position): GroupPanel {
@ -421,7 +432,7 @@ export class DockviewComponent
this.clear(); this.clear();
if (!this.deserializer) { if (!this.deserializer) {
throw new Error('invalid deserializer'); throw new Error('no deserializer provided');
} }
const { grid, panels, options, activeGroup } = data; const { grid, panels, options, activeGroup } = data;
@ -429,8 +440,8 @@ export class DockviewComponent
this.tabHeight = options.tabHeight; this.tabHeight = options.tabHeight;
} }
if (!this.deserializer) { if (grid.root.type !== 'branch' || !Array.isArray(grid.root.data)) {
throw new Error('no deserializer provided'); throw new Error('root must be of type branch');
} }
this.gridview.deserialize(grid, { this.gridview.deserialize(grid, {
@ -610,13 +621,7 @@ export class DockviewComponent
panel.dispose(); panel.dispose();
const retainGroupForWatermark = this.size === 1; if (group.size === 0 && options.removeEmptyGroup) {
if (
!retainGroupForWatermark &&
group.size === 0 &&
options.removeEmptyGroup
) {
this.removeGroup(group); this.removeGroup(group);
} }
} }
@ -635,7 +640,32 @@ export class DockviewComponent
); );
} }
addGroup(options: AddGroupOptions): GroupPanel { private updateWatermark(): void {
if (this.groups.length === 0) {
if (!this.watermark) {
this.watermark = this.createWatermarkComponent();
this.watermark.init({
containerApi: new DockviewApi(this),
params: {},
title: '',
api: null as any,
});
const watermarkContainer = document.createElement('div');
watermarkContainer.className = 'dv-watermark-container';
watermarkContainer.appendChild(this.watermark.element);
this.element.appendChild(watermarkContainer);
}
} else if (this.watermark) {
this.watermark.element.parentElement!.remove();
this.watermark.dispose();
this.watermark = null;
}
}
addGroup(options?: AddGroupOptions): GroupPanel {
const group = this.createGroup(); const group = this.createGroup();
if (options) { if (options) {