mirror of
https://github.com/mathuo/dockview
synced 2025-07-31 14:26:03 +00:00
feat: group controls renderer
This commit is contained in:
parent
a92fb3f554
commit
a7f69fc617
@ -1,9 +1,5 @@
|
|||||||
import { DefaultGroupPanelView } from '../../dockview/defaultGroupPanelView';
|
import { DefaultGroupPanelView } from '../../dockview/defaultGroupPanelView';
|
||||||
import {
|
import { IContentRenderer, ITabRenderer } from '../../groupview/types';
|
||||||
IActionsRenderer,
|
|
||||||
IContentRenderer,
|
|
||||||
ITabRenderer,
|
|
||||||
} from '../../groupview/types';
|
|
||||||
|
|
||||||
describe('defaultGroupPanelView', () => {
|
describe('defaultGroupPanelView', () => {
|
||||||
test('dispose cleanup', () => {
|
test('dispose cleanup', () => {
|
||||||
@ -23,24 +19,14 @@ describe('defaultGroupPanelView', () => {
|
|||||||
return partial as IContentRenderer;
|
return partial as IContentRenderer;
|
||||||
});
|
});
|
||||||
|
|
||||||
const actionsMock = jest.fn<IActionsRenderer, []>(() => {
|
|
||||||
const partial: Partial<IContentRenderer> = {
|
|
||||||
element: document.createElement('div'),
|
|
||||||
dispose: jest.fn(),
|
|
||||||
};
|
|
||||||
return partial as IContentRenderer;
|
|
||||||
});
|
|
||||||
|
|
||||||
const content = new contentMock();
|
const content = new contentMock();
|
||||||
const tab = new tabMock();
|
const tab = new tabMock();
|
||||||
const actions = new actionsMock();
|
|
||||||
|
|
||||||
const cut = new DefaultGroupPanelView({ content, tab, actions });
|
const cut = new DefaultGroupPanelView({ content, tab });
|
||||||
|
|
||||||
cut.dispose();
|
cut.dispose();
|
||||||
|
|
||||||
expect(content.dispose).toHaveBeenCalled();
|
expect(content.dispose).toHaveBeenCalled();
|
||||||
expect(tab.dispose).toHaveBeenCalled();
|
expect(tab.dispose).toHaveBeenCalled();
|
||||||
expect(actions.dispose).toHaveBeenCalled();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -152,7 +152,7 @@ class TestGroupPanel implements IDockviewPanel {
|
|||||||
public readonly title: string,
|
public readonly title: string,
|
||||||
accessor: DockviewComponent
|
accessor: DockviewComponent
|
||||||
) {
|
) {
|
||||||
this.api = new DockviewPanelApiImpl(this, this._group);
|
this.api = new DockviewPanelApiImpl(this, this._group!);
|
||||||
this._group = new GroupPanel(accessor, id, {});
|
this._group = new GroupPanel(accessor, id, {});
|
||||||
this.view = new TestGroupPanelView(
|
this.view = new TestGroupPanelView(
|
||||||
new PanelContentPartTest(id, 'component')
|
new PanelContentPartTest(id, 'component')
|
||||||
@ -162,9 +162,8 @@ class TestGroupPanel implements IDockviewPanel {
|
|||||||
get params(): Record<string, any> {
|
get params(): Record<string, any> {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
get group(): GroupPanel {
|
||||||
get group(): GroupPanel | undefined {
|
return this._group!;
|
||||||
return this._group;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateParentGroup(group: GroupPanel, isGroupActive: boolean): void {
|
updateParentGroup(group: GroupPanel, isGroupActive: boolean): void {
|
||||||
|
@ -11,11 +11,7 @@ import {
|
|||||||
IWatermarkRenderer,
|
IWatermarkRenderer,
|
||||||
} from '../../groupview/types';
|
} from '../../groupview/types';
|
||||||
import { PanelUpdateEvent } from '../../panel/types';
|
import { PanelUpdateEvent } from '../../panel/types';
|
||||||
import {
|
import { GroupOptions, Groupview } from '../../groupview/groupview';
|
||||||
GroupChangeKind2,
|
|
||||||
GroupOptions,
|
|
||||||
Groupview,
|
|
||||||
} from '../../groupview/groupview';
|
|
||||||
import { DockviewPanelApi } from '../../api/groupPanelApi';
|
import { DockviewPanelApi } from '../../api/groupPanelApi';
|
||||||
import {
|
import {
|
||||||
DefaultGroupPanelView,
|
DefaultGroupPanelView,
|
||||||
@ -24,6 +20,13 @@ import {
|
|||||||
import { GroupPanel } from '../../groupview/groupviewPanel';
|
import { GroupPanel } from '../../groupview/groupviewPanel';
|
||||||
import { fireEvent } from '@testing-library/dom';
|
import { fireEvent } from '@testing-library/dom';
|
||||||
import { LocalSelectionTransfer, PanelTransfer } from '../../dnd/dataTransfer';
|
import { LocalSelectionTransfer, PanelTransfer } from '../../dnd/dataTransfer';
|
||||||
|
import { CompositeDisposable } from '../../lifecycle';
|
||||||
|
|
||||||
|
enum GroupChangeKind2 {
|
||||||
|
ADD_PANEL,
|
||||||
|
REMOVE_PANEL,
|
||||||
|
PANEL_ACTIVE,
|
||||||
|
}
|
||||||
|
|
||||||
class Watermark implements IWatermarkRenderer {
|
class Watermark implements IWatermarkRenderer {
|
||||||
public readonly element = document.createElement('div');
|
public readonly element = document.createElement('div');
|
||||||
@ -193,7 +196,7 @@ export class TestPanel implements IDockviewPanel {
|
|||||||
toJSON(): GroupviewPanelState {
|
toJSON(): GroupviewPanelState {
|
||||||
return {
|
return {
|
||||||
id: this.id,
|
id: this.id,
|
||||||
view: this._view.toJSON(),
|
view: this._view?.toJSON(),
|
||||||
title: this._params?.title,
|
title: this._params?.title,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -269,10 +272,29 @@ describe('groupview', () => {
|
|||||||
|
|
||||||
const events: Array<{
|
const events: Array<{
|
||||||
kind: GroupChangeKind2;
|
kind: GroupChangeKind2;
|
||||||
|
panel?: IDockviewPanel;
|
||||||
}> = [];
|
}> = [];
|
||||||
const disposable = groupview2.model.onDidGroupChange((e) => {
|
|
||||||
events.push(e);
|
const disposable = new CompositeDisposable(
|
||||||
|
groupview2.model.onDidAddPanel((e) => {
|
||||||
|
events.push({
|
||||||
|
kind: GroupChangeKind2.ADD_PANEL,
|
||||||
|
panel: e.panel,
|
||||||
});
|
});
|
||||||
|
}),
|
||||||
|
groupview2.model.onDidRemovePanel((e) => {
|
||||||
|
events.push({
|
||||||
|
kind: GroupChangeKind2.REMOVE_PANEL,
|
||||||
|
panel: e.panel,
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
groupview2.model.onDidActivePanelChange((e) => {
|
||||||
|
events.push({
|
||||||
|
kind: GroupChangeKind2.PANEL_ACTIVE,
|
||||||
|
panel: e.panel,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
groupview2.initialize();
|
groupview2.initialize();
|
||||||
|
|
||||||
@ -301,10 +323,29 @@ describe('groupview', () => {
|
|||||||
test('panel events flow', () => {
|
test('panel events flow', () => {
|
||||||
let events: Array<{
|
let events: Array<{
|
||||||
kind: GroupChangeKind2;
|
kind: GroupChangeKind2;
|
||||||
|
panel?: IDockviewPanel;
|
||||||
}> = [];
|
}> = [];
|
||||||
const disposable = groupview.model.onDidGroupChange((e) => {
|
|
||||||
events.push(e);
|
const disposable = new CompositeDisposable(
|
||||||
|
groupview.model.onDidAddPanel((e) => {
|
||||||
|
events.push({
|
||||||
|
kind: GroupChangeKind2.ADD_PANEL,
|
||||||
|
panel: e.panel,
|
||||||
});
|
});
|
||||||
|
}),
|
||||||
|
groupview.model.onDidRemovePanel((e) => {
|
||||||
|
events.push({
|
||||||
|
kind: GroupChangeKind2.REMOVE_PANEL,
|
||||||
|
panel: e.panel,
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
groupview.model.onDidActivePanelChange((e) => {
|
||||||
|
events.push({
|
||||||
|
kind: GroupChangeKind2.PANEL_ACTIVE,
|
||||||
|
panel: e.panel,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
const panel1 = new TestPanel('panel1', jest.fn() as any);
|
const panel1 = new TestPanel('panel1', jest.fn() as any);
|
||||||
const panel2 = new TestPanel('panel2', jest.fn() as any);
|
const panel2 = new TestPanel('panel2', jest.fn() as any);
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { DefaultTab } from './components/tab/defaultTab';
|
import { DefaultTab } from './components/tab/defaultTab';
|
||||||
import {
|
import {
|
||||||
GroupPanelPartInitParameters,
|
GroupPanelPartInitParameters,
|
||||||
IActionsRenderer,
|
|
||||||
IContentRenderer,
|
IContentRenderer,
|
||||||
ITabRenderer,
|
ITabRenderer,
|
||||||
} from '../groupview/types';
|
} from '../groupview/types';
|
||||||
@ -12,7 +11,6 @@ import { GroupPanelUpdateEvent } from '../groupview/groupPanel';
|
|||||||
export interface IGroupPanelView extends IDisposable {
|
export interface IGroupPanelView extends IDisposable {
|
||||||
readonly content: IContentRenderer;
|
readonly content: IContentRenderer;
|
||||||
readonly tab?: ITabRenderer;
|
readonly tab?: ITabRenderer;
|
||||||
readonly actions?: IActionsRenderer;
|
|
||||||
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;
|
||||||
@ -23,37 +21,18 @@ export interface IGroupPanelView extends IDisposable {
|
|||||||
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 readonly _actions: IActionsRenderer | undefined;
|
|
||||||
|
|
||||||
get content() {
|
get content(): IContentRenderer {
|
||||||
return this._content;
|
return this._content;
|
||||||
}
|
}
|
||||||
|
|
||||||
get tab() {
|
get tab(): ITabRenderer {
|
||||||
return this._tab;
|
return this._tab;
|
||||||
}
|
}
|
||||||
|
|
||||||
get actions() {
|
constructor(renderers: { content: IContentRenderer; tab?: ITabRenderer }) {
|
||||||
return this._actions;
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(renderers: {
|
|
||||||
content: IContentRenderer;
|
|
||||||
tab?: ITabRenderer;
|
|
||||||
actions?: IActionsRenderer;
|
|
||||||
}) {
|
|
||||||
this._content = renderers.content;
|
this._content = renderers.content;
|
||||||
this._tab = renderers.tab ?? new DefaultTab();
|
this._tab = renderers.tab ?? new DefaultTab();
|
||||||
this._actions =
|
|
||||||
renderers.actions ||
|
|
||||||
(this.content.actions
|
|
||||||
? {
|
|
||||||
element: this.content.actions,
|
|
||||||
dispose: () => {
|
|
||||||
//
|
|
||||||
},
|
|
||||||
}
|
|
||||||
: undefined);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init(params: GroupPanelPartInitParameters): void {
|
init(params: GroupPanelPartInitParameters): void {
|
||||||
@ -85,6 +64,5 @@ export class DefaultGroupPanelView implements IGroupPanelView {
|
|||||||
dispose(): void {
|
dispose(): void {
|
||||||
this.content.dispose();
|
this.content.dispose();
|
||||||
this.tab.dispose();
|
this.tab.dispose();
|
||||||
this.actions?.dispose();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,6 @@ import { LayoutMouseEvent, MouseEventKind } from '../groupview/tab';
|
|||||||
import { Orientation } from '../splitview/core/splitview';
|
import { Orientation } from '../splitview/core/splitview';
|
||||||
import { DefaultTab } from './components/tab/defaultTab';
|
import { DefaultTab } from './components/tab/defaultTab';
|
||||||
import {
|
import {
|
||||||
GroupChangeKind2,
|
|
||||||
GroupOptions,
|
GroupOptions,
|
||||||
GroupPanelViewState,
|
GroupPanelViewState,
|
||||||
GroupviewDropEvent,
|
GroupviewDropEvent,
|
||||||
@ -73,6 +72,7 @@ export type DockviewComponentUpdateOptions = Pick<
|
|||||||
| 'showDndOverlay'
|
| 'showDndOverlay'
|
||||||
| 'watermarkFrameworkComponent'
|
| 'watermarkFrameworkComponent'
|
||||||
| 'defaultTabComponent'
|
| 'defaultTabComponent'
|
||||||
|
| 'createGroupControlElement'
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export interface DockviewDropEvent extends GroupviewDropEvent {
|
export interface DockviewDropEvent extends GroupviewDropEvent {
|
||||||
@ -716,22 +716,14 @@ export class DockviewComponent
|
|||||||
view.model.onDidDrop((event) => {
|
view.model.onDidDrop((event) => {
|
||||||
this._onDidDrop.fire({ ...event, api: this._api, group: view });
|
this._onDidDrop.fire({ ...event, api: this._api, group: view });
|
||||||
}),
|
}),
|
||||||
view.model.onDidGroupChange((event) => {
|
view.model.onDidAddPanel((event) => {
|
||||||
switch (event.kind) {
|
|
||||||
case GroupChangeKind2.ADD_PANEL:
|
|
||||||
if (event.panel) {
|
|
||||||
this._onDidAddPanel.fire(event.panel);
|
this._onDidAddPanel.fire(event.panel);
|
||||||
}
|
}),
|
||||||
break;
|
view.model.onDidRemovePanel((event) => {
|
||||||
case GroupChangeKind2.REMOVE_PANEL:
|
|
||||||
if (event.panel) {
|
|
||||||
this._onDidRemovePanel.fire(event.panel);
|
this._onDidRemovePanel.fire(event.panel);
|
||||||
}
|
}),
|
||||||
break;
|
view.model.onDidActivePanelChange((event) => {
|
||||||
case GroupChangeKind2.PANEL_ACTIVE:
|
|
||||||
this._onDidActivePanelChange.fire(event.panel);
|
this._onDidActivePanelChange.fire(event.panel);
|
||||||
break;
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ import { ISplitviewStyles, Orientation } from '../splitview/core/splitview';
|
|||||||
import { FrameworkFactory } from '../types';
|
import { FrameworkFactory } from '../types';
|
||||||
import { DockviewDropTargets } from '../groupview/dnd';
|
import { DockviewDropTargets } from '../groupview/dnd';
|
||||||
import { PanelTransfer } from '../dnd/dataTransfer';
|
import { PanelTransfer } from '../dnd/dataTransfer';
|
||||||
|
import { IGroupControlRenderer } from '../react/dockview/groupControlsRenderer';
|
||||||
|
|
||||||
export interface GroupPanelFrameworkComponentFactory {
|
export interface GroupPanelFrameworkComponentFactory {
|
||||||
content: FrameworkFactory<IContentRenderer>;
|
content: FrameworkFactory<IContentRenderer>;
|
||||||
@ -66,6 +67,7 @@ export interface DockviewComponentOptions extends DockviewRenderFunctions {
|
|||||||
styles?: ISplitviewStyles;
|
styles?: ISplitviewStyles;
|
||||||
defaultTabComponent?: string;
|
defaultTabComponent?: string;
|
||||||
showDndOverlay?: (event: DockviewDndOverlayEvent) => boolean;
|
showDndOverlay?: (event: DockviewDndOverlayEvent) => boolean;
|
||||||
|
createGroupControlElement?: (group: GroupPanel) => IGroupControlRenderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PanelOptions {
|
export interface PanelOptions {
|
||||||
|
@ -14,12 +14,7 @@ import { ITabsContainer, TabsContainer } from './titlebar/tabsContainer';
|
|||||||
import { IWatermarkRenderer } from './types';
|
import { IWatermarkRenderer } from './types';
|
||||||
import { GroupPanel } from './groupviewPanel';
|
import { GroupPanel } from './groupviewPanel';
|
||||||
import { DockviewDropTargets } from './dnd';
|
import { DockviewDropTargets } from './dnd';
|
||||||
|
import { IGroupControlRenderer } from '../react/dockview/groupControlsRenderer';
|
||||||
export enum GroupChangeKind2 {
|
|
||||||
ADD_PANEL = 'ADD_PANEL',
|
|
||||||
REMOVE_PANEL = 'REMOVE_PANEL',
|
|
||||||
PANEL_ACTIVE = 'PANEL_ACTIVE',
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DndService {
|
export interface DndService {
|
||||||
canDisplayOverlay(
|
canDisplayOverlay(
|
||||||
@ -67,15 +62,14 @@ export interface GroupPanelViewState extends CoreGroupOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface GroupviewChangeEvent {
|
export interface GroupviewChangeEvent {
|
||||||
readonly kind: GroupChangeKind2;
|
readonly panel: IDockviewPanel;
|
||||||
readonly panel?: IDockviewPanel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GroupviewDropEvent {
|
export interface GroupviewDropEvent {
|
||||||
nativeEvent: DragEvent;
|
readonly nativeEvent: DragEvent;
|
||||||
position: Position;
|
readonly position: Position;
|
||||||
|
readonly index?: number;
|
||||||
getData(): PanelTransfer | undefined;
|
getData(): PanelTransfer | undefined;
|
||||||
index?: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IHeader {
|
export interface IHeader {
|
||||||
@ -91,7 +85,9 @@ export interface IGroupview extends IDisposable, IGridPanelView {
|
|||||||
readonly header: IHeader;
|
readonly header: IHeader;
|
||||||
readonly isContentFocused: boolean;
|
readonly isContentFocused: boolean;
|
||||||
readonly onDidDrop: Event<GroupviewDropEvent>;
|
readonly onDidDrop: Event<GroupviewDropEvent>;
|
||||||
readonly onDidGroupChange: Event<GroupviewChangeEvent>;
|
readonly onDidAddPanel: Event<GroupviewChangeEvent>;
|
||||||
|
readonly onDidRemovePanel: Event<GroupviewChangeEvent>;
|
||||||
|
readonly onDidActivePanelChange: Event<GroupviewChangeEvent>;
|
||||||
readonly onMove: Event<GroupMoveEvent>;
|
readonly onMove: Event<GroupMoveEvent>;
|
||||||
locked: boolean;
|
locked: boolean;
|
||||||
// state
|
// state
|
||||||
@ -121,10 +117,11 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
|||||||
private readonly tabsContainer: ITabsContainer;
|
private readonly tabsContainer: ITabsContainer;
|
||||||
private readonly contentContainer: IContentContainer;
|
private readonly contentContainer: IContentContainer;
|
||||||
private readonly dropTarget: Droptarget;
|
private readonly dropTarget: Droptarget;
|
||||||
private _activePanel?: IDockviewPanel;
|
private _activePanel: IDockviewPanel | undefined;
|
||||||
private watermark?: IWatermarkRenderer;
|
private watermark?: IWatermarkRenderer;
|
||||||
private _isGroupActive = false;
|
private _isGroupActive = false;
|
||||||
private _locked = false;
|
private _locked = false;
|
||||||
|
private _control: IGroupControlRenderer | undefined;
|
||||||
|
|
||||||
private mostRecentlyUsed: IDockviewPanel[] = [];
|
private mostRecentlyUsed: IDockviewPanel[] = [];
|
||||||
|
|
||||||
@ -140,13 +137,22 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
|||||||
private readonly _onMove = new Emitter<GroupMoveEvent>();
|
private readonly _onMove = new Emitter<GroupMoveEvent>();
|
||||||
readonly onMove: Event<GroupMoveEvent> = this._onMove.event;
|
readonly onMove: Event<GroupMoveEvent> = this._onMove.event;
|
||||||
|
|
||||||
private readonly _onDidGroupChange = new Emitter<GroupviewChangeEvent>();
|
|
||||||
readonly onDidGroupChange: Event<GroupviewChangeEvent> =
|
|
||||||
this._onDidGroupChange.event;
|
|
||||||
|
|
||||||
private readonly _onDidDrop = new Emitter<GroupviewDropEvent>();
|
private readonly _onDidDrop = new Emitter<GroupviewDropEvent>();
|
||||||
readonly onDidDrop: Event<GroupviewDropEvent> = this._onDidDrop.event;
|
readonly onDidDrop: Event<GroupviewDropEvent> = this._onDidDrop.event;
|
||||||
|
|
||||||
|
private readonly _onDidAddPanel = new Emitter<GroupviewChangeEvent>();
|
||||||
|
readonly onDidAddPanel: Event<GroupviewChangeEvent> =
|
||||||
|
this._onDidAddPanel.event;
|
||||||
|
|
||||||
|
private readonly _onDidRemovePanel = new Emitter<GroupviewChangeEvent>();
|
||||||
|
readonly onDidRemovePanel: Event<GroupviewChangeEvent> =
|
||||||
|
this._onDidRemovePanel.event;
|
||||||
|
|
||||||
|
private readonly _onDidActivePanelChange =
|
||||||
|
new Emitter<GroupviewChangeEvent>();
|
||||||
|
readonly onDidActivePanelChange: Event<GroupviewChangeEvent> =
|
||||||
|
this._onDidActivePanelChange.event;
|
||||||
|
|
||||||
get element(): HTMLElement {
|
get element(): HTMLElement {
|
||||||
throw new Error('not supported');
|
throw new Error('not supported');
|
||||||
}
|
}
|
||||||
@ -226,16 +232,10 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
|||||||
|
|
||||||
this.container.classList.add('groupview');
|
this.container.classList.add('groupview');
|
||||||
|
|
||||||
this.addDisposables(
|
|
||||||
this._onMove,
|
|
||||||
this._onDidGroupChange,
|
|
||||||
this._onDidChange,
|
|
||||||
this._onDidDrop
|
|
||||||
);
|
|
||||||
|
|
||||||
this.tabsContainer = new TabsContainer(this.accessor, this.parent, {
|
this.tabsContainer = new TabsContainer(this.accessor, this.parent, {
|
||||||
tabHeight: options.tabHeight,
|
tabHeight: options.tabHeight,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.contentContainer = new ContentContainer();
|
this.contentContainer = new ContentContainer();
|
||||||
|
|
||||||
this.dropTarget = new Droptarget(this.contentContainer.element, {
|
this.dropTarget = new Droptarget(this.contentContainer.element, {
|
||||||
@ -268,7 +268,11 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
|||||||
|
|
||||||
this.addDisposables(
|
this.addDisposables(
|
||||||
this._onMove,
|
this._onMove,
|
||||||
this._onDidGroupChange,
|
this._onDidChange,
|
||||||
|
this._onDidDrop,
|
||||||
|
this._onDidAddPanel,
|
||||||
|
this._onDidRemovePanel,
|
||||||
|
this._onDidActivePanelChange,
|
||||||
this.tabsContainer.onDrop((event) => {
|
this.tabsContainer.onDrop((event) => {
|
||||||
this.handleDropEvent(event.event, Position.Center, event.index);
|
this.handleDropEvent(event.event, Position.Center, event.index);
|
||||||
}),
|
}),
|
||||||
@ -284,7 +288,7 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
initialize() {
|
initialize(): void {
|
||||||
if (this.options?.panels) {
|
if (this.options?.panels) {
|
||||||
this.options.panels.forEach((panel) => {
|
this.options.panels.forEach((panel) => {
|
||||||
this.doAddPanel(panel);
|
this.doAddPanel(panel);
|
||||||
@ -299,9 +303,21 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
|||||||
// correctly initialized
|
// correctly initialized
|
||||||
this.setActive(this.isActive, true, true);
|
this.setActive(this.isActive, true, true);
|
||||||
this.updateContainer();
|
this.updateContainer();
|
||||||
|
|
||||||
|
if (this.accessor.options.createGroupControlElement) {
|
||||||
|
this._control = this.accessor.options.createGroupControlElement(
|
||||||
|
this.parent
|
||||||
|
);
|
||||||
|
this.addDisposables(this._control);
|
||||||
|
this._control.init({
|
||||||
|
containerApi: new DockviewApi(this.accessor),
|
||||||
|
api: this.parent.api,
|
||||||
|
});
|
||||||
|
this.tabsContainer.setActionElement(this._control.element);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public indexOf(panel: IDockviewPanel) {
|
public indexOf(panel: IDockviewPanel): number {
|
||||||
return this.tabsContainer.indexOf(panel.id);
|
return this.tabsContainer.indexOf(panel.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,7 +342,7 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
|||||||
public moveToNext(options?: {
|
public moveToNext(options?: {
|
||||||
panel?: IDockviewPanel;
|
panel?: IDockviewPanel;
|
||||||
suppressRoll?: boolean;
|
suppressRoll?: boolean;
|
||||||
}) {
|
}): void {
|
||||||
if (!options) {
|
if (!options) {
|
||||||
options = {};
|
options = {};
|
||||||
}
|
}
|
||||||
@ -352,7 +368,7 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
|||||||
public moveToPrevious(options?: {
|
public moveToPrevious(options?: {
|
||||||
panel?: IDockviewPanel;
|
panel?: IDockviewPanel;
|
||||||
suppressRoll?: boolean;
|
suppressRoll?: boolean;
|
||||||
}) {
|
}): void {
|
||||||
if (!options) {
|
if (!options) {
|
||||||
options = {};
|
options = {};
|
||||||
}
|
}
|
||||||
@ -379,19 +395,19 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
|||||||
this.openPanel(this.panels[normalizedIndex]);
|
this.openPanel(this.panels[normalizedIndex]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public containsPanel(panel: IDockviewPanel) {
|
public containsPanel(panel: IDockviewPanel): boolean {
|
||||||
return this.panels.includes(panel);
|
return this.panels.includes(panel);
|
||||||
}
|
}
|
||||||
|
|
||||||
init(_params: PanelInitParameters) {
|
init(_params: PanelInitParameters): void {
|
||||||
//noop
|
//noop
|
||||||
}
|
}
|
||||||
|
|
||||||
update(_params: PanelUpdateEvent) {
|
update(_params: PanelUpdateEvent): void {
|
||||||
//noop
|
//noop
|
||||||
}
|
}
|
||||||
|
|
||||||
focus() {
|
focus(): void {
|
||||||
this._activePanel?.focus();
|
this._activePanel?.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,7 +419,7 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
|||||||
skipSetPanelActive?: boolean;
|
skipSetPanelActive?: boolean;
|
||||||
skipSetGroupActive?: boolean;
|
skipSetGroupActive?: boolean;
|
||||||
} = {}
|
} = {}
|
||||||
) {
|
): void {
|
||||||
if (
|
if (
|
||||||
typeof options.index !== 'number' ||
|
typeof options.index !== 'number' ||
|
||||||
options.index > this.panels.length
|
options.index > this.panels.length
|
||||||
@ -452,7 +468,7 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
|||||||
return this._removePanel(panelToRemove);
|
return this._removePanel(panelToRemove);
|
||||||
}
|
}
|
||||||
|
|
||||||
public closeAllPanels() {
|
public closeAllPanels(): void {
|
||||||
if (this.panels.length > 0) {
|
if (this.panels.length > 0) {
|
||||||
// take a copy since we will be edting the array as we iterate through
|
// take a copy since we will be edting the array as we iterate through
|
||||||
const arrPanelCpy = [...this.panels];
|
const arrPanelCpy = [...this.panels];
|
||||||
@ -468,25 +484,23 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
|||||||
this.doClose(panel);
|
this.doClose(panel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private doClose(panel: IDockviewPanel) {
|
private doClose(panel: IDockviewPanel): void {
|
||||||
this.accessor.removePanel(panel);
|
this.accessor.removePanel(panel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public isPanelActive(panel: IDockviewPanel) {
|
public isPanelActive(panel: IDockviewPanel): boolean {
|
||||||
return this._activePanel === panel;
|
return this._activePanel === panel;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateActions() {
|
updateActions(element: HTMLElement | undefined): void {
|
||||||
if (this.isActive && this._activePanel?.view?.actions) {
|
this.tabsContainer.setActionElement(element);
|
||||||
this.tabsContainer.setActionElement(
|
|
||||||
this._activePanel.view.actions.element
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
this.tabsContainer.setActionElement(undefined);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public setActive(isGroupActive: boolean, skipFocus = false, force = false) {
|
public setActive(
|
||||||
|
isGroupActive: boolean,
|
||||||
|
skipFocus = false,
|
||||||
|
force = false
|
||||||
|
): void {
|
||||||
if (!force && this.isActive === isGroupActive) {
|
if (!force && this.isActive === isGroupActive) {
|
||||||
if (!skipFocus) {
|
if (!skipFocus) {
|
||||||
this._activePanel?.focus();
|
this._activePanel?.focus();
|
||||||
@ -514,7 +528,7 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public layout(width: number, height: number) {
|
public layout(width: number, height: number): void {
|
||||||
this._width = width;
|
this._width = width;
|
||||||
this._height = height;
|
this._height = height;
|
||||||
|
|
||||||
@ -525,7 +539,7 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _removePanel(panel: IDockviewPanel) {
|
private _removePanel(panel: IDockviewPanel): IDockviewPanel {
|
||||||
const isActivePanel = this._activePanel === panel;
|
const isActivePanel = this._activePanel === panel;
|
||||||
|
|
||||||
this.doRemovePanel(panel);
|
this.doRemovePanel(panel);
|
||||||
@ -543,7 +557,7 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
|||||||
return panel;
|
return panel;
|
||||||
}
|
}
|
||||||
|
|
||||||
private doRemovePanel(panel: IDockviewPanel) {
|
private doRemovePanel(panel: IDockviewPanel): void {
|
||||||
const index = this.panels.indexOf(panel);
|
const index = this.panels.indexOf(panel);
|
||||||
|
|
||||||
if (this._activePanel === panel) {
|
if (this._activePanel === panel) {
|
||||||
@ -560,17 +574,14 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._onDidGroupChange.fire({
|
this._onDidRemovePanel.fire({ panel });
|
||||||
kind: GroupChangeKind2.REMOVE_PANEL,
|
|
||||||
panel,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private doAddPanel(
|
private doAddPanel(
|
||||||
panel: IDockviewPanel,
|
panel: IDockviewPanel,
|
||||||
index: number = this.panels.length,
|
index: number = this.panels.length,
|
||||||
skipSetActive = false
|
skipSetActive = false
|
||||||
) {
|
): void {
|
||||||
const existingPanel = this._panels.indexOf(panel);
|
const existingPanel = this._panels.indexOf(panel);
|
||||||
const hasExistingPanel = existingPanel > -1;
|
const hasExistingPanel = existingPanel > -1;
|
||||||
|
|
||||||
@ -591,13 +602,10 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
|||||||
this.updateMru(panel);
|
this.updateMru(panel);
|
||||||
this.panels.splice(index, 0, panel);
|
this.panels.splice(index, 0, panel);
|
||||||
|
|
||||||
this._onDidGroupChange.fire({
|
this._onDidAddPanel.fire({ panel });
|
||||||
kind: GroupChangeKind2.ADD_PANEL,
|
|
||||||
panel,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private doSetActivePanel(panel: IDockviewPanel | undefined) {
|
private doSetActivePanel(panel: IDockviewPanel | undefined): void {
|
||||||
this._activePanel = panel;
|
this._activePanel = panel;
|
||||||
|
|
||||||
if (panel) {
|
if (panel) {
|
||||||
@ -607,14 +615,11 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
|||||||
|
|
||||||
this.updateMru(panel);
|
this.updateMru(panel);
|
||||||
|
|
||||||
this._onDidGroupChange.fire({
|
this._onDidActivePanelChange.fire({ panel });
|
||||||
kind: GroupChangeKind2.PANEL_ACTIVE,
|
|
||||||
panel,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateMru(panel: IDockviewPanel) {
|
private updateMru(panel: IDockviewPanel): void {
|
||||||
if (this.mostRecentlyUsed.includes(panel)) {
|
if (this.mostRecentlyUsed.includes(panel)) {
|
||||||
this.mostRecentlyUsed.splice(
|
this.mostRecentlyUsed.splice(
|
||||||
this.mostRecentlyUsed.indexOf(panel),
|
this.mostRecentlyUsed.indexOf(panel),
|
||||||
@ -624,8 +629,7 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
|||||||
this.mostRecentlyUsed = [panel, ...this.mostRecentlyUsed];
|
this.mostRecentlyUsed = [panel, ...this.mostRecentlyUsed];
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateContainer() {
|
private updateContainer(): void {
|
||||||
this.updateActions();
|
|
||||||
toggleClass(this.container, 'empty', this.isEmpty);
|
toggleClass(this.container, 'empty', this.isEmpty);
|
||||||
|
|
||||||
this.panels.forEach((panel) =>
|
this.panels.forEach((panel) =>
|
||||||
@ -680,7 +684,7 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
|||||||
event: DragEvent,
|
event: DragEvent,
|
||||||
position: Position,
|
position: Position,
|
||||||
index?: number
|
index?: number
|
||||||
) {
|
): void {
|
||||||
const data = getPanelData();
|
const data = getPanelData();
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
@ -716,7 +720,7 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public dispose() {
|
public dispose(): void {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
|
|
||||||
this.watermark?.dispose();
|
this.watermark?.dispose();
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { IDisposable } from '../lifecycle';
|
|
||||||
import { IDockviewComponent } from '../dockview/dockviewComponent';
|
import { IDockviewComponent } from '../dockview/dockviewComponent';
|
||||||
import { DockviewPanelApi } from '../api/groupPanelApi';
|
import { DockviewPanelApi } from '../api/groupPanelApi';
|
||||||
import { PanelInitParameters, IPanel } from '../panel/types';
|
import { PanelInitParameters, IPanel } from '../panel/types';
|
||||||
@ -42,10 +41,6 @@ export interface ITabRenderer extends IPanel {
|
|||||||
updateParentGroup(group: GroupPanel, isPanelVisible: boolean): void;
|
updateParentGroup(group: GroupPanel, isPanelVisible: boolean): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IActionsRenderer extends IDisposable {
|
|
||||||
readonly element: HTMLElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IContentRenderer extends IPanel {
|
export interface IContentRenderer extends IPanel {
|
||||||
readonly element: HTMLElement;
|
readonly element: HTMLElement;
|
||||||
readonly actions?: HTMLElement;
|
readonly actions?: HTMLElement;
|
||||||
|
@ -12,15 +12,36 @@ import {
|
|||||||
TabContextMenuEvent,
|
TabContextMenuEvent,
|
||||||
} from '../../dockview/options';
|
} from '../../dockview/options';
|
||||||
import { DockviewPanelApi } from '../../api/groupPanelApi';
|
import { DockviewPanelApi } from '../../api/groupPanelApi';
|
||||||
import { usePortalsLifecycle } from '../react';
|
import { ReactPortalStore, usePortalsLifecycle } from '../react';
|
||||||
import { DockviewApi } from '../../api/component.api';
|
import { DockviewApi } from '../../api/component.api';
|
||||||
import { IWatermarkPanelProps, ReactWatermarkPart } from './reactWatermarkPart';
|
import { IWatermarkPanelProps, ReactWatermarkPart } from './reactWatermarkPart';
|
||||||
import { PanelCollection, PanelParameters } from '../types';
|
import { PanelCollection, PanelParameters } from '../types';
|
||||||
import { watchElementResize } from '../../dom';
|
import { watchElementResize } from '../../dom';
|
||||||
import { IContentRenderer, ITabRenderer } from '../../groupview/types';
|
import { IContentRenderer, ITabRenderer } from '../../groupview/types';
|
||||||
|
import {
|
||||||
|
IDockviewGroupControlProps,
|
||||||
|
IGroupControlRenderer,
|
||||||
|
ReactGroupControlsRendererPart,
|
||||||
|
} from './groupControlsRenderer';
|
||||||
|
import { GroupPanel } from '../../groupview/groupviewPanel';
|
||||||
|
|
||||||
export const DEFAULT_TAB_IDENTIFIER = '__default__tab__';
|
export const DEFAULT_TAB_IDENTIFIER = '__default__tab__';
|
||||||
|
|
||||||
|
function createGroupControlElement(
|
||||||
|
component: React.FunctionComponent<IDockviewGroupControlProps> | undefined,
|
||||||
|
store: ReactPortalStore
|
||||||
|
): ((groupPanel: GroupPanel) => IGroupControlRenderer) | undefined {
|
||||||
|
return component
|
||||||
|
? (groupPanel: GroupPanel) => {
|
||||||
|
return new ReactGroupControlsRendererPart(
|
||||||
|
component,
|
||||||
|
store,
|
||||||
|
groupPanel
|
||||||
|
);
|
||||||
|
}
|
||||||
|
: undefined;
|
||||||
|
}
|
||||||
|
|
||||||
export interface IGroupPanelBaseProps<T extends {} = Record<string, any>>
|
export interface IGroupPanelBaseProps<T extends {} = Record<string, any>>
|
||||||
extends PanelParameters<T> {
|
extends PanelParameters<T> {
|
||||||
api: DockviewPanelApi;
|
api: DockviewPanelApi;
|
||||||
@ -50,6 +71,7 @@ export interface IDockviewReactProps {
|
|||||||
className?: string;
|
className?: string;
|
||||||
disableAutoResizing?: boolean;
|
disableAutoResizing?: boolean;
|
||||||
defaultTabComponent?: React.FunctionComponent<IDockviewPanelHeaderProps>;
|
defaultTabComponent?: React.FunctionComponent<IDockviewPanelHeaderProps>;
|
||||||
|
groupControlComponent?: React.FunctionComponent<IDockviewGroupControlProps>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DockviewReact = React.forwardRef(
|
export const DockviewReact = React.forwardRef(
|
||||||
@ -138,6 +160,10 @@ export const DockviewReact = React.forwardRef(
|
|||||||
? { separatorBorder: 'transparent' }
|
? { separatorBorder: 'transparent' }
|
||||||
: undefined,
|
: undefined,
|
||||||
showDndOverlay: props.showDndOverlay,
|
showDndOverlay: props.showDndOverlay,
|
||||||
|
createGroupControlElement: createGroupControlElement(
|
||||||
|
props.groupControlComponent,
|
||||||
|
{ addPortal }
|
||||||
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
domRef.current?.appendChild(dockview.element);
|
domRef.current?.appendChild(dockview.element);
|
||||||
@ -243,6 +269,18 @@ export const DockviewReact = React.forwardRef(
|
|||||||
});
|
});
|
||||||
}, [props.defaultTabComponent]);
|
}, [props.defaultTabComponent]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (!dockviewRef.current) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dockviewRef.current.updateOptions({
|
||||||
|
createGroupControlElement: createGroupControlElement(
|
||||||
|
props.groupControlComponent,
|
||||||
|
{ addPortal }
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}, [props.groupControlComponent]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={props.className}
|
className={props.className}
|
||||||
|
117
packages/dockview/src/react/dockview/groupControlsRenderer.ts
Normal file
117
packages/dockview/src/react/dockview/groupControlsRenderer.ts
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { ReactPart, ReactPortalStore } from '../react';
|
||||||
|
import { PanelUpdateEvent } from '../../panel/types';
|
||||||
|
import { GroupPanel, GroupviewPanelApi } from '../../groupview/groupviewPanel';
|
||||||
|
import { DockviewApi } from '../../api/component.api';
|
||||||
|
import {
|
||||||
|
CompositeDisposable,
|
||||||
|
IDisposable,
|
||||||
|
MutableDisposable,
|
||||||
|
} from '../../lifecycle';
|
||||||
|
import { IDockviewPanel } from '../../groupview/groupPanel';
|
||||||
|
|
||||||
|
export interface IDockviewGroupControlProps {
|
||||||
|
api: GroupviewPanelApi;
|
||||||
|
containerApi: DockviewApi;
|
||||||
|
panels: IDockviewPanel[];
|
||||||
|
activePanel: IDockviewPanel | undefined;
|
||||||
|
isGroupActive: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IGroupControlRenderer extends IDisposable {
|
||||||
|
readonly element: HTMLElement;
|
||||||
|
init(params: { containerApi: DockviewApi; api: GroupviewPanelApi }): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ReactGroupControlsRendererPart {
|
||||||
|
private mutableDisposable = new MutableDisposable();
|
||||||
|
private _element: HTMLElement;
|
||||||
|
private _part?: ReactPart<IDockviewGroupControlProps>;
|
||||||
|
|
||||||
|
get element(): HTMLElement {
|
||||||
|
return this._element;
|
||||||
|
}
|
||||||
|
|
||||||
|
get part(): ReactPart<IDockviewGroupControlProps> | undefined {
|
||||||
|
return this._part;
|
||||||
|
}
|
||||||
|
|
||||||
|
get group(): GroupPanel {
|
||||||
|
return this._group;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private readonly component: React.FunctionComponent<IDockviewGroupControlProps>,
|
||||||
|
private readonly reactPortalStore: ReactPortalStore,
|
||||||
|
private readonly _group: GroupPanel
|
||||||
|
) {
|
||||||
|
this._element = document.createElement('div');
|
||||||
|
this._element.className = 'dockview-react-part';
|
||||||
|
}
|
||||||
|
|
||||||
|
focus() {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(parameters: {
|
||||||
|
containerApi: DockviewApi;
|
||||||
|
api: GroupviewPanelApi;
|
||||||
|
}): void {
|
||||||
|
this.mutableDisposable.value = new CompositeDisposable(
|
||||||
|
this._group.model.onDidAddPanel(() => {
|
||||||
|
this.updatePanels();
|
||||||
|
}),
|
||||||
|
this._group.model.onDidRemovePanel(() => {
|
||||||
|
this.updatePanels();
|
||||||
|
}),
|
||||||
|
this._group.model.onDidActivePanelChange(() => {
|
||||||
|
this.updateActivePanel();
|
||||||
|
}),
|
||||||
|
parameters.api.onDidActiveChange(() => {
|
||||||
|
this.updateGroupActive();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
this._part = new ReactPart(
|
||||||
|
this.element,
|
||||||
|
this.reactPortalStore,
|
||||||
|
this.component,
|
||||||
|
{
|
||||||
|
api: parameters.api,
|
||||||
|
containerApi: parameters.containerApi,
|
||||||
|
panels: this._group.model.panels,
|
||||||
|
activePanel: this._group.model.activePanel,
|
||||||
|
isGroupActive: this._group.api.isActive,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public update(event: PanelUpdateEvent) {
|
||||||
|
this._part?.update(event.params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public dispose() {
|
||||||
|
this.mutableDisposable.dispose();
|
||||||
|
this._part?.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private updatePanels() {
|
||||||
|
this.update({ params: { panels: this._group.model.panels } });
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateActivePanel() {
|
||||||
|
this.update({
|
||||||
|
params: {
|
||||||
|
activePanel: this._group.model.activePanel,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateGroupActive() {
|
||||||
|
this.update({
|
||||||
|
params: {
|
||||||
|
isGroupActive: this._group.api.isActive,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -2,34 +2,17 @@ import * as React from 'react';
|
|||||||
import {
|
import {
|
||||||
IContentRenderer,
|
IContentRenderer,
|
||||||
GroupPanelContentPartInitParameters,
|
GroupPanelContentPartInitParameters,
|
||||||
ITabRenderer,
|
|
||||||
} from '../../groupview/types';
|
} from '../../groupview/types';
|
||||||
import { ReactPart, ReactPortalStore } from '../react';
|
import { ReactPart, ReactPortalStore } from '../react';
|
||||||
import { IDockviewPanelProps } from '../dockview/dockview';
|
import { IDockviewPanelProps } from '../dockview/dockview';
|
||||||
import { PanelUpdateEvent } from '../../panel/types';
|
import { PanelUpdateEvent } from '../../panel/types';
|
||||||
import { DockviewPanelApi } from '../../api/groupPanelApi';
|
|
||||||
import { DockviewApi } from '../../api/component.api';
|
|
||||||
import { GroupPanel } from '../../groupview/groupviewPanel';
|
import { GroupPanel } from '../../groupview/groupviewPanel';
|
||||||
import { Emitter, Event } from '../../events';
|
import { Emitter, Event } from '../../events';
|
||||||
|
|
||||||
export interface IGroupPanelActionbarProps {
|
|
||||||
api: DockviewPanelApi;
|
|
||||||
containerApi: DockviewApi;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ReactContentPartContext {
|
|
||||||
api: DockviewPanelApi;
|
|
||||||
containerApi: DockviewApi;
|
|
||||||
actionsPortalElement: HTMLElement;
|
|
||||||
tabPortalElement: ITabRenderer;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ReactPanelContentPart implements IContentRenderer {
|
export class ReactPanelContentPart implements IContentRenderer {
|
||||||
private _element: HTMLElement;
|
private _element: HTMLElement;
|
||||||
private part?: ReactPart<IDockviewPanelProps>;
|
private part?: ReactPart<IDockviewPanelProps>;
|
||||||
//
|
//
|
||||||
private _actionsElement: HTMLElement;
|
|
||||||
private actionsPart?: ReactPart<any>;
|
|
||||||
private _group: GroupPanel | undefined;
|
private _group: GroupPanel | undefined;
|
||||||
|
|
||||||
private readonly _onDidFocus = new Emitter<void>();
|
private readonly _onDidFocus = new Emitter<void>();
|
||||||
@ -42,10 +25,6 @@ export class ReactPanelContentPart implements IContentRenderer {
|
|||||||
return this._element;
|
return this._element;
|
||||||
}
|
}
|
||||||
|
|
||||||
get actions(): HTMLElement {
|
|
||||||
return this._actionsElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public readonly id: string,
|
public readonly id: string,
|
||||||
private readonly component: React.FunctionComponent<IDockviewPanelProps>,
|
private readonly component: React.FunctionComponent<IDockviewPanelProps>,
|
||||||
@ -53,9 +32,6 @@ export class ReactPanelContentPart implements IContentRenderer {
|
|||||||
) {
|
) {
|
||||||
this._element = document.createElement('div');
|
this._element = document.createElement('div');
|
||||||
this._element.className = 'dockview-react-part';
|
this._element.className = 'dockview-react-part';
|
||||||
|
|
||||||
this._actionsElement = document.createElement('div');
|
|
||||||
this._actionsElement.className = 'dockview-react-part';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
focus() {
|
focus() {
|
||||||
@ -63,13 +39,6 @@ export class ReactPanelContentPart implements IContentRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public init(parameters: GroupPanelContentPartInitParameters): void {
|
public init(parameters: GroupPanelContentPartInitParameters): void {
|
||||||
const context: ReactContentPartContext = {
|
|
||||||
api: parameters.api,
|
|
||||||
containerApi: parameters.containerApi,
|
|
||||||
actionsPortalElement: this._actionsElement,
|
|
||||||
tabPortalElement: parameters.tab,
|
|
||||||
};
|
|
||||||
|
|
||||||
this.part = new ReactPart(
|
this.part = new ReactPart(
|
||||||
this.element,
|
this.element,
|
||||||
this.reactPortalStore,
|
this.reactPortalStore,
|
||||||
@ -78,8 +47,7 @@ export class ReactPanelContentPart implements IContentRenderer {
|
|||||||
params: parameters.params,
|
params: parameters.params,
|
||||||
api: parameters.api,
|
api: parameters.api,
|
||||||
containerApi: parameters.containerApi,
|
containerApi: parameters.containerApi,
|
||||||
},
|
}
|
||||||
context
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,6 +76,5 @@ export class ReactPanelContentPart implements IContentRenderer {
|
|||||||
this._onDidFocus.dispose();
|
this._onDidFocus.dispose();
|
||||||
this._onDidBlur.dispose();
|
this._onDidBlur.dispose();
|
||||||
this.part?.dispose();
|
this.part?.dispose();
|
||||||
this.actionsPart?.dispose();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,7 @@ export * from './dockview/dockview';
|
|||||||
export * from './dockview/defaultTab';
|
export * from './dockview/defaultTab';
|
||||||
export * from './splitview/splitview';
|
export * from './splitview/splitview';
|
||||||
export * from './gridview/gridview';
|
export * from './gridview/gridview';
|
||||||
export * from './dockview/reactContentPart';
|
export { IDockviewGroupControlProps } from './dockview/groupControlsRenderer';
|
||||||
export * from './dockview/reactHeaderPart';
|
|
||||||
export { IWatermarkPanelProps } from './dockview/reactWatermarkPart';
|
export { IWatermarkPanelProps } from './dockview/reactWatermarkPart';
|
||||||
export * from './paneview/paneview';
|
export * from './paneview/paneview';
|
||||||
export * from './types';
|
export * from './types';
|
||||||
|
@ -65,6 +65,7 @@ export const ReactPartContext = React.createContext<{}>({});
|
|||||||
export class ReactPart<P extends object, C extends object = {}>
|
export class ReactPart<P extends object, C extends object = {}>
|
||||||
implements IFrameworkPart
|
implements IFrameworkPart
|
||||||
{
|
{
|
||||||
|
private _initialProps: Record<string, any> = {};
|
||||||
private componentInstance?: IPanelWrapperRef;
|
private componentInstance?: IPanelWrapperRef;
|
||||||
private ref?: { portal: React.ReactPortal; disposable: IDisposable };
|
private ref?: { portal: React.ReactPortal; disposable: IDisposable };
|
||||||
private disposed = false;
|
private disposed = false;
|
||||||
@ -84,7 +85,12 @@ export class ReactPart<P extends object, C extends object = {}>
|
|||||||
throw new Error('invalid operation: resource is already disposed');
|
throw new Error('invalid operation: resource is already disposed');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.componentInstance?.update(props);
|
if (!this.componentInstance) {
|
||||||
|
// if the component is yet to be mounted store the props
|
||||||
|
this._initialProps = { ...this._initialProps, ...props };
|
||||||
|
} else {
|
||||||
|
this.componentInstance.update(props);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private createPortal() {
|
private createPortal() {
|
||||||
@ -111,6 +117,11 @@ export class ReactPart<P extends object, C extends object = {}>
|
|||||||
componentProps: this.parameters as unknown as {},
|
componentProps: this.parameters as unknown as {},
|
||||||
ref: (element: IPanelWrapperRef) => {
|
ref: (element: IPanelWrapperRef) => {
|
||||||
this.componentInstance = element;
|
this.componentInstance = element;
|
||||||
|
|
||||||
|
if (Object.keys(this._initialProps).length > 0) {
|
||||||
|
this.componentInstance.update(this._initialProps);
|
||||||
|
this._initialProps = {}; // don't keep a reference to the users object once no longer required
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user