mirror of
https://github.com/mathuo/dockview
synced 2025-01-22 17:35:57 +00:00
feat: popout group enhancements
This commit is contained in:
parent
c2791c6124
commit
0bca63b550
@ -62,16 +62,19 @@ describe('contentContainer', () => {
|
|||||||
|
|
||||||
const disposable = new CompositeDisposable();
|
const disposable = new CompositeDisposable();
|
||||||
|
|
||||||
const dockviewComponent = jest.fn<DockviewComponent, []>(() => {
|
const overlayRenderContainer = new OverlayRenderContainer(
|
||||||
return {
|
document.createElement('div')
|
||||||
renderer: 'onlyWhenVisibile',
|
);
|
||||||
overlayRenderContainer: new OverlayRenderContainer(
|
|
||||||
document.createElement('div')
|
|
||||||
),
|
|
||||||
} as DockviewComponent;
|
|
||||||
});
|
|
||||||
|
|
||||||
const cut = new ContentContainer(dockviewComponent(), jest.fn() as any);
|
const cut = new ContentContainer(
|
||||||
|
fromPartial<DockviewComponent>({
|
||||||
|
renderer: 'onlyWhenVisibile',
|
||||||
|
overlayRenderContainer,
|
||||||
|
}),
|
||||||
|
fromPartial<DockviewGroupPanelModel>({
|
||||||
|
renderContainer: overlayRenderContainer,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
disposable.addDisposables(
|
disposable.addDisposables(
|
||||||
cut.onDidFocus(() => {
|
cut.onDidFocus(() => {
|
||||||
@ -84,12 +87,12 @@ describe('contentContainer', () => {
|
|||||||
|
|
||||||
const contentRenderer = new TestContentRenderer('id-1');
|
const contentRenderer = new TestContentRenderer('id-1');
|
||||||
|
|
||||||
const panel = {
|
const panel = fromPartial<IDockviewPanel>({
|
||||||
view: {
|
view: {
|
||||||
content: contentRenderer,
|
content: contentRenderer,
|
||||||
} as Partial<IDockviewPanelModel>,
|
},
|
||||||
api: { renderer: 'onlyWhenVisibile' },
|
api: { renderer: 'onlyWhenVisibile' },
|
||||||
} as Partial<IDockviewPanel>;
|
});
|
||||||
|
|
||||||
cut.openPanel(panel as IDockviewPanel);
|
cut.openPanel(panel as IDockviewPanel);
|
||||||
|
|
||||||
@ -151,13 +154,17 @@ describe('contentContainer', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("that panels renderered as 'onlyWhenVisibile' are removed when closed", () => {
|
test("that panels renderered as 'onlyWhenVisibile' are removed when closed", () => {
|
||||||
|
const overlayRenderContainer = fromPartial<OverlayRenderContainer>({
|
||||||
|
detatch: jest.fn(),
|
||||||
|
});
|
||||||
|
|
||||||
const cut = new ContentContainer(
|
const cut = new ContentContainer(
|
||||||
fromPartial<DockviewComponent>({
|
fromPartial<DockviewComponent>({
|
||||||
overlayRenderContainer: {
|
overlayRenderContainer,
|
||||||
detatch: jest.fn(),
|
|
||||||
},
|
|
||||||
}),
|
}),
|
||||||
fromPartial<DockviewGroupPanelModel>({})
|
fromPartial<DockviewGroupPanelModel>({
|
||||||
|
renderContainer: overlayRenderContainer,
|
||||||
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const panel1 = fromPartial<IDockviewPanel>({
|
const panel1 = fromPartial<IDockviewPanel>({
|
||||||
|
@ -4434,44 +4434,12 @@ describe('dockviewComponent', () => {
|
|||||||
cb();
|
cb();
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
removeEventListener: jest.fn(),
|
||||||
close: jest.fn(),
|
close: jest.fn(),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('that can remove a popout group', async () => {
|
|
||||||
const container = document.createElement('div');
|
|
||||||
|
|
||||||
const dockview = new DockviewComponent({
|
|
||||||
parentElement: container,
|
|
||||||
components: {
|
|
||||||
default: PanelContentPartTest,
|
|
||||||
},
|
|
||||||
tabComponents: {
|
|
||||||
test_tab_id: PanelTabPartTest,
|
|
||||||
},
|
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
|
||||||
|
|
||||||
const panel1 = dockview.addPanel({
|
|
||||||
id: 'panel_1',
|
|
||||||
component: 'default',
|
|
||||||
});
|
|
||||||
|
|
||||||
await dockview.addPopoutGroup(panel1);
|
|
||||||
|
|
||||||
expect(dockview.panels.length).toBe(1);
|
|
||||||
expect(dockview.groups.length).toBe(2);
|
|
||||||
expect(panel1.api.group.api.location.type).toBe('popout');
|
|
||||||
|
|
||||||
dockview.removePanel(panel1);
|
|
||||||
|
|
||||||
expect(dockview.panels.length).toBe(0);
|
|
||||||
expect(dockview.groups.length).toBe(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('add a popout group', async () => {
|
test('add a popout group', async () => {
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
|
|
||||||
@ -4511,6 +4479,39 @@ describe('dockviewComponent', () => {
|
|||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('that can remove a popout group', async () => {
|
||||||
|
const container = document.createElement('div');
|
||||||
|
|
||||||
|
const dockview = new DockviewComponent({
|
||||||
|
parentElement: container,
|
||||||
|
components: {
|
||||||
|
default: PanelContentPartTest,
|
||||||
|
},
|
||||||
|
tabComponents: {
|
||||||
|
test_tab_id: PanelTabPartTest,
|
||||||
|
},
|
||||||
|
orientation: Orientation.HORIZONTAL,
|
||||||
|
});
|
||||||
|
|
||||||
|
dockview.layout(1000, 500);
|
||||||
|
|
||||||
|
const panel1 = dockview.addPanel({
|
||||||
|
id: 'panel_1',
|
||||||
|
component: 'default',
|
||||||
|
});
|
||||||
|
|
||||||
|
await dockview.addPopoutGroup(panel1);
|
||||||
|
|
||||||
|
expect(dockview.panels.length).toBe(1);
|
||||||
|
expect(dockview.groups.length).toBe(2);
|
||||||
|
expect(panel1.api.group.api.location.type).toBe('popout');
|
||||||
|
|
||||||
|
dockview.removePanel(panel1);
|
||||||
|
|
||||||
|
expect(dockview.panels.length).toBe(0);
|
||||||
|
expect(dockview.groups.length).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
test('move from fixed to popout group and back', async () => {
|
test('move from fixed to popout group and back', async () => {
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ export class ContentContainer
|
|||||||
|
|
||||||
switch (panel.api.renderer) {
|
switch (panel.api.renderer) {
|
||||||
case 'onlyWhenVisibile':
|
case 'onlyWhenVisibile':
|
||||||
this.accessor.overlayRenderContainer.detatch(panel);
|
this.group.renderContainer.detatch(panel);
|
||||||
if (this.panel) {
|
if (this.panel) {
|
||||||
if (doRender) {
|
if (doRender) {
|
||||||
this._element.appendChild(
|
this._element.appendChild(
|
||||||
@ -149,7 +149,7 @@ export class ContentContainer
|
|||||||
) {
|
) {
|
||||||
this._element.removeChild(panel.view.content.element);
|
this._element.removeChild(panel.view.content.element);
|
||||||
}
|
}
|
||||||
container = this.accessor.overlayRenderContainer.attach({
|
container = this.group.renderContainer.attach({
|
||||||
panel,
|
panel,
|
||||||
referenceContainer: this,
|
referenceContainer: this,
|
||||||
});
|
});
|
||||||
|
@ -13,7 +13,7 @@ import {
|
|||||||
import { tail, sequenceEquals, remove } from '../array';
|
import { tail, sequenceEquals, remove } from '../array';
|
||||||
import { DockviewPanel, IDockviewPanel } from './dockviewPanel';
|
import { DockviewPanel, IDockviewPanel } from './dockviewPanel';
|
||||||
import { CompositeDisposable, Disposable, IDisposable } from '../lifecycle';
|
import { CompositeDisposable, Disposable, IDisposable } from '../lifecycle';
|
||||||
import { Event, Emitter } from '../events';
|
import { Event, Emitter, addDisposableWindowListener } from '../events';
|
||||||
import { Watermark } from './components/watermark/watermark';
|
import { Watermark } from './components/watermark/watermark';
|
||||||
import { IWatermarkRenderer, GroupviewPanelState } from './types';
|
import { IWatermarkRenderer, GroupviewPanelState } from './types';
|
||||||
import { sequentialNumberGenerator } from '../math';
|
import { sequentialNumberGenerator } from '../math';
|
||||||
@ -561,12 +561,15 @@ export class DockviewComponent
|
|||||||
from: DockviewGroupPanel;
|
from: DockviewGroupPanel;
|
||||||
to: DockviewGroupPanel;
|
to: DockviewGroupPanel;
|
||||||
}) {
|
}) {
|
||||||
|
const activePanel = options.from.activePanel;
|
||||||
const panels = [...options.from.panels].map((panel) =>
|
const panels = [...options.from.panels].map((panel) =>
|
||||||
options.from.model.removePanel(panel)
|
options.from.model.removePanel(panel)
|
||||||
);
|
);
|
||||||
|
|
||||||
panels.forEach((panel) => {
|
panels.forEach((panel) => {
|
||||||
options.to.model.openPanel(panel);
|
options.to.model.openPanel(panel, {
|
||||||
|
skipSetPanelActive: activePanel !== panel,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -624,10 +627,18 @@ export class DockviewComponent
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const gready = document.createElement('div');
|
||||||
|
gready.className = 'dv-overlay-render-container';
|
||||||
|
|
||||||
|
const overlayRenderContainer = new OverlayRenderContainer(
|
||||||
|
gready
|
||||||
|
);
|
||||||
|
|
||||||
const referenceGroup =
|
const referenceGroup =
|
||||||
item instanceof DockviewPanel ? item.group : item;
|
item instanceof DockviewPanel ? item.group : item;
|
||||||
|
|
||||||
const group = this.createGroup({ id: groupId });
|
const group = this.createGroup({ id: groupId });
|
||||||
|
group.model.renderContainer = overlayRenderContainer;
|
||||||
|
|
||||||
if (item instanceof DockviewPanel) {
|
if (item instanceof DockviewPanel) {
|
||||||
const panel = referenceGroup.model.removePanel(item);
|
const panel = referenceGroup.model.removePanel(item);
|
||||||
@ -637,9 +648,13 @@ export class DockviewComponent
|
|||||||
from: referenceGroup,
|
from: referenceGroup,
|
||||||
to: group,
|
to: group,
|
||||||
});
|
});
|
||||||
referenceGroup.api.setHidden(false);
|
referenceGroup.api.setHidden(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
popoutContainer.classList.add('dv-dockview');
|
||||||
|
popoutContainer.style.overflow = 'hidden';
|
||||||
|
popoutContainer.appendChild(gready);
|
||||||
|
|
||||||
popoutContainer.appendChild(group.element);
|
popoutContainer.appendChild(group.element);
|
||||||
|
|
||||||
group.model.location = {
|
group.model.location = {
|
||||||
@ -655,6 +670,19 @@ export class DockviewComponent
|
|||||||
};
|
};
|
||||||
|
|
||||||
popoutWindowDisposable.addDisposables(
|
popoutWindowDisposable.addDisposables(
|
||||||
|
/**
|
||||||
|
* ResizeObserver seems slow here, I do not know why but we don't need it
|
||||||
|
* since we can reply on the window resize event as we will occupy the full
|
||||||
|
* window dimensions
|
||||||
|
*/
|
||||||
|
addDisposableWindowListener(
|
||||||
|
_window.window!,
|
||||||
|
'resize',
|
||||||
|
() => {
|
||||||
|
group.layout(window.innerWidth, window.innerHeight);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
overlayRenderContainer,
|
||||||
Disposable.from(() => {
|
Disposable.from(() => {
|
||||||
if (this.getPanel(referenceGroup.id)) {
|
if (this.getPanel(referenceGroup.id)) {
|
||||||
moveGroupWithoutDestroying({
|
moveGroupWithoutDestroying({
|
||||||
@ -666,12 +694,16 @@ export class DockviewComponent
|
|||||||
referenceGroup.api.setHidden(false);
|
referenceGroup.api.setHidden(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.doRemoveGroup(group);
|
this.doRemoveGroup(group, {
|
||||||
|
skipPopoutAssociated: true,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
const removedGroup = this.doRemoveGroup(group, {
|
const removedGroup = this.doRemoveGroup(group, {
|
||||||
skipDispose: true,
|
skipDispose: true,
|
||||||
skipActive: true,
|
skipActive: true,
|
||||||
});
|
});
|
||||||
|
removedGroup.model.renderContainer =
|
||||||
|
this.overlayRenderContainer;
|
||||||
removedGroup.model.location = { type: 'grid' };
|
removedGroup.model.location = { type: 'grid' };
|
||||||
this.doAddGroup(removedGroup, [0]);
|
this.doAddGroup(removedGroup, [0]);
|
||||||
}
|
}
|
||||||
@ -1484,6 +1516,7 @@ export class DockviewComponent
|
|||||||
| {
|
| {
|
||||||
skipActive?: boolean;
|
skipActive?: boolean;
|
||||||
skipDispose?: boolean;
|
skipDispose?: boolean;
|
||||||
|
skipPopoutAssociated?: boolean;
|
||||||
}
|
}
|
||||||
| undefined
|
| undefined
|
||||||
): DockviewGroupPanel {
|
): DockviewGroupPanel {
|
||||||
@ -1523,7 +1556,9 @@ export class DockviewComponent
|
|||||||
|
|
||||||
if (selectedGroup) {
|
if (selectedGroup) {
|
||||||
if (!options?.skipDispose) {
|
if (!options?.skipDispose) {
|
||||||
this.doRemoveGroup(selectedGroup.referenceGroup);
|
if (!options?.skipPopoutAssociated) {
|
||||||
|
this.removeGroup(selectedGroup.referenceGroup);
|
||||||
|
}
|
||||||
|
|
||||||
selectedGroup.popoutGroup.dispose();
|
selectedGroup.popoutGroup.dispose();
|
||||||
this._groups.delete(group.id);
|
this._groups.delete(group.id);
|
||||||
|
@ -26,6 +26,7 @@ import { DockviewDropTargets, IWatermarkRenderer } from './types';
|
|||||||
import { DockviewGroupPanel } from './dockviewGroupPanel';
|
import { DockviewGroupPanel } from './dockviewGroupPanel';
|
||||||
import { IDockviewPanel } from './dockviewPanel';
|
import { IDockviewPanel } from './dockviewPanel';
|
||||||
import { IHeaderActionsRenderer } from './options';
|
import { IHeaderActionsRenderer } from './options';
|
||||||
|
import { OverlayRenderContainer } from '../overlayRenderContainer';
|
||||||
|
|
||||||
interface GroupMoveEvent {
|
interface GroupMoveEvent {
|
||||||
groupId: string;
|
groupId: string;
|
||||||
@ -421,6 +422,27 @@ export class DockviewGroupPanelModel
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _overwriteRenderContainer: OverlayRenderContainer | null = null;
|
||||||
|
|
||||||
|
set renderContainer(value: OverlayRenderContainer | null) {
|
||||||
|
this.panels.forEach((panel) => {
|
||||||
|
this.renderContainer.detatch(panel);
|
||||||
|
});
|
||||||
|
|
||||||
|
this._overwriteRenderContainer = value;
|
||||||
|
|
||||||
|
this.panels.forEach((panel) => {
|
||||||
|
this.rerender(panel);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get renderContainer(): OverlayRenderContainer {
|
||||||
|
return (
|
||||||
|
this._overwriteRenderContainer ??
|
||||||
|
this.accessor.overlayRenderContainer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
initialize(): void {
|
initialize(): void {
|
||||||
if (this.options.panels) {
|
if (this.options.panels) {
|
||||||
this.options.panels.forEach((panel) => {
|
this.options.panels.forEach((panel) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user