mirror of
https://github.com/mathuo/dockview
synced 2025-02-22 16:15:45 +00:00
feat: persistance and rendering
This commit is contained in:
parent
37b0a062a4
commit
f26a1cd404
@ -1,8 +1,9 @@
|
|||||||
import { DefaultGroupPanelView } from '../../dockview/defaultGroupPanelView';
|
import { DefaultGroupPanelView } from '../../dockview/defaultGroupPanelView';
|
||||||
|
import { GroupPanel } from '../../groupview/groupviewPanel';
|
||||||
import { IContentRenderer, ITabRenderer } from '../../groupview/types';
|
import { IContentRenderer, ITabRenderer } from '../../groupview/types';
|
||||||
|
|
||||||
describe('defaultGroupPanelView', () => {
|
describe('defaultGroupPanelView', () => {
|
||||||
test('dispose cleanup', () => {
|
test('that dispose is called on content and tab renderers when present', () => {
|
||||||
const contentMock = jest.fn<IContentRenderer, []>(() => {
|
const contentMock = jest.fn<IContentRenderer, []>(() => {
|
||||||
const partial: Partial<IContentRenderer> = {
|
const partial: Partial<IContentRenderer> = {
|
||||||
element: document.createElement('div'),
|
element: document.createElement('div'),
|
||||||
@ -22,11 +23,109 @@ describe('defaultGroupPanelView', () => {
|
|||||||
const content = new contentMock();
|
const content = new contentMock();
|
||||||
const tab = new tabMock();
|
const tab = new tabMock();
|
||||||
|
|
||||||
const cut = new DefaultGroupPanelView({ content, tab });
|
const cut = new DefaultGroupPanelView({
|
||||||
|
content,
|
||||||
|
tab,
|
||||||
|
contentComponent: 'contentComponent',
|
||||||
|
});
|
||||||
|
|
||||||
cut.dispose();
|
cut.dispose();
|
||||||
|
|
||||||
expect(content.dispose).toHaveBeenCalled();
|
expect(content.dispose).toHaveBeenCalled();
|
||||||
expect(tab.dispose).toHaveBeenCalled();
|
expect(tab.dispose).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('that update is called on content and tab renderers when present', () => {
|
||||||
|
const contentMock = jest.fn<IContentRenderer, []>(() => {
|
||||||
|
const partial: Partial<IContentRenderer> = {
|
||||||
|
element: document.createElement('div'),
|
||||||
|
update: jest.fn(),
|
||||||
|
};
|
||||||
|
return partial as IContentRenderer;
|
||||||
|
});
|
||||||
|
|
||||||
|
const tabMock = jest.fn<ITabRenderer, []>(() => {
|
||||||
|
const partial: Partial<IContentRenderer> = {
|
||||||
|
element: document.createElement('div'),
|
||||||
|
update: jest.fn(),
|
||||||
|
};
|
||||||
|
return partial as IContentRenderer;
|
||||||
|
});
|
||||||
|
|
||||||
|
const content = new contentMock();
|
||||||
|
const tab = new tabMock();
|
||||||
|
|
||||||
|
const cut = new DefaultGroupPanelView({
|
||||||
|
content,
|
||||||
|
tab,
|
||||||
|
contentComponent: 'contentComponent',
|
||||||
|
});
|
||||||
|
|
||||||
|
cut.update({
|
||||||
|
params: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(content.update).toHaveBeenCalled();
|
||||||
|
expect(tab.update).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('test1', () => {
|
||||||
|
const contentMock = jest.fn<IContentRenderer, []>(() => {
|
||||||
|
const partial: Partial<IContentRenderer> = {
|
||||||
|
element: document.createElement('div'),
|
||||||
|
onGroupChange: jest.fn(),
|
||||||
|
onPanelVisibleChange: jest.fn(),
|
||||||
|
};
|
||||||
|
return partial as IContentRenderer;
|
||||||
|
});
|
||||||
|
|
||||||
|
const tabMock = jest.fn<ITabRenderer, []>(() => {
|
||||||
|
const partial: Partial<IContentRenderer> = {
|
||||||
|
element: document.createElement('div'),
|
||||||
|
onGroupChange: jest.fn(),
|
||||||
|
onPanelVisibleChange: jest.fn(),
|
||||||
|
};
|
||||||
|
return partial as IContentRenderer;
|
||||||
|
});
|
||||||
|
|
||||||
|
const content = new contentMock();
|
||||||
|
const tab = new tabMock();
|
||||||
|
|
||||||
|
let cut = new DefaultGroupPanelView({
|
||||||
|
content,
|
||||||
|
tab,
|
||||||
|
contentComponent: 'contentComponent',
|
||||||
|
});
|
||||||
|
|
||||||
|
const group1 = jest.fn() as any;
|
||||||
|
const group2 = jest.fn() as any;
|
||||||
|
cut.updateParentGroup(group1 as GroupPanel, false);
|
||||||
|
|
||||||
|
expect(content.onGroupChange).toHaveBeenNthCalledWith(1, group1);
|
||||||
|
expect(tab.onGroupChange).toHaveBeenNthCalledWith(1, group1);
|
||||||
|
expect(content.onPanelVisibleChange).toHaveBeenNthCalledWith(1, false);
|
||||||
|
expect(tab.onPanelVisibleChange).toHaveBeenNthCalledWith(1, false);
|
||||||
|
expect(content.onGroupChange).toHaveBeenCalledTimes(1);
|
||||||
|
expect(tab.onGroupChange).toHaveBeenCalledTimes(1);
|
||||||
|
expect(content.onPanelVisibleChange).toHaveBeenCalledTimes(1);
|
||||||
|
expect(tab.onPanelVisibleChange).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
cut.updateParentGroup(group1 as GroupPanel, true);
|
||||||
|
|
||||||
|
expect(content.onPanelVisibleChange).toHaveBeenNthCalledWith(2, true);
|
||||||
|
expect(tab.onPanelVisibleChange).toHaveBeenNthCalledWith(2, true);
|
||||||
|
expect(content.onGroupChange).toHaveBeenCalledTimes(1);
|
||||||
|
expect(tab.onGroupChange).toHaveBeenCalledTimes(1);
|
||||||
|
expect(content.onPanelVisibleChange).toHaveBeenCalledTimes(2);
|
||||||
|
expect(tab.onPanelVisibleChange).toHaveBeenCalledTimes(2);
|
||||||
|
|
||||||
|
cut.updateParentGroup(group2 as GroupPanel, true);
|
||||||
|
|
||||||
|
expect(content.onGroupChange).toHaveBeenNthCalledWith(2, group2);
|
||||||
|
expect(tab.onGroupChange).toHaveBeenNthCalledWith(2, group2);
|
||||||
|
expect(content.onGroupChange).toHaveBeenCalledTimes(2);
|
||||||
|
expect(tab.onGroupChange).toHaveBeenCalledTimes(2);
|
||||||
|
expect(content.onPanelVisibleChange).toHaveBeenCalledTimes(2);
|
||||||
|
expect(tab.onPanelVisibleChange).toHaveBeenCalledTimes(2);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -8,8 +8,6 @@ import { PanelUpdateEvent } from '../../../panel/types';
|
|||||||
import { GroupPanel } from '../../../groupview/groupviewPanel';
|
import { GroupPanel } from '../../../groupview/groupviewPanel';
|
||||||
import { createCloseButton } from '../../../svg';
|
import { createCloseButton } from '../../../svg';
|
||||||
|
|
||||||
export const DEFAULT_TAB_IDENTIFIER = '__default__tab__';
|
|
||||||
|
|
||||||
export class DefaultTab extends CompositeDisposable implements ITabRenderer {
|
export class DefaultTab extends CompositeDisposable implements ITabRenderer {
|
||||||
private _element: HTMLElement;
|
private _element: HTMLElement;
|
||||||
|
|
||||||
@ -26,10 +24,6 @@ export class DefaultTab extends CompositeDisposable implements ITabRenderer {
|
|||||||
return this._element;
|
return this._element;
|
||||||
}
|
}
|
||||||
|
|
||||||
get id() {
|
|
||||||
return DEFAULT_TAB_IDENTIFIER;
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
@ -69,18 +63,13 @@ export class DefaultTab extends CompositeDisposable implements ITabRenderer {
|
|||||||
this.render();
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
public toJSON() {
|
|
||||||
return { id: this.id };
|
|
||||||
}
|
|
||||||
|
|
||||||
focus() {
|
focus() {
|
||||||
//noop
|
//noop
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(params: GroupPanelPartInitParameters) {
|
public init(params: GroupPanelPartInitParameters) {
|
||||||
this.params = params;
|
this.params = params;
|
||||||
this._content.textContent =
|
this._content.textContent = params.title;
|
||||||
typeof params.title === 'string' ? params.title : this.id;
|
|
||||||
|
|
||||||
addDisposableListener(this.action, 'click', (ev) => {
|
addDisposableListener(this.action, 'click', (ev) => {
|
||||||
ev.preventDefault(); //
|
ev.preventDefault(); //
|
||||||
@ -107,10 +96,7 @@ export class DefaultTab extends CompositeDisposable implements ITabRenderer {
|
|||||||
|
|
||||||
private render() {
|
private render() {
|
||||||
if (this._content.textContent !== this.params.title) {
|
if (this._content.textContent !== this.params.title) {
|
||||||
this._content.textContent =
|
this._content.textContent = this.params.title;
|
||||||
typeof this.params.title === 'string'
|
|
||||||
? this.params.title
|
|
||||||
: this.id;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,21 +7,32 @@ import {
|
|||||||
} from '../groupview/types';
|
} from '../groupview/types';
|
||||||
import { GroupPanel } from '../groupview/groupviewPanel';
|
import { GroupPanel } from '../groupview/groupviewPanel';
|
||||||
import { IDisposable } from '../lifecycle';
|
import { IDisposable } from '../lifecycle';
|
||||||
|
import { createComponent } from '../panel/componentFactory';
|
||||||
|
import { IDockviewComponent } from './dockviewComponent';
|
||||||
|
|
||||||
|
export interface SerializedGroupPanelView {
|
||||||
|
tab?: { id: string };
|
||||||
|
content: { id: string };
|
||||||
|
}
|
||||||
|
|
||||||
export interface IGroupPanelView extends IDisposable {
|
export interface IGroupPanelView extends IDisposable {
|
||||||
|
readonly contentComponent: string;
|
||||||
|
readonly tabComponent?: string;
|
||||||
readonly content: IContentRenderer;
|
readonly content: IContentRenderer;
|
||||||
readonly tab?: ITabRenderer;
|
readonly tab?: ITabRenderer;
|
||||||
update(event: GroupPanelUpdateEvent): void;
|
update(event: GroupPanelUpdateEvent): void;
|
||||||
layout(width: number, height: number): void;
|
layout(width: number, height: number): void;
|
||||||
init(params: GroupPanelPartInitParameters): void;
|
init(params: GroupPanelPartInitParameters): void;
|
||||||
updateParentGroup(group: GroupPanel, isPanelVisible: boolean): void;
|
updateParentGroup(group: GroupPanel, isPanelVisible: boolean): void;
|
||||||
toJSON(): {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DefaultGroupPanelView implements IGroupPanelView {
|
export class DefaultGroupPanelView implements IGroupPanelView {
|
||||||
private readonly _content: IContentRenderer;
|
private readonly _content: IContentRenderer;
|
||||||
private readonly _tab: ITabRenderer;
|
private readonly _tab: ITabRenderer;
|
||||||
|
|
||||||
|
private _group: GroupPanel | null = null;
|
||||||
|
private _isPanelVisible: boolean | null = null;
|
||||||
|
|
||||||
get content(): IContentRenderer {
|
get content(): IContentRenderer {
|
||||||
return this._content;
|
return this._content;
|
||||||
}
|
}
|
||||||
@ -30,9 +41,15 @@ export class DefaultGroupPanelView implements IGroupPanelView {
|
|||||||
return this._tab;
|
return this._tab;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(renderers: { content: IContentRenderer; tab?: ITabRenderer }) {
|
constructor(
|
||||||
this._content = renderers.content;
|
private readonly accessor: IDockviewComponent,
|
||||||
this._tab = renderers.tab ?? new DefaultTab();
|
private readonly id: string,
|
||||||
|
readonly contentComponent: string,
|
||||||
|
readonly tabComponent?: string
|
||||||
|
) {
|
||||||
|
this._content = this.createContentComponent(this.id, contentComponent);
|
||||||
|
this._tab =
|
||||||
|
this.createTabComponent(this.id, tabComponent) ?? new DefaultTab();
|
||||||
}
|
}
|
||||||
|
|
||||||
init(params: GroupPanelPartInitParameters): void {
|
init(params: GroupPanelPartInitParameters): void {
|
||||||
@ -41,35 +58,65 @@ export class DefaultGroupPanelView implements IGroupPanelView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateParentGroup(group: GroupPanel, isPanelVisible: boolean): void {
|
updateParentGroup(group: GroupPanel, isPanelVisible: boolean): void {
|
||||||
this._content.updateParentGroup(group, isPanelVisible);
|
if (group !== this._group) {
|
||||||
this._tab?.updateParentGroup(group, isPanelVisible);
|
this._group = group;
|
||||||
|
if (this._content.onGroupChange) {
|
||||||
|
this._content.onGroupChange(group);
|
||||||
|
}
|
||||||
|
if (this._tab.onGroupChange) {
|
||||||
|
this._tab.onGroupChange(group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPanelVisible !== this._isPanelVisible) {
|
||||||
|
this._isPanelVisible = isPanelVisible;
|
||||||
|
if (this._content.onPanelVisibleChange) {
|
||||||
|
this._content.onPanelVisibleChange(isPanelVisible);
|
||||||
|
}
|
||||||
|
if (this._tab.onPanelVisibleChange) {
|
||||||
|
this._tab.onPanelVisibleChange(isPanelVisible);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
layout(width: number, height: number): void {
|
layout(width: number, height: number): void {
|
||||||
this.content.layout(width, height);
|
this.content.layout?.(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
update(event: GroupPanelUpdateEvent): void {
|
update(event: GroupPanelUpdateEvent): void {
|
||||||
this.content.update(event);
|
this.content.update?.(event);
|
||||||
this.tab.update(event);
|
this.tab.update?.(event);
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(): {} {
|
|
||||||
let tab =
|
|
||||||
this.tab instanceof DefaultTab ? undefined : this.tab.toJSON();
|
|
||||||
|
|
||||||
if (tab && Object.keys(tab).length === 0) {
|
|
||||||
tab = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
content: this.content.toJSON(),
|
|
||||||
tab,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose(): void {
|
dispose(): void {
|
||||||
this.content.dispose();
|
this.content.dispose?.();
|
||||||
this.tab.dispose();
|
this.tab.dispose?.();
|
||||||
|
}
|
||||||
|
|
||||||
|
private createContentComponent(
|
||||||
|
id: string,
|
||||||
|
componentName: string
|
||||||
|
): IContentRenderer {
|
||||||
|
return createComponent(
|
||||||
|
id,
|
||||||
|
componentName,
|
||||||
|
this.accessor.options.components || {},
|
||||||
|
this.accessor.options.frameworkComponents,
|
||||||
|
this.accessor.options.frameworkComponentFactory?.content
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private createTabComponent(
|
||||||
|
id: string,
|
||||||
|
componentName?: string
|
||||||
|
): ITabRenderer {
|
||||||
|
return createComponent(
|
||||||
|
id,
|
||||||
|
componentName,
|
||||||
|
this.accessor.options.tabComponents || {},
|
||||||
|
this.accessor.options.frameworkTabComponents,
|
||||||
|
this.accessor.options.frameworkComponentFactory?.tab,
|
||||||
|
() => new DefaultTab()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { GroupviewPanelState, ITabRenderer } from '../groupview/types';
|
import { GroupviewPanelState, ITabRenderer } from '../groupview/types';
|
||||||
import { GroupPanel } from '../groupview/groupviewPanel';
|
import { GroupPanel } from '../groupview/groupviewPanel';
|
||||||
import { DockviewPanel, IDockviewPanel } from './dockviewPanel';
|
import { DockviewPanel, IDockviewPanel } from './dockviewPanel';
|
||||||
import { DockviewComponent } from './dockviewComponent';
|
import { IDockviewComponent } from './dockviewComponent';
|
||||||
import { createComponent } from '../panel/componentFactory';
|
import { createComponent } from '../panel/componentFactory';
|
||||||
import { DefaultTab } from './components/tab/defaultTab';
|
import { DefaultTab } from './components/tab/defaultTab';
|
||||||
import { DefaultGroupPanelView } from './defaultGroupPanelView';
|
import { DefaultGroupPanelView } from './defaultGroupPanelView';
|
||||||
@ -12,7 +12,7 @@ export interface IPanelDeserializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class DefaultDockviewDeserialzier implements IPanelDeserializer {
|
export class DefaultDockviewDeserialzier implements IPanelDeserializer {
|
||||||
constructor(private readonly layout: DockviewComponent) {}
|
constructor(private readonly layout: IDockviewComponent) {}
|
||||||
|
|
||||||
public fromJSON(
|
public fromJSON(
|
||||||
panelData: GroupviewPanelState,
|
panelData: GroupviewPanelState,
|
||||||
@ -21,14 +21,21 @@ export class DefaultDockviewDeserialzier implements IPanelDeserializer {
|
|||||||
const panelId = panelData.id;
|
const panelId = panelData.id;
|
||||||
const params = panelData.params;
|
const params = panelData.params;
|
||||||
const title = panelData.title;
|
const title = panelData.title;
|
||||||
const viewData = panelData.view;
|
const viewData = panelData.view!;
|
||||||
|
|
||||||
let tab: ITabRenderer;
|
let tab: ITabRenderer;
|
||||||
|
|
||||||
if (viewData.tab?.id) {
|
const contentComponent = viewData
|
||||||
|
? viewData.content.id
|
||||||
|
: panelData.contentComponent || 'unknown';
|
||||||
|
const tabComponent = viewData
|
||||||
|
? viewData.tab?.id
|
||||||
|
: panelData.tabComponent;
|
||||||
|
|
||||||
|
if (tabComponent) {
|
||||||
tab = createComponent(
|
tab = createComponent(
|
||||||
viewData.tab.id,
|
panelId,
|
||||||
viewData.tab.id,
|
tabComponent,
|
||||||
this.layout.options.tabComponents,
|
this.layout.options.tabComponents,
|
||||||
this.layout.options.frameworkTabComponents,
|
this.layout.options.frameworkTabComponents,
|
||||||
this.layout.options.frameworkComponentFactory?.tab,
|
this.layout.options.frameworkComponentFactory?.tab,
|
||||||
@ -36,7 +43,7 @@ export class DefaultDockviewDeserialzier implements IPanelDeserializer {
|
|||||||
);
|
);
|
||||||
} else if (this.layout.options.defaultTabComponent) {
|
} else if (this.layout.options.defaultTabComponent) {
|
||||||
tab = createComponent(
|
tab = createComponent(
|
||||||
this.layout.options.defaultTabComponent,
|
panelId,
|
||||||
this.layout.options.defaultTabComponent,
|
this.layout.options.defaultTabComponent,
|
||||||
this.layout.options.tabComponents,
|
this.layout.options.tabComponents,
|
||||||
this.layout.options.frameworkTabComponents,
|
this.layout.options.frameworkTabComponents,
|
||||||
@ -47,16 +54,12 @@ export class DefaultDockviewDeserialzier implements IPanelDeserializer {
|
|||||||
tab = new DefaultTab();
|
tab = new DefaultTab();
|
||||||
}
|
}
|
||||||
|
|
||||||
const view = new DefaultGroupPanelView({
|
const view = new DefaultGroupPanelView(
|
||||||
content: createComponent(
|
this.layout,
|
||||||
viewData.content.id,
|
panelId,
|
||||||
viewData.content.id,
|
contentComponent,
|
||||||
this.layout.options.components,
|
tabComponent
|
||||||
this.layout.options.frameworkComponents,
|
);
|
||||||
this.layout.options.frameworkComponentFactory?.content
|
|
||||||
),
|
|
||||||
tab,
|
|
||||||
});
|
|
||||||
|
|
||||||
const panel = new DockviewPanel(
|
const panel = new DockviewPanel(
|
||||||
panelId,
|
panelId,
|
||||||
@ -67,7 +70,7 @@ export class DefaultDockviewDeserialzier implements IPanelDeserializer {
|
|||||||
|
|
||||||
panel.init({
|
panel.init({
|
||||||
view,
|
view,
|
||||||
title,
|
title: title || panelId,
|
||||||
params: params || {},
|
params: params || {},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -950,13 +950,16 @@ export class DockviewComponent
|
|||||||
options: AddPanelOptions,
|
options: AddPanelOptions,
|
||||||
group: GroupPanel
|
group: GroupPanel
|
||||||
): IDockviewPanel {
|
): IDockviewPanel {
|
||||||
const view = new DefaultGroupPanelView({
|
const contentComponent = options.component;
|
||||||
content: this.createContentComponent(options.id, options.component),
|
const tabComponent =
|
||||||
tab: this.createTabComponent(
|
options.tabComponent || this.options.defaultTabComponent;
|
||||||
options.id,
|
|
||||||
options.tabComponent || this.options.defaultTabComponent
|
const view = new DefaultGroupPanelView(
|
||||||
),
|
this,
|
||||||
});
|
options.id,
|
||||||
|
contentComponent,
|
||||||
|
tabComponent
|
||||||
|
);
|
||||||
|
|
||||||
const panel = new DockviewPanel(options.id, this, this._api, group);
|
const panel = new DockviewPanel(options.id, this, this._api, group);
|
||||||
panel.init({
|
panel.init({
|
||||||
@ -968,33 +971,6 @@ export class DockviewComponent
|
|||||||
return panel;
|
return panel;
|
||||||
}
|
}
|
||||||
|
|
||||||
private createContentComponent(
|
|
||||||
id: string,
|
|
||||||
componentName: string
|
|
||||||
): IContentRenderer {
|
|
||||||
return createComponent(
|
|
||||||
id,
|
|
||||||
componentName,
|
|
||||||
this.options.components || {},
|
|
||||||
this.options.frameworkComponents,
|
|
||||||
this.options.frameworkComponentFactory?.content
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private createTabComponent(
|
|
||||||
id: string,
|
|
||||||
componentName?: string
|
|
||||||
): ITabRenderer {
|
|
||||||
return createComponent(
|
|
||||||
id,
|
|
||||||
componentName,
|
|
||||||
this.options.tabComponents || {},
|
|
||||||
this.options.frameworkTabComponents,
|
|
||||||
this.options.frameworkComponentFactory?.tab,
|
|
||||||
() => new DefaultTab()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private createGroupAtLocation(location: number[] = [0]): GroupPanel {
|
private createGroupAtLocation(location: number[] = [0]): GroupPanel {
|
||||||
const group = this.createGroup();
|
const group = this.createGroup();
|
||||||
this.doAddGroup(group, location);
|
this.doAddGroup(group, location);
|
||||||
|
@ -12,7 +12,7 @@ import { GroupPanel } from '../groupview/groupviewPanel';
|
|||||||
import { CompositeDisposable, IDisposable } from '../lifecycle';
|
import { CompositeDisposable, IDisposable } from '../lifecycle';
|
||||||
import { IPanel, Parameters } from '../panel/types';
|
import { IPanel, Parameters } from '../panel/types';
|
||||||
import { IGroupPanelView } from './defaultGroupPanelView';
|
import { IGroupPanelView } from './defaultGroupPanelView';
|
||||||
import { DockviewComponent } from './dockviewComponent';
|
import { IDockviewComponent } from './dockviewComponent';
|
||||||
|
|
||||||
export interface IDockviewPanel extends IDisposable, IPanel {
|
export interface IDockviewPanel extends IDisposable, IPanel {
|
||||||
readonly view?: IGroupPanelView;
|
readonly view?: IGroupPanelView;
|
||||||
@ -56,7 +56,7 @@ export class DockviewPanel
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public readonly id: string,
|
public readonly id: string,
|
||||||
accessor: DockviewComponent,
|
accessor: IDockviewComponent,
|
||||||
private readonly containerApi: DockviewApi,
|
private readonly containerApi: DockviewApi,
|
||||||
group: GroupPanel
|
group: GroupPanel
|
||||||
) {
|
) {
|
||||||
@ -82,9 +82,7 @@ export class DockviewPanel
|
|||||||
this._params = params.params;
|
this._params = params.params;
|
||||||
this._view = params.view;
|
this._view = params.view;
|
||||||
|
|
||||||
if (typeof params.title === 'string') {
|
this.setTitle(params.title);
|
||||||
this.setTitle(params.title);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.view?.init({
|
this.view?.init({
|
||||||
...params,
|
...params,
|
||||||
@ -100,7 +98,8 @@ export class DockviewPanel
|
|||||||
public toJSON(): GroupviewPanelState {
|
public toJSON(): GroupviewPanelState {
|
||||||
return <GroupviewPanelState>{
|
return <GroupviewPanelState>{
|
||||||
id: this.id,
|
id: this.id,
|
||||||
view: this.view!.toJSON(),
|
contentComponent: this.view?.contentComponent,
|
||||||
|
tabComponent: this.view?.tabComponent,
|
||||||
params:
|
params:
|
||||||
Object.keys(this._params || {}).length > 0
|
Object.keys(this._params || {}).length > 0
|
||||||
? this._params
|
? this._params
|
||||||
@ -133,11 +132,9 @@ export class DockviewPanel
|
|||||||
...event.params.params,
|
...event.params.params,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (typeof params.title === 'string') {
|
if (params.title !== this.title) {
|
||||||
if (params.title !== this.title) {
|
this._title = params.title;
|
||||||
this._title = params.title;
|
this.api._onDidTitleChange.fire({ title: this.title });
|
||||||
this.api._onDidTitleChange.fire({ title: this.title });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.view?.update({
|
this.view?.update({
|
||||||
|
@ -235,14 +235,14 @@ export abstract class BaseGrid<T extends IGridPanelView>
|
|||||||
if (this._activeGroup) {
|
if (this._activeGroup) {
|
||||||
this._activeGroup.setActive(false);
|
this._activeGroup.setActive(false);
|
||||||
if (!skipFocus) {
|
if (!skipFocus) {
|
||||||
this._activeGroup.focus();
|
this._activeGroup.focus?.();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (group) {
|
if (group) {
|
||||||
group.setActive(true);
|
group.setActive(true);
|
||||||
if (!skipFocus) {
|
if (!skipFocus) {
|
||||||
group.focus();
|
group.focus?.();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,15 +40,15 @@ export abstract class BasePanelView<T extends PanelApiImpl>
|
|||||||
*/
|
*/
|
||||||
protected abstract getComponent(): IFrameworkPart;
|
protected abstract getComponent(): IFrameworkPart;
|
||||||
|
|
||||||
get element() {
|
get element(): HTMLElement {
|
||||||
return this._element;
|
return this._element;
|
||||||
}
|
}
|
||||||
|
|
||||||
get width() {
|
get width(): number {
|
||||||
return this._width;
|
return this._width;
|
||||||
}
|
}
|
||||||
|
|
||||||
get height() {
|
get height(): number {
|
||||||
return this._height;
|
return this._height;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,11 +83,11 @@ export abstract class BasePanelView<T extends PanelApiImpl>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
focus() {
|
focus(): void {
|
||||||
this.api._onFocusEvent.fire();
|
this.api._onFocusEvent.fire();
|
||||||
}
|
}
|
||||||
|
|
||||||
layout(width: number, height: number) {
|
layout(width: number, height: number): void {
|
||||||
this._width = width;
|
this._width = width;
|
||||||
this._height = height;
|
this._height = height;
|
||||||
this.api._onDidDimensionChange.fire({ width, height });
|
this.api._onDidDimensionChange.fire({ width, height });
|
||||||
@ -104,7 +104,7 @@ export abstract class BasePanelView<T extends PanelApiImpl>
|
|||||||
this.part = this.getComponent();
|
this.part = this.getComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
update(event: PanelUpdateEvent) {
|
update(event: PanelUpdateEvent): void {
|
||||||
this._params = {
|
this._params = {
|
||||||
...this._params,
|
...this._params,
|
||||||
params: {
|
params: {
|
||||||
@ -125,7 +125,7 @@ export abstract class BasePanelView<T extends PanelApiImpl>
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose() {
|
dispose(): void {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
|
|
||||||
this.api.dispose();
|
this.api.dispose();
|
||||||
|
@ -77,7 +77,7 @@ export interface IHeader {
|
|||||||
height: number | undefined;
|
height: number | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IGroupview extends IDisposable, IGridPanelView {
|
export interface IGroupview extends IGridPanelView {
|
||||||
readonly isActive: boolean;
|
readonly isActive: boolean;
|
||||||
readonly size: number;
|
readonly size: number;
|
||||||
readonly panels: IDockviewPanel[];
|
readonly panels: IDockviewPanel[];
|
||||||
@ -427,7 +427,7 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
|||||||
}
|
}
|
||||||
|
|
||||||
focus(): void {
|
focus(): void {
|
||||||
this._activePanel?.focus();
|
this._activePanel?.focus?.();
|
||||||
}
|
}
|
||||||
|
|
||||||
public openPanel(
|
public openPanel(
|
||||||
@ -525,7 +525,7 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
|||||||
): void {
|
): void {
|
||||||
if (!force && this.isActive === isGroupActive) {
|
if (!force && this.isActive === isGroupActive) {
|
||||||
if (!skipFocus) {
|
if (!skipFocus) {
|
||||||
this._activePanel?.focus();
|
this._activePanel?.focus?.();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -545,7 +545,7 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
|||||||
|
|
||||||
if (isGroupActive) {
|
if (isGroupActive) {
|
||||||
if (!skipFocus) {
|
if (!skipFocus) {
|
||||||
this._activePanel?.focus();
|
this._activePanel?.focus?.();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,9 +74,8 @@ export class ContentContainer
|
|||||||
const disposable = new CompositeDisposable();
|
const disposable = new CompositeDisposable();
|
||||||
|
|
||||||
if (this.panel.view) {
|
if (this.panel.view) {
|
||||||
const _onDidFocus: Event<void> =
|
const _onDidFocus = this.panel.view.content.onDidFocus;
|
||||||
this.panel.view.content.onDidFocus!;
|
const _onDidBlur = this.panel.view.content.onDidBlur;
|
||||||
const _onDidBlur: Event<void> = this.panel.view.content.onDidBlur!;
|
|
||||||
|
|
||||||
const { onDidFocus, onDidBlur } = trackFocus(this._element);
|
const { onDidFocus, onDidBlur } = trackFocus(this._element);
|
||||||
|
|
||||||
|
@ -9,7 +9,11 @@ import {
|
|||||||
import { DockviewApi } from '../api/component.api';
|
import { DockviewApi } from '../api/component.api';
|
||||||
import { GroupPanel } from './groupviewPanel';
|
import { GroupPanel } from './groupviewPanel';
|
||||||
import { Event } from '../events';
|
import { Event } from '../events';
|
||||||
import { IGroupPanelView } from '../dockview/defaultGroupPanelView';
|
import {
|
||||||
|
IGroupPanelView,
|
||||||
|
SerializedGroupPanelView,
|
||||||
|
} from '../dockview/defaultGroupPanelView';
|
||||||
|
import { Optional } from '../types';
|
||||||
|
|
||||||
export interface IRenderable {
|
export interface IRenderable {
|
||||||
id: string;
|
id: string;
|
||||||
@ -19,7 +23,7 @@ export interface IRenderable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface HeaderPartInitParameters {
|
export interface HeaderPartInitParameters {
|
||||||
title?: string;
|
title: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GroupPanelPartInitParameters
|
export interface GroupPanelPartInitParameters
|
||||||
@ -40,20 +44,28 @@ export interface IWatermarkRenderer extends IPanel {
|
|||||||
updateParentGroup(group: GroupPanel, visible: boolean): void;
|
updateParentGroup(group: GroupPanel, visible: boolean): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ITabRenderer extends IPanel {
|
export interface ITabRenderer
|
||||||
|
extends Optional<
|
||||||
|
Omit<IPanel, 'id'>,
|
||||||
|
'dispose' | 'update' | 'layout' | 'toJSON'
|
||||||
|
> {
|
||||||
readonly element: HTMLElement;
|
readonly element: HTMLElement;
|
||||||
init(parameters: GroupPanelPartInitParameters): void;
|
init(parameters: GroupPanelPartInitParameters): void;
|
||||||
updateParentGroup(group: GroupPanel, isPanelVisible: boolean): void;
|
onGroupChange?(group: GroupPanel): void;
|
||||||
|
onPanelVisibleChange?(isPanelVisible: boolean): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IContentRenderer extends IPanel {
|
export interface IContentRenderer
|
||||||
|
extends Optional<
|
||||||
|
Omit<IPanel, 'id'>,
|
||||||
|
'dispose' | 'update' | 'layout' | 'toJSON'
|
||||||
|
> {
|
||||||
readonly element: HTMLElement;
|
readonly element: HTMLElement;
|
||||||
readonly actions?: HTMLElement;
|
|
||||||
readonly onDidFocus?: Event<void>;
|
readonly onDidFocus?: Event<void>;
|
||||||
readonly onDidBlur?: Event<void>;
|
readonly onDidBlur?: Event<void>;
|
||||||
updateParentGroup(group: GroupPanel, isPanelVisible: boolean): void;
|
|
||||||
init(parameters: GroupPanelContentPartInitParameters): void;
|
init(parameters: GroupPanelContentPartInitParameters): void;
|
||||||
layout(width: number, height: number): void;
|
onGroupChange?(group: GroupPanel): void;
|
||||||
|
onPanelVisibleChange?(isPanelVisible: boolean): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
// watermark component
|
// watermark component
|
||||||
@ -88,7 +100,9 @@ export type GroupPanelUpdateEvent = PanelUpdateEvent<{
|
|||||||
|
|
||||||
export interface GroupviewPanelState {
|
export interface GroupviewPanelState {
|
||||||
id: string;
|
id: string;
|
||||||
view?: any;
|
contentComponent?: string;
|
||||||
|
tabComponent?: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
params?: { [key: string]: any };
|
params?: { [key: string]: any };
|
||||||
|
view?: SerializedGroupPanelView; // depreciated
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ export interface IPanel extends IDisposable {
|
|||||||
layout(width: number, height: number): void;
|
layout(width: number, height: number): void;
|
||||||
update(event: PanelUpdateEvent<Parameters>): void;
|
update(event: PanelUpdateEvent<Parameters>): void;
|
||||||
toJSON(): object;
|
toJSON(): object;
|
||||||
focus(): void;
|
focus?(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IFrameworkPart extends IDisposable {
|
export interface IFrameworkPart extends IDisposable {
|
||||||
|
@ -11,3 +11,5 @@ export type FunctionOrValue<T> = (() => T) | T;
|
|||||||
export function isBooleanValue(value: any): value is boolean {
|
export function isBooleanValue(value: any): value is boolean {
|
||||||
return typeof value === 'boolean';
|
return typeof value === 'boolean';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>;
|
||||||
|
@ -11,7 +11,6 @@ import {
|
|||||||
ITabRenderer,
|
ITabRenderer,
|
||||||
watchElementResize,
|
watchElementResize,
|
||||||
GroupPanel,
|
GroupPanel,
|
||||||
DEFAULT_TAB_IDENTIFIER,
|
|
||||||
DefaultDockviewDeserialzier,
|
DefaultDockviewDeserialzier,
|
||||||
} from 'dockview-core';
|
} from 'dockview-core';
|
||||||
import { ReactPanelContentPart } from './reactContentPart';
|
import { ReactPanelContentPart } from './reactContentPart';
|
||||||
@ -72,6 +71,8 @@ export interface IDockviewReactProps {
|
|||||||
singleTabMode?: 'fullwidth' | 'default';
|
singleTabMode?: 'fullwidth' | 'default';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DEFAULT_REACT_TAB = 'props.defaultTabComponent';
|
||||||
|
|
||||||
export const DockviewReact = React.forwardRef(
|
export const DockviewReact = React.forwardRef(
|
||||||
(props: IDockviewReactProps, ref: React.ForwardedRef<HTMLDivElement>) => {
|
(props: IDockviewReactProps, ref: React.ForwardedRef<HTMLDivElement>) => {
|
||||||
const domRef = React.useRef<HTMLDivElement>(null);
|
const domRef = React.useRef<HTMLDivElement>(null);
|
||||||
@ -144,16 +145,22 @@ export const DockviewReact = React.forwardRef(
|
|||||||
|
|
||||||
const element = document.createElement('div');
|
const element = document.createElement('div');
|
||||||
|
|
||||||
|
const frameworkTabComponents = props.tabComponents || {};
|
||||||
|
|
||||||
|
if (props.defaultTabComponent) {
|
||||||
|
frameworkTabComponents[DEFAULT_REACT_TAB] =
|
||||||
|
props.defaultTabComponent;
|
||||||
|
}
|
||||||
|
|
||||||
const dockview = new DockviewComponent(element, {
|
const dockview = new DockviewComponent(element, {
|
||||||
frameworkComponentFactory: factory,
|
frameworkComponentFactory: factory,
|
||||||
frameworkComponents: props.components,
|
frameworkComponents: props.components,
|
||||||
frameworkTabComponents: {
|
frameworkTabComponents,
|
||||||
...(props.tabComponents || {}),
|
|
||||||
[DEFAULT_TAB_IDENTIFIER]: props.defaultTabComponent,
|
|
||||||
},
|
|
||||||
tabHeight: props.tabHeight,
|
tabHeight: props.tabHeight,
|
||||||
watermarkFrameworkComponent: props.watermarkComponent,
|
watermarkFrameworkComponent: props.watermarkComponent,
|
||||||
defaultTabComponent: DEFAULT_TAB_IDENTIFIER,
|
defaultTabComponent: props.defaultTabComponent
|
||||||
|
? DEFAULT_REACT_TAB
|
||||||
|
: undefined,
|
||||||
styles: props.hideBorders
|
styles: props.hideBorders
|
||||||
? { separatorBorder: 'transparent' }
|
? { separatorBorder: 'transparent' }
|
||||||
: undefined,
|
: undefined,
|
||||||
@ -241,12 +248,19 @@ export const DockviewReact = React.forwardRef(
|
|||||||
if (!dockviewRef.current) {
|
if (!dockviewRef.current) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const frameworkTabComponents = props.tabComponents || {};
|
||||||
|
|
||||||
|
if (props.defaultTabComponent) {
|
||||||
|
frameworkTabComponents[DEFAULT_REACT_TAB] =
|
||||||
|
props.defaultTabComponent;
|
||||||
|
}
|
||||||
|
|
||||||
dockviewRef.current.updateOptions({
|
dockviewRef.current.updateOptions({
|
||||||
defaultTabComponent: DEFAULT_TAB_IDENTIFIER,
|
defaultTabComponent: props.defaultTabComponent
|
||||||
frameworkTabComponents: {
|
? DEFAULT_REACT_TAB
|
||||||
...(props.tabComponents || {}),
|
: undefined,
|
||||||
[DEFAULT_TAB_IDENTIFIER]: props.defaultTabComponent,
|
frameworkTabComponents,
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}, [props.defaultTabComponent]);
|
}, [props.defaultTabComponent]);
|
||||||
|
|
||||||
|
@ -52,12 +52,6 @@ export class ReactPanelContentPart implements IContentRenderer {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public toJSON() {
|
|
||||||
return {
|
|
||||||
id: this.id,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public update(event: PanelUpdateEvent) {
|
public update(event: PanelUpdateEvent) {
|
||||||
this.part?.update(event.params);
|
this.part?.update(event.params);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ import * as React from 'react';
|
|||||||
import { ReactPart, ReactPortalStore } from '../react';
|
import { ReactPart, ReactPortalStore } from '../react';
|
||||||
import { IGroupPanelBaseProps } from './dockview';
|
import { IGroupPanelBaseProps } from './dockview';
|
||||||
import {
|
import {
|
||||||
DEFAULT_TAB_IDENTIFIER,
|
|
||||||
PanelUpdateEvent,
|
PanelUpdateEvent,
|
||||||
GroupPanel,
|
GroupPanel,
|
||||||
ITabRenderer,
|
ITabRenderer,
|
||||||
@ -47,16 +46,6 @@ export class ReactPanelHeaderPart implements ITabRenderer {
|
|||||||
this.part?.update(event.params);
|
this.part?.update(event.params);
|
||||||
}
|
}
|
||||||
|
|
||||||
public toJSON() {
|
|
||||||
if (this.id === DEFAULT_TAB_IDENTIFIER) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: this.id,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public layout(_width: number, _height: number) {
|
public layout(_width: number, _height: number) {
|
||||||
// noop - retrieval from api
|
// noop - retrieval from api
|
||||||
}
|
}
|
||||||
|
@ -32,10 +32,6 @@ export class WebviewContentRenderer implements IContentRenderer {
|
|||||||
this.parameters = parameters;
|
this.parameters = parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
public toJSON() {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
public update(params: PanelUpdateEvent) {
|
public update(params: PanelUpdateEvent) {
|
||||||
if (this.parameters) {
|
if (this.parameters) {
|
||||||
this.parameters.params = params.params;
|
this.parameters.params = params.params;
|
||||||
|
Loading…
Reference in New Issue
Block a user