mirror of
https://github.com/mathuo/dockview
synced 2025-09-06 01:16:33 +00:00
feat: adjust to make group non-optional
This commit is contained in:
parent
05f8ab8f8b
commit
a6b0250b86
@ -619,7 +619,7 @@ describe('dockviewComponent', () => {
|
||||
data: {
|
||||
views: ['panel2', 'panel3'],
|
||||
id: 'group-2',
|
||||
activeView: 'panel2',
|
||||
activeView: 'panel3',
|
||||
},
|
||||
size: 500,
|
||||
},
|
||||
|
@ -1,19 +1,26 @@
|
||||
import { DockviewComponent } from '../..';
|
||||
import { DockviewComponent } from '../../dockview/dockviewComponent';
|
||||
import { DockviewApi } from '../../api/component.api';
|
||||
import { IGroupPanelView } from '../../dockview/defaultGroupPanelView';
|
||||
import { DockviewGroupPanel } from '../../dockview/dockviewGroupPanel';
|
||||
import { GroupviewPanel } from '../../groupview/groupviewPanel';
|
||||
|
||||
describe('dockviewGroupPanel', () => {
|
||||
test('update title', () => {
|
||||
const dockviewApiMock = jest.fn<DockviewApi, []>(() => {
|
||||
return {} as any;
|
||||
return {
|
||||
onDidActiveChange: jest.fn(),
|
||||
} as any;
|
||||
});
|
||||
const accessorMock = jest.fn<DockviewComponent, []>(() => {
|
||||
return {} as any;
|
||||
});
|
||||
const groupMock = jest.fn<GroupviewPanel, []>(() => {
|
||||
return {} as any;
|
||||
});
|
||||
const api = new dockviewApiMock();
|
||||
const accessor = new accessorMock();
|
||||
const cut = new DockviewGroupPanel('fake-id', accessor, api);
|
||||
const group = new groupMock();
|
||||
const cut = new DockviewGroupPanel('fake-id', accessor, api, group);
|
||||
|
||||
let latestTitle: string | undefined = undefined;
|
||||
|
||||
@ -41,10 +48,14 @@ describe('dockviewGroupPanel', () => {
|
||||
const accessorMock = jest.fn<DockviewComponent, []>(() => {
|
||||
return {} as any;
|
||||
});
|
||||
const groupMock = jest.fn<GroupviewPanel, []>(() => {
|
||||
return {} as any;
|
||||
});
|
||||
const api = new dockviewApiMock();
|
||||
const accessor = new accessorMock();
|
||||
const group = new groupMock();
|
||||
|
||||
const cut = new DockviewGroupPanel('fake-id', accessor, api);
|
||||
const cut = new DockviewGroupPanel('fake-id', accessor, api, group);
|
||||
|
||||
let latestSuppressClosable: boolean | undefined = undefined;
|
||||
|
||||
@ -77,10 +88,14 @@ describe('dockviewGroupPanel', () => {
|
||||
const accessorMock = jest.fn<DockviewComponent, []>(() => {
|
||||
return {} as any;
|
||||
});
|
||||
const groupMock = jest.fn<GroupviewPanel, []>(() => {
|
||||
return {} as any;
|
||||
});
|
||||
const api = new dockviewApiMock();
|
||||
const accessor = new accessorMock();
|
||||
const group = new groupMock();
|
||||
|
||||
const cut = new DockviewGroupPanel('fake-id', accessor, api);
|
||||
const cut = new DockviewGroupPanel('fake-id', accessor, api, group);
|
||||
|
||||
const viewMock = jest.fn<IGroupPanelView, []>(() => {
|
||||
return {
|
||||
|
@ -17,7 +17,7 @@ export interface SuppressClosableEvent {
|
||||
* because it belongs to a groupview
|
||||
*/
|
||||
export interface DockviewPanelApi extends Omit<GridviewPanelApi, 'setVisible'> {
|
||||
readonly group: GroupviewPanel | undefined;
|
||||
readonly group: GroupviewPanel;
|
||||
readonly isGroupActive: boolean;
|
||||
readonly title: string;
|
||||
readonly suppressClosable: boolean;
|
||||
@ -29,7 +29,7 @@ export class DockviewPanelApiImpl
|
||||
extends GridviewPanelApiImpl
|
||||
implements DockviewPanelApi
|
||||
{
|
||||
private _group: GroupviewPanel | undefined;
|
||||
private _group: GroupviewPanel;
|
||||
|
||||
readonly _onDidTitleChange = new Emitter<TitleEvent>();
|
||||
readonly onDidTitleChange = this._onDidTitleChange.event;
|
||||
@ -60,7 +60,7 @@ export class DockviewPanelApiImpl
|
||||
return !!this.group?.isActive;
|
||||
}
|
||||
|
||||
set group(value: GroupviewPanel | undefined) {
|
||||
set group(value: GroupviewPanel) {
|
||||
const isOldGroupActive = this.isGroupActive;
|
||||
|
||||
this._group = value;
|
||||
@ -78,13 +78,13 @@ export class DockviewPanelApiImpl
|
||||
}
|
||||
}
|
||||
|
||||
get group(): GroupviewPanel | undefined {
|
||||
get group(): GroupviewPanel {
|
||||
return this._group;
|
||||
}
|
||||
|
||||
constructor(private panel: IGroupPanel, group: GroupviewPanel | undefined) {
|
||||
constructor(private panel: IGroupPanel, group: GroupviewPanel) {
|
||||
super(panel.id);
|
||||
this.group = group;
|
||||
this._group = group;
|
||||
|
||||
this.addDisposables(
|
||||
this.disposable,
|
||||
|
@ -5,17 +5,21 @@ import {
|
||||
} from '../gridview/gridview';
|
||||
import { GroupviewPanelState, IGroupPanel } from '../groupview/groupPanel';
|
||||
import { GroupPanelViewState } from '../groupview/groupview';
|
||||
import { GroupviewPanel } from '../groupview/groupviewPanel';
|
||||
import { DockviewComponent } from './dockviewComponent';
|
||||
|
||||
export interface IPanelDeserializer {
|
||||
fromJSON(panelData: GroupviewPanelState): IGroupPanel;
|
||||
fromJSON(
|
||||
panelData: GroupviewPanelState,
|
||||
group: GroupviewPanel
|
||||
): IGroupPanel;
|
||||
}
|
||||
|
||||
export class DefaultDeserializer implements IViewDeserializer {
|
||||
constructor(
|
||||
private readonly layout: DockviewComponent,
|
||||
private panelDeserializer: {
|
||||
createPanel: (id: string) => IGroupPanel;
|
||||
createPanel: (id: string, group: GroupviewPanel) => IGroupPanel;
|
||||
}
|
||||
) {}
|
||||
|
||||
@ -24,29 +28,26 @@ export class DefaultDeserializer implements IViewDeserializer {
|
||||
const children = data.views;
|
||||
const active = data.activeView;
|
||||
|
||||
const panels: IGroupPanel[] = [];
|
||||
|
||||
for (const child of children) {
|
||||
const panel = this.panelDeserializer.createPanel(child);
|
||||
|
||||
panels.push(panel);
|
||||
}
|
||||
|
||||
return this.layout.createGroup({
|
||||
panels,
|
||||
activePanel: panels.find((p) => p.id === active),
|
||||
const group = this.layout.createGroup({
|
||||
id: data.id,
|
||||
locked: !!data.locked,
|
||||
headerHidden: !!data.headerHidden,
|
||||
});
|
||||
}
|
||||
|
||||
for (const child of children) {
|
||||
const panel = this.panelDeserializer.createPanel(child, group);
|
||||
|
||||
const isActive = typeof active === 'string' && active === panel.id;
|
||||
|
||||
group.model.openPanel(panel, {
|
||||
skipSetActive: !isActive,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* isGroup
|
||||
*
|
||||
*
|
||||
* panel.group.locked = true
|
||||
* panel.group.header.hiddden = true
|
||||
*
|
||||
*/
|
||||
if (!group.activePanel && group.panels.length > 0) {
|
||||
group.model.openPanel(group.panels[group.panels.length - 1]);
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
}
|
||||
|
@ -263,9 +263,6 @@ export class DockviewComponent
|
||||
}
|
||||
|
||||
setActivePanel(panel: IGroupPanel): void {
|
||||
if (!panel.group) {
|
||||
throw new Error(`Panel ${panel.id} has no associated group`);
|
||||
}
|
||||
this.doSetGroupActive(panel.group);
|
||||
panel.group.model.openPanel(panel);
|
||||
}
|
||||
@ -367,9 +364,9 @@ export class DockviewComponent
|
||||
this.gridview.deserialize(
|
||||
grid,
|
||||
new DefaultDeserializer(this, {
|
||||
createPanel: (id) => {
|
||||
createPanel: (id, group) => {
|
||||
const panelData = panels[id];
|
||||
return this.deserializer!.fromJSON(panelData);
|
||||
return this.deserializer!.fromJSON(panelData, group);
|
||||
},
|
||||
})
|
||||
);
|
||||
@ -411,8 +408,6 @@ export class DockviewComponent
|
||||
throw new Error(`panel with id ${options.id} already exists`);
|
||||
}
|
||||
|
||||
const panel = this.createPanel(options);
|
||||
|
||||
let referenceGroup: GroupviewPanel | undefined;
|
||||
|
||||
if (options.position?.referencePanel) {
|
||||
@ -431,9 +426,12 @@ export class DockviewComponent
|
||||
referenceGroup = this.activeGroup;
|
||||
}
|
||||
|
||||
let panel: IGroupPanel
|
||||
|
||||
if (referenceGroup) {
|
||||
const target = toTarget(options.position?.direction || 'within');
|
||||
if (target === Position.Center) {
|
||||
panel = this.createPanel(options, referenceGroup)
|
||||
referenceGroup.model.openPanel(panel);
|
||||
} else {
|
||||
const location = getGridLocation(referenceGroup.element);
|
||||
@ -442,10 +440,14 @@ export class DockviewComponent
|
||||
location,
|
||||
target
|
||||
);
|
||||
this.addPanelToNewGroup(panel, relativeLocation);
|
||||
const group = this.createGroupAtLocation(relativeLocation);
|
||||
panel = this.createPanel(options, group)
|
||||
group.model.openPanel(panel);
|
||||
}
|
||||
} else {
|
||||
this.addPanelToNewGroup(panel);
|
||||
const group = this.createGroupAtLocation();
|
||||
panel = this.createPanel(options, group);
|
||||
group.model.openPanel(panel);
|
||||
}
|
||||
|
||||
return panel;
|
||||
@ -622,7 +624,8 @@ export class DockviewComponent
|
||||
target
|
||||
);
|
||||
|
||||
this.addPanelToNewGroup(groupItem, dropLocation);
|
||||
const group = this.createGroupAtLocation( dropLocation);
|
||||
group.model.openPanel(groupItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -710,13 +713,13 @@ export class DockviewComponent
|
||||
return view;
|
||||
}
|
||||
|
||||
private createPanel(options: AddPanelOptions): IGroupPanel {
|
||||
private createPanel(options: AddPanelOptions, group: GroupviewPanel): IGroupPanel {
|
||||
const view = new DefaultGroupPanelView({
|
||||
content: this.createContentComponent(options.id, options.component),
|
||||
tab: this.createTabComponent(options.id, options.tabComponent),
|
||||
});
|
||||
|
||||
const panel = new DockviewGroupPanel(options.id, this, this._api);
|
||||
const panel = new DockviewGroupPanel(options.id, this, this._api, group);
|
||||
panel.init({
|
||||
view,
|
||||
title: options.title || options.id,
|
||||
@ -754,14 +757,12 @@ export class DockviewComponent
|
||||
);
|
||||
}
|
||||
|
||||
private addPanelToNewGroup(
|
||||
panel: IGroupPanel,
|
||||
private createGroupAtLocation(
|
||||
location: number[] = [0]
|
||||
): void {
|
||||
): GroupviewPanel {
|
||||
const group = this.createGroup();
|
||||
this.doAddGroup(group, location);
|
||||
|
||||
group.model.openPanel(panel);
|
||||
return group
|
||||
}
|
||||
|
||||
private findGroup(panel: IGroupPanel): GroupviewPanel | undefined {
|
||||
|
@ -19,7 +19,7 @@ export class DockviewGroupPanel
|
||||
private readonly mutableDisposable = new MutableDisposable();
|
||||
|
||||
readonly api: DockviewPanelApiImpl;
|
||||
private _group: GroupviewPanel | undefined;
|
||||
private _group: GroupviewPanel;
|
||||
private _params?: Parameters;
|
||||
|
||||
private _view?: IGroupPanelView;
|
||||
@ -39,7 +39,7 @@ export class DockviewGroupPanel
|
||||
return this._suppressClosable;
|
||||
}
|
||||
|
||||
get group(): GroupviewPanel | undefined {
|
||||
get group(): GroupviewPanel {
|
||||
return this._group;
|
||||
}
|
||||
|
||||
@ -50,11 +50,13 @@ export class DockviewGroupPanel
|
||||
constructor(
|
||||
public readonly id: string,
|
||||
accessor: DockviewComponent,
|
||||
private readonly containerApi: DockviewApi
|
||||
private readonly containerApi: DockviewApi,
|
||||
group: GroupviewPanel
|
||||
) {
|
||||
super();
|
||||
this._suppressClosable = false;
|
||||
this._title = '';
|
||||
this._group = group;
|
||||
|
||||
this.api = new DockviewPanelApiImpl(this, this._group);
|
||||
|
||||
@ -169,7 +171,7 @@ export class DockviewGroupPanel
|
||||
// the obtain the correct dimensions of the content panel we must deduct the tab height
|
||||
this.api._onDidPanelDimensionChange.fire({
|
||||
width,
|
||||
height: height - (this.group?.model.header.height || 0),
|
||||
height: height - (this.group.model.header.height || 0),
|
||||
});
|
||||
|
||||
this.view?.layout(width, height);
|
||||
|
@ -24,7 +24,7 @@ export type GroupPanelUpdateEvent = PanelUpdateEvent<{
|
||||
|
||||
export interface IGroupPanel extends IDisposable, IPanel {
|
||||
readonly view?: IGroupPanelView;
|
||||
readonly group?: GroupviewPanel;
|
||||
readonly group: GroupviewPanel;
|
||||
readonly api: DockviewPanelApi;
|
||||
readonly title: string;
|
||||
readonly suppressClosable: boolean;
|
||||
|
@ -394,7 +394,11 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
||||
|
||||
public openPanel(
|
||||
panel: IGroupPanel,
|
||||
options: { index?: number; skipFocus?: boolean } = {}
|
||||
options: {
|
||||
index?: number;
|
||||
skipFocus?: boolean;
|
||||
skipSetActive?: boolean;
|
||||
} = {}
|
||||
) {
|
||||
if (
|
||||
typeof options.index !== 'number' ||
|
||||
@ -403,18 +407,22 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
||||
options.index = this.panels.length;
|
||||
}
|
||||
|
||||
const skipSetActive = !!options.skipSetActive;
|
||||
|
||||
// ensure the group is updated before we fire any events
|
||||
panel.updateParentGroup(this.parent, true);
|
||||
|
||||
if (this._activePanel === panel) {
|
||||
if (!skipSetActive && this._activePanel === panel) {
|
||||
this.accessor.doSetGroupActive(this.parent);
|
||||
return;
|
||||
}
|
||||
|
||||
this.doAddPanel(panel, options.index);
|
||||
|
||||
if (!skipSetActive) {
|
||||
this.doSetActivePanel(panel);
|
||||
this.accessor.doSetGroupActive(this.parent, !!options.skipFocus);
|
||||
}
|
||||
|
||||
this.updateContainer();
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import {
|
||||
GridviewPanelApi,
|
||||
GridviewPanelApiImpl,
|
||||
} from '../api/gridviewPanelApi';
|
||||
import { Groupview, GroupOptions, IGroupview } from './groupview';
|
||||
import { Groupview, GroupOptions, IHeader } from './groupview';
|
||||
import { GridviewPanel, IGridviewPanel } from '../gridview/gridviewPanel';
|
||||
import { IGroupPanel } from './groupPanel';
|
||||
|
||||
@ -65,6 +65,10 @@ export class GroupviewPanel extends GridviewPanel implements IGroupviewPanel {
|
||||
this._model.locked = value;
|
||||
}
|
||||
|
||||
get header(): IHeader {
|
||||
return this._model.header;
|
||||
}
|
||||
|
||||
constructor(
|
||||
accessor: IDockviewComponent,
|
||||
id: string,
|
||||
|
@ -6,11 +6,15 @@ import { createComponent } from '../panel/componentFactory';
|
||||
import { DockviewApi } from '../api/component.api';
|
||||
import { DefaultTab } from '../dockview/components/tab/defaultTab';
|
||||
import { DefaultGroupPanelView } from '../dockview/defaultGroupPanelView';
|
||||
import { GroupviewPanel } from '../groupview/groupviewPanel';
|
||||
|
||||
export class ReactPanelDeserialzier implements IPanelDeserializer {
|
||||
constructor(private readonly layout: DockviewComponent) {}
|
||||
|
||||
public fromJSON(panelData: GroupviewPanelState): IGroupPanel {
|
||||
public fromJSON(
|
||||
panelData: GroupviewPanelState,
|
||||
group: GroupviewPanel
|
||||
): IGroupPanel {
|
||||
const panelId = panelData.id;
|
||||
const params = panelData.params;
|
||||
const title = panelData.title;
|
||||
@ -39,7 +43,8 @@ export class ReactPanelDeserialzier implements IPanelDeserializer {
|
||||
const panel = new DockviewGroupPanel(
|
||||
panelId,
|
||||
this.layout,
|
||||
new DockviewApi(this.layout)
|
||||
new DockviewApi(this.layout),
|
||||
group
|
||||
);
|
||||
|
||||
panel.init({
|
||||
|
Loading…
x
Reference in New Issue
Block a user