mirror of
https://github.com/mathuo/dockview
synced 2025-09-02 23:46:31 +00:00
feat: add additional methods and docs for floating groups
This commit is contained in:
parent
42b95e5f0a
commit
307780d15a
@ -5,6 +5,12 @@ import { DockviewGroupPanel } from '../../dockview/dockviewGroupPanel';
|
|||||||
|
|
||||||
describe('groupPanelApi', () => {
|
describe('groupPanelApi', () => {
|
||||||
test('title', () => {
|
test('title', () => {
|
||||||
|
const accessor: Partial<DockviewComponent> = {
|
||||||
|
onDidAddPanel: jest.fn(),
|
||||||
|
onDidRemovePanel: jest.fn(),
|
||||||
|
options: {},
|
||||||
|
};
|
||||||
|
|
||||||
const panelMock = jest.fn<DockviewPanel, []>(() => {
|
const panelMock = jest.fn<DockviewPanel, []>(() => {
|
||||||
return {
|
return {
|
||||||
update: jest.fn(),
|
update: jest.fn(),
|
||||||
@ -18,7 +24,11 @@ describe('groupPanelApi', () => {
|
|||||||
const panel = new panelMock();
|
const panel = new panelMock();
|
||||||
const group = new groupMock();
|
const group = new groupMock();
|
||||||
|
|
||||||
const cut = new DockviewPanelApiImpl(panel, group);
|
const cut = new DockviewPanelApiImpl(
|
||||||
|
panel,
|
||||||
|
group,
|
||||||
|
<DockviewComponent>accessor
|
||||||
|
);
|
||||||
|
|
||||||
cut.setTitle('test_title');
|
cut.setTitle('test_title');
|
||||||
expect(panel.setTitle).toBeCalledTimes(1);
|
expect(panel.setTitle).toBeCalledTimes(1);
|
||||||
@ -44,7 +54,8 @@ describe('groupPanelApi', () => {
|
|||||||
|
|
||||||
const cut = new DockviewPanelApiImpl(
|
const cut = new DockviewPanelApiImpl(
|
||||||
<IDockviewPanel>groupPanel,
|
<IDockviewPanel>groupPanel,
|
||||||
<DockviewGroupPanel>groupViewPanel
|
<DockviewGroupPanel>groupViewPanel,
|
||||||
|
<DockviewComponent>accessor
|
||||||
);
|
);
|
||||||
|
|
||||||
cut.updateParameters({ keyA: 'valueA' });
|
cut.updateParameters({ keyA: 'valueA' });
|
||||||
@ -73,7 +84,8 @@ describe('groupPanelApi', () => {
|
|||||||
|
|
||||||
const cut = new DockviewPanelApiImpl(
|
const cut = new DockviewPanelApiImpl(
|
||||||
<IDockviewPanel>groupPanel,
|
<IDockviewPanel>groupPanel,
|
||||||
<DockviewGroupPanel>groupViewPanel
|
<DockviewGroupPanel>groupViewPanel,
|
||||||
|
<DockviewComponent>accessor
|
||||||
);
|
);
|
||||||
|
|
||||||
let events = 0;
|
let events = 0;
|
||||||
|
@ -10,7 +10,7 @@ describe('groupDragHandler', () => {
|
|||||||
const groupMock = jest.fn<DockviewGroupPanel, []>(() => {
|
const groupMock = jest.fn<DockviewGroupPanel, []>(() => {
|
||||||
const partial: Partial<DockviewGroupPanel> = {
|
const partial: Partial<DockviewGroupPanel> = {
|
||||||
id: 'test_group_id',
|
id: 'test_group_id',
|
||||||
isFloating: false,
|
api: { isFloating: false } as any,
|
||||||
};
|
};
|
||||||
return partial as DockviewGroupPanel;
|
return partial as DockviewGroupPanel;
|
||||||
});
|
});
|
||||||
@ -48,7 +48,7 @@ describe('groupDragHandler', () => {
|
|||||||
|
|
||||||
const groupMock = jest.fn<DockviewGroupPanel, []>(() => {
|
const groupMock = jest.fn<DockviewGroupPanel, []>(() => {
|
||||||
const partial: Partial<DockviewGroupPanel> = {
|
const partial: Partial<DockviewGroupPanel> = {
|
||||||
isFloating: true,
|
api: { isFloating: true } as any,
|
||||||
};
|
};
|
||||||
return partial as DockviewGroupPanel;
|
return partial as DockviewGroupPanel;
|
||||||
});
|
});
|
||||||
@ -76,7 +76,7 @@ describe('groupDragHandler', () => {
|
|||||||
|
|
||||||
const groupMock = jest.fn<DockviewGroupPanel, []>(() => {
|
const groupMock = jest.fn<DockviewGroupPanel, []>(() => {
|
||||||
const partial: Partial<DockviewGroupPanel> = {
|
const partial: Partial<DockviewGroupPanel> = {
|
||||||
isFloating: false,
|
api: { isFloating: false } as any,
|
||||||
};
|
};
|
||||||
return partial as DockviewGroupPanel;
|
return partial as DockviewGroupPanel;
|
||||||
});
|
});
|
||||||
|
@ -39,7 +39,7 @@ describe('overlay', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('#1', () => {
|
test('that out-of-bounds dimensions are fixed', () => {
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
const content = document.createElement('div');
|
const content = document.createElement('div');
|
||||||
|
|
||||||
@ -77,6 +77,46 @@ describe('overlay', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('setBounds', () => {
|
||||||
|
const container = document.createElement('div');
|
||||||
|
const content = document.createElement('div');
|
||||||
|
|
||||||
|
document.body.appendChild(container);
|
||||||
|
container.appendChild(content);
|
||||||
|
|
||||||
|
const cut = new Overlay({
|
||||||
|
height: 1000,
|
||||||
|
width: 1000,
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
minimumInViewportWidth: 0,
|
||||||
|
minimumInViewportHeight: 0,
|
||||||
|
container,
|
||||||
|
content,
|
||||||
|
});
|
||||||
|
|
||||||
|
const element: HTMLElement = container.querySelector(
|
||||||
|
'.dv-resize-container'
|
||||||
|
)!;
|
||||||
|
expect(element).toBeTruthy();
|
||||||
|
|
||||||
|
jest.spyOn(element, 'getBoundingClientRect').mockImplementation(() => {
|
||||||
|
return { left: 300, top: 400, width: 1000, height: 1000 } as any;
|
||||||
|
});
|
||||||
|
jest.spyOn(container, 'getBoundingClientRect').mockImplementation(
|
||||||
|
() => {
|
||||||
|
return { left: 0, top: 0, width: 1000, height: 1000 } as any;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
cut.setBounds({ height: 100, width: 200, left: 300, top: 400 });
|
||||||
|
|
||||||
|
expect(element.style.height).toBe('100px');
|
||||||
|
expect(element.style.width).toBe('200px');
|
||||||
|
expect(element.style.left).toBe('300px');
|
||||||
|
expect(element.style.top).toBe('400px');
|
||||||
|
});
|
||||||
|
|
||||||
test('that the resize handles are added', () => {
|
test('that the resize handles are added', () => {
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
const content = document.createElement('div');
|
const content = document.createElement('div');
|
||||||
|
@ -478,7 +478,7 @@ describe('tabsContainer', () => {
|
|||||||
|
|
||||||
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
|
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
|
||||||
return (<Partial<DockviewGroupPanel>>{
|
return (<Partial<DockviewGroupPanel>>{
|
||||||
isFloating: false,
|
api: { isFloating: false } as any,
|
||||||
}) as DockviewGroupPanel;
|
}) as DockviewGroupPanel;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -506,10 +506,14 @@ describe('tabsContainer', () => {
|
|||||||
const eventPreventDefaultSpy = jest.spyOn(event, 'preventDefault');
|
const eventPreventDefaultSpy = jest.spyOn(event, 'preventDefault');
|
||||||
fireEvent(container, event);
|
fireEvent(container, event);
|
||||||
|
|
||||||
expect(accessor.addFloatingGroup).toBeCalledWith(groupPanel, {
|
expect(accessor.addFloatingGroup).toBeCalledWith(
|
||||||
x: 100,
|
groupPanel,
|
||||||
y: 60,
|
{
|
||||||
});
|
x: 100,
|
||||||
|
y: 60,
|
||||||
|
},
|
||||||
|
{ inDragMode: true }
|
||||||
|
);
|
||||||
expect(accessor.addFloatingGroup).toBeCalledTimes(1);
|
expect(accessor.addFloatingGroup).toBeCalledTimes(1);
|
||||||
expect(eventPreventDefaultSpy).toBeCalledTimes(1);
|
expect(eventPreventDefaultSpy).toBeCalledTimes(1);
|
||||||
|
|
||||||
@ -534,7 +538,7 @@ describe('tabsContainer', () => {
|
|||||||
|
|
||||||
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
|
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
|
||||||
return (<Partial<DockviewGroupPanel>>{
|
return (<Partial<DockviewGroupPanel>>{
|
||||||
isFloating: true,
|
api: { isFloating: true } as any,
|
||||||
}) as DockviewGroupPanel;
|
}) as DockviewGroupPanel;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -587,7 +591,7 @@ describe('tabsContainer', () => {
|
|||||||
|
|
||||||
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
|
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
|
||||||
return (<Partial<DockviewGroupPanel>>{
|
return (<Partial<DockviewGroupPanel>>{
|
||||||
isFloating: true,
|
api: { isFloating: true } as any,
|
||||||
}) as DockviewGroupPanel;
|
}) as DockviewGroupPanel;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2795,8 +2795,8 @@ describe('dockviewComponent', () => {
|
|||||||
floating: true,
|
floating: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeTruthy();
|
expect(panel2.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
|
|
||||||
@ -2807,8 +2807,8 @@ describe('dockviewComponent', () => {
|
|||||||
'right'
|
'right'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeFalsy();
|
expect(panel2.group.api.isFloating).toBeFalsy();
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
});
|
});
|
||||||
@ -2840,8 +2840,8 @@ describe('dockviewComponent', () => {
|
|||||||
floating: true,
|
floating: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeTruthy();
|
expect(panel2.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
|
|
||||||
@ -2852,8 +2852,8 @@ describe('dockviewComponent', () => {
|
|||||||
'center'
|
'center'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeFalsy();
|
expect(panel2.group.api.isFloating).toBeFalsy();
|
||||||
expect(dockview.groups.length).toBe(1);
|
expect(dockview.groups.length).toBe(1);
|
||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
});
|
});
|
||||||
@ -2891,9 +2891,9 @@ describe('dockviewComponent', () => {
|
|||||||
floating: true,
|
floating: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeTruthy();
|
expect(panel2.group.api.isFloating).toBeTruthy();
|
||||||
expect(panel3.group.model.isFloating).toBeTruthy();
|
expect(panel3.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(3);
|
expect(dockview.groups.length).toBe(3);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
|
|
||||||
@ -2904,9 +2904,9 @@ describe('dockviewComponent', () => {
|
|||||||
'center'
|
'center'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeTruthy();
|
expect(panel2.group.api.isFloating).toBeTruthy();
|
||||||
expect(panel3.group.model.isFloating).toBeTruthy();
|
expect(panel3.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
});
|
});
|
||||||
@ -2944,9 +2944,9 @@ describe('dockviewComponent', () => {
|
|||||||
position: { referencePanel: panel2 },
|
position: { referencePanel: panel2 },
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeTruthy();
|
expect(panel2.group.api.isFloating).toBeTruthy();
|
||||||
expect(panel3.group.model.isFloating).toBeTruthy();
|
expect(panel3.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
|
|
||||||
@ -2957,9 +2957,9 @@ describe('dockviewComponent', () => {
|
|||||||
'right'
|
'right'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeFalsy();
|
expect(panel2.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel3.group.model.isFloating).toBeFalsy();
|
expect(panel3.group.api.isFloating).toBeFalsy();
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
});
|
});
|
||||||
@ -2997,9 +2997,9 @@ describe('dockviewComponent', () => {
|
|||||||
position: { referencePanel: panel2 },
|
position: { referencePanel: panel2 },
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeTruthy();
|
expect(panel2.group.api.isFloating).toBeTruthy();
|
||||||
expect(panel3.group.model.isFloating).toBeTruthy();
|
expect(panel3.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
|
|
||||||
@ -3010,9 +3010,9 @@ describe('dockviewComponent', () => {
|
|||||||
'center'
|
'center'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeFalsy();
|
expect(panel2.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel3.group.model.isFloating).toBeFalsy();
|
expect(panel3.group.api.isFloating).toBeFalsy();
|
||||||
expect(dockview.groups.length).toBe(1);
|
expect(dockview.groups.length).toBe(1);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
});
|
});
|
||||||
@ -3056,10 +3056,10 @@ describe('dockviewComponent', () => {
|
|||||||
floating: true,
|
floating: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeTruthy();
|
expect(panel2.group.api.isFloating).toBeTruthy();
|
||||||
expect(panel3.group.model.isFloating).toBeTruthy();
|
expect(panel3.group.api.isFloating).toBeTruthy();
|
||||||
expect(panel4.group.model.isFloating).toBeTruthy();
|
expect(panel4.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(3);
|
expect(dockview.groups.length).toBe(3);
|
||||||
expect(dockview.panels.length).toBe(4);
|
expect(dockview.panels.length).toBe(4);
|
||||||
|
|
||||||
@ -3070,10 +3070,10 @@ describe('dockviewComponent', () => {
|
|||||||
'center'
|
'center'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeTruthy();
|
expect(panel2.group.api.isFloating).toBeTruthy();
|
||||||
expect(panel3.group.model.isFloating).toBeTruthy();
|
expect(panel3.group.api.isFloating).toBeTruthy();
|
||||||
expect(panel4.group.model.isFloating).toBeTruthy();
|
expect(panel4.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(4);
|
expect(dockview.panels.length).toBe(4);
|
||||||
});
|
});
|
||||||
@ -3105,8 +3105,8 @@ describe('dockviewComponent', () => {
|
|||||||
floating: true,
|
floating: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeTruthy();
|
expect(panel2.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
|
|
||||||
@ -3117,8 +3117,8 @@ describe('dockviewComponent', () => {
|
|||||||
'right'
|
'right'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeFalsy();
|
expect(panel2.group.api.isFloating).toBeFalsy();
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
});
|
});
|
||||||
@ -3150,8 +3150,8 @@ describe('dockviewComponent', () => {
|
|||||||
floating: true,
|
floating: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeTruthy();
|
expect(panel2.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
|
|
||||||
@ -3162,8 +3162,8 @@ describe('dockviewComponent', () => {
|
|||||||
'center'
|
'center'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeFalsy();
|
expect(panel2.group.api.isFloating).toBeFalsy();
|
||||||
expect(dockview.groups.length).toBe(1);
|
expect(dockview.groups.length).toBe(1);
|
||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
});
|
});
|
||||||
@ -3201,9 +3201,9 @@ describe('dockviewComponent', () => {
|
|||||||
floating: true,
|
floating: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeTruthy();
|
expect(panel2.group.api.isFloating).toBeTruthy();
|
||||||
expect(panel3.group.model.isFloating).toBeTruthy();
|
expect(panel3.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(3);
|
expect(dockview.groups.length).toBe(3);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
|
|
||||||
@ -3214,9 +3214,9 @@ describe('dockviewComponent', () => {
|
|||||||
'center'
|
'center'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeTruthy();
|
expect(panel2.group.api.isFloating).toBeTruthy();
|
||||||
expect(panel3.group.model.isFloating).toBeTruthy();
|
expect(panel3.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
});
|
});
|
||||||
@ -3254,9 +3254,9 @@ describe('dockviewComponent', () => {
|
|||||||
position: { referencePanel: panel2 },
|
position: { referencePanel: panel2 },
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeTruthy();
|
expect(panel2.group.api.isFloating).toBeTruthy();
|
||||||
expect(panel3.group.model.isFloating).toBeTruthy();
|
expect(panel3.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
|
|
||||||
@ -3267,9 +3267,9 @@ describe('dockviewComponent', () => {
|
|||||||
'right'
|
'right'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeFalsy();
|
expect(panel2.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel3.group.model.isFloating).toBeTruthy();
|
expect(panel3.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(3);
|
expect(dockview.groups.length).toBe(3);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
});
|
});
|
||||||
@ -3307,9 +3307,9 @@ describe('dockviewComponent', () => {
|
|||||||
position: { referencePanel: panel2 },
|
position: { referencePanel: panel2 },
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeTruthy();
|
expect(panel2.group.api.isFloating).toBeTruthy();
|
||||||
expect(panel3.group.model.isFloating).toBeTruthy();
|
expect(panel3.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
|
|
||||||
@ -3320,9 +3320,9 @@ describe('dockviewComponent', () => {
|
|||||||
'center'
|
'center'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeFalsy();
|
expect(panel2.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel3.group.model.isFloating).toBeTruthy();
|
expect(panel3.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
});
|
});
|
||||||
@ -3366,10 +3366,10 @@ describe('dockviewComponent', () => {
|
|||||||
floating: true,
|
floating: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeTruthy();
|
expect(panel2.group.api.isFloating).toBeTruthy();
|
||||||
expect(panel3.group.model.isFloating).toBeTruthy();
|
expect(panel3.group.api.isFloating).toBeTruthy();
|
||||||
expect(panel4.group.model.isFloating).toBeTruthy();
|
expect(panel4.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(3);
|
expect(dockview.groups.length).toBe(3);
|
||||||
expect(dockview.panels.length).toBe(4);
|
expect(dockview.panels.length).toBe(4);
|
||||||
|
|
||||||
@ -3380,10 +3380,10 @@ describe('dockviewComponent', () => {
|
|||||||
'center'
|
'center'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeTruthy();
|
expect(panel2.group.api.isFloating).toBeTruthy();
|
||||||
expect(panel3.group.model.isFloating).toBeTruthy();
|
expect(panel3.group.api.isFloating).toBeTruthy();
|
||||||
expect(panel4.group.model.isFloating).toBeTruthy();
|
expect(panel4.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(3);
|
expect(dockview.groups.length).toBe(3);
|
||||||
expect(dockview.panels.length).toBe(4);
|
expect(dockview.panels.length).toBe(4);
|
||||||
});
|
});
|
||||||
@ -3421,9 +3421,9 @@ describe('dockviewComponent', () => {
|
|||||||
floating: true,
|
floating: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeFalsy();
|
expect(panel2.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel3.group.model.isFloating).toBeTruthy();
|
expect(panel3.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(3);
|
expect(dockview.groups.length).toBe(3);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
|
|
||||||
@ -3434,9 +3434,9 @@ describe('dockviewComponent', () => {
|
|||||||
'center'
|
'center'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeTruthy();
|
expect(panel1.group.api.isFloating).toBeTruthy();
|
||||||
expect(panel2.group.model.isFloating).toBeFalsy();
|
expect(panel2.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel3.group.model.isFloating).toBeTruthy();
|
expect(panel3.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
});
|
});
|
||||||
@ -3473,9 +3473,9 @@ describe('dockviewComponent', () => {
|
|||||||
floating: true,
|
floating: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeFalsy();
|
expect(panel2.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel3.group.model.isFloating).toBeTruthy();
|
expect(panel3.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
|
|
||||||
@ -3486,9 +3486,9 @@ describe('dockviewComponent', () => {
|
|||||||
'center'
|
'center'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeTruthy();
|
expect(panel1.group.api.isFloating).toBeTruthy();
|
||||||
expect(panel2.group.model.isFloating).toBeFalsy();
|
expect(panel2.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel3.group.model.isFloating).toBeTruthy();
|
expect(panel3.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
});
|
});
|
||||||
@ -3526,9 +3526,9 @@ describe('dockviewComponent', () => {
|
|||||||
floating: true,
|
floating: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeFalsy();
|
expect(panel2.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel3.group.model.isFloating).toBeTruthy();
|
expect(panel3.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(3);
|
expect(dockview.groups.length).toBe(3);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
|
|
||||||
@ -3539,9 +3539,9 @@ describe('dockviewComponent', () => {
|
|||||||
'center'
|
'center'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeTruthy();
|
expect(panel1.group.api.isFloating).toBeTruthy();
|
||||||
expect(panel2.group.model.isFloating).toBeFalsy();
|
expect(panel2.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel3.group.model.isFloating).toBeTruthy();
|
expect(panel3.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
});
|
});
|
||||||
@ -3578,9 +3578,9 @@ describe('dockviewComponent', () => {
|
|||||||
floating: true,
|
floating: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeFalsy();
|
expect(panel2.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel3.group.model.isFloating).toBeTruthy();
|
expect(panel3.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
|
|
||||||
@ -3591,9 +3591,9 @@ describe('dockviewComponent', () => {
|
|||||||
'center'
|
'center'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeTruthy();
|
expect(panel1.group.api.isFloating).toBeTruthy();
|
||||||
expect(panel2.group.model.isFloating).toBeTruthy();
|
expect(panel2.group.api.isFloating).toBeTruthy();
|
||||||
expect(panel3.group.model.isFloating).toBeTruthy();
|
expect(panel3.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(1);
|
expect(dockview.groups.length).toBe(1);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
});
|
});
|
||||||
@ -3625,15 +3625,15 @@ describe('dockviewComponent', () => {
|
|||||||
position: { direction: 'right' },
|
position: { direction: 'right' },
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeFalsy();
|
expect(panel2.group.api.isFloating).toBeFalsy();
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
|
|
||||||
dockview.addFloatingGroup(panel2);
|
dockview.addFloatingGroup(panel2);
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeTruthy();
|
expect(panel2.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
});
|
});
|
||||||
@ -3664,15 +3664,15 @@ describe('dockviewComponent', () => {
|
|||||||
component: 'default',
|
component: 'default',
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeFalsy();
|
expect(panel2.group.api.isFloating).toBeFalsy();
|
||||||
expect(dockview.groups.length).toBe(1);
|
expect(dockview.groups.length).toBe(1);
|
||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
|
|
||||||
dockview.addFloatingGroup(panel2);
|
dockview.addFloatingGroup(panel2);
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeTruthy();
|
expect(panel2.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
});
|
});
|
||||||
@ -3704,15 +3704,15 @@ describe('dockviewComponent', () => {
|
|||||||
position: { direction: 'right' },
|
position: { direction: 'right' },
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeFalsy();
|
expect(panel2.group.api.isFloating).toBeFalsy();
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
|
|
||||||
dockview.addFloatingGroup(panel2.group);
|
dockview.addFloatingGroup(panel2.group);
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeTruthy();
|
expect(panel2.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
});
|
});
|
||||||
@ -3743,15 +3743,15 @@ describe('dockviewComponent', () => {
|
|||||||
component: 'default',
|
component: 'default',
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeFalsy();
|
expect(panel1.group.api.isFloating).toBeFalsy();
|
||||||
expect(panel2.group.model.isFloating).toBeFalsy();
|
expect(panel2.group.api.isFloating).toBeFalsy();
|
||||||
expect(dockview.groups.length).toBe(1);
|
expect(dockview.groups.length).toBe(1);
|
||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
|
|
||||||
dockview.addFloatingGroup(panel2.group);
|
dockview.addFloatingGroup(panel2.group);
|
||||||
|
|
||||||
expect(panel1.group.model.isFloating).toBeTruthy();
|
expect(panel1.group.api.isFloating).toBeTruthy();
|
||||||
expect(panel2.group.model.isFloating).toBeTruthy();
|
expect(panel2.group.api.isFloating).toBeTruthy();
|
||||||
expect(dockview.groups.length).toBe(1);
|
expect(dockview.groups.length).toBe(1);
|
||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
});
|
});
|
||||||
|
21
packages/dockview-core/src/__tests__/dom.spec.ts
Normal file
21
packages/dockview-core/src/__tests__/dom.spec.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { quasiDefaultPrevented, quasiPreventDefault } from '../dom';
|
||||||
|
|
||||||
|
describe('dom', () => {
|
||||||
|
test('quasiPreventDefault', () => {
|
||||||
|
const event = new Event('myevent');
|
||||||
|
expect((event as any)['dv-quasiPreventDefault']).toBeUndefined();
|
||||||
|
quasiPreventDefault(event);
|
||||||
|
expect((event as any)['dv-quasiPreventDefault']).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('quasiDefaultPrevented', () => {
|
||||||
|
const event = new Event('myevent');
|
||||||
|
expect(quasiDefaultPrevented(event)).toBeFalsy();
|
||||||
|
|
||||||
|
(event as any)['dv-quasiPreventDefault'] = false;
|
||||||
|
expect(quasiDefaultPrevented(event)).toBeFalsy();
|
||||||
|
|
||||||
|
(event as any)['dv-quasiPreventDefault'] = true;
|
||||||
|
expect(quasiDefaultPrevented(event)).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -435,7 +435,7 @@ export class DockviewApi implements CommonApi<SerializedDockview> {
|
|||||||
return this.component.addPanel(options);
|
return this.component.addPanel(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
addGroup(options?: AddGroupOptions): IDockviewGroupPanel {
|
addGroup(options?: AddGroupOptions): DockviewGroupPanel {
|
||||||
return this.component.addGroup(options);
|
return this.component.addGroup(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -459,6 +459,13 @@ export class DockviewApi implements CommonApi<SerializedDockview> {
|
|||||||
return this.component.getPanel(id);
|
return this.component.getPanel(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addFloatingGroup(
|
||||||
|
item: IDockviewPanel | DockviewGroupPanel,
|
||||||
|
coord?: { x: number; y: number }
|
||||||
|
): void {
|
||||||
|
return this.component.addFloatingGroup(item, coord);
|
||||||
|
}
|
||||||
|
|
||||||
fromJSON(data: SerializedDockview): void {
|
fromJSON(data: SerializedDockview): void {
|
||||||
this.component.fromJSON(data);
|
this.component.fromJSON(data);
|
||||||
}
|
}
|
||||||
|
54
packages/dockview-core/src/api/dockviewGroupPanelApi.ts
Normal file
54
packages/dockview-core/src/api/dockviewGroupPanelApi.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { Position } from '../dnd/droptarget';
|
||||||
|
import { DockviewComponent } from '../dockview/dockviewComponent';
|
||||||
|
import { DockviewGroupPanel } from '../dockview/dockviewGroupPanel';
|
||||||
|
import { Emitter, Event } from '../events';
|
||||||
|
import { GridviewPanelApi, GridviewPanelApiImpl } from './gridviewPanelApi';
|
||||||
|
|
||||||
|
export interface DockviewGroupPanelApi extends GridviewPanelApi {
|
||||||
|
readonly onDidFloatingStateChange: Event<DockviewGroupPanelFloatingChangeEvent>;
|
||||||
|
readonly isFloating: boolean;
|
||||||
|
moveTo(options: { group: DockviewGroupPanel; position?: Position }): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DockviewGroupPanelFloatingChangeEvent {
|
||||||
|
readonly isFloating: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl {
|
||||||
|
private _group: DockviewGroupPanel | undefined;
|
||||||
|
|
||||||
|
readonly _onDidFloatingStateChange =
|
||||||
|
new Emitter<DockviewGroupPanelFloatingChangeEvent>();
|
||||||
|
readonly onDidFloatingStateChange: Event<DockviewGroupPanelFloatingChangeEvent> =
|
||||||
|
this._onDidFloatingStateChange.event;
|
||||||
|
|
||||||
|
get isFloating() {
|
||||||
|
if (!this._group) {
|
||||||
|
throw new Error(`DockviewGroupPanelApiImpl not initialized`);
|
||||||
|
}
|
||||||
|
return this._group.model.isFloating;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(id: string, private readonly accessor: DockviewComponent) {
|
||||||
|
super(id);
|
||||||
|
|
||||||
|
this.addDisposables(this._onDidFloatingStateChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
moveTo(options: { group: DockviewGroupPanel; position?: Position }): void {
|
||||||
|
if (!this._group) {
|
||||||
|
throw new Error(`DockviewGroupPanelApiImpl not initialized`);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.accessor.moveGroupOrPanel(
|
||||||
|
options.group,
|
||||||
|
this._group.id,
|
||||||
|
undefined,
|
||||||
|
options.position ?? 'center'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize(group: DockviewGroupPanel): void {
|
||||||
|
this._group = group;
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,8 @@ import { GridviewPanelApiImpl, GridviewPanelApi } from './gridviewPanelApi';
|
|||||||
import { DockviewGroupPanel } from '../dockview/dockviewGroupPanel';
|
import { DockviewGroupPanel } from '../dockview/dockviewGroupPanel';
|
||||||
import { MutableDisposable } from '../lifecycle';
|
import { MutableDisposable } from '../lifecycle';
|
||||||
import { IDockviewPanel } from '../dockview/dockviewPanel';
|
import { IDockviewPanel } from '../dockview/dockviewPanel';
|
||||||
|
import { DockviewComponent } from '../dockview/dockviewComponent';
|
||||||
|
import { Position } from '../dnd/droptarget';
|
||||||
|
|
||||||
export interface TitleEvent {
|
export interface TitleEvent {
|
||||||
readonly title: string;
|
readonly title: string;
|
||||||
@ -24,6 +26,11 @@ export interface DockviewPanelApi
|
|||||||
readonly onDidGroupChange: Event<void>;
|
readonly onDidGroupChange: Event<void>;
|
||||||
close(): void;
|
close(): void;
|
||||||
setTitle(title: string): void;
|
setTitle(title: string): void;
|
||||||
|
moveTo(options: {
|
||||||
|
group: DockviewGroupPanel;
|
||||||
|
position?: Position;
|
||||||
|
index?: number;
|
||||||
|
}): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DockviewPanelApiImpl
|
export class DockviewPanelApiImpl
|
||||||
@ -73,7 +80,11 @@ export class DockviewPanelApiImpl
|
|||||||
return this._group;
|
return this._group;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(private panel: IDockviewPanel, group: DockviewGroupPanel) {
|
constructor(
|
||||||
|
private panel: IDockviewPanel,
|
||||||
|
group: DockviewGroupPanel,
|
||||||
|
private readonly accessor: DockviewComponent
|
||||||
|
) {
|
||||||
super(panel.id);
|
super(panel.id);
|
||||||
|
|
||||||
this.initialize(panel);
|
this.initialize(panel);
|
||||||
@ -88,11 +99,25 @@ export class DockviewPanelApiImpl
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public setTitle(title: string): void {
|
moveTo(options: {
|
||||||
|
group: DockviewGroupPanel;
|
||||||
|
position?: Position;
|
||||||
|
index?: number;
|
||||||
|
}): void {
|
||||||
|
this.accessor.moveGroupOrPanel(
|
||||||
|
options.group,
|
||||||
|
this._group.id,
|
||||||
|
this.panel.id,
|
||||||
|
options.position ?? 'center',
|
||||||
|
options.index
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
setTitle(title: string): void {
|
||||||
this.panel.setTitle(title);
|
this.panel.setTitle(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
public close(): void {
|
close(): void {
|
||||||
this.group.model.closePanel(this.panel);
|
this.group.model.closePanel(this.panel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,11 +23,11 @@ export class GroupDragHandler extends DragHandler {
|
|||||||
'mousedown',
|
'mousedown',
|
||||||
(e) => {
|
(e) => {
|
||||||
if (e.shiftKey) {
|
if (e.shiftKey) {
|
||||||
/**
|
/**
|
||||||
* You cannot call e.preventDefault() because that will prevent drag events from firing
|
* You cannot call e.preventDefault() because that will prevent drag events from firing
|
||||||
* but we also need to stop any group overlay drag events from occuring
|
* but we also need to stop any group overlay drag events from occuring
|
||||||
* Use a custom event marker that can be checked by the overlay drag events
|
* Use a custom event marker that can be checked by the overlay drag events
|
||||||
*/
|
*/
|
||||||
quasiPreventDefault(e);
|
quasiPreventDefault(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -37,7 +37,7 @@ export class GroupDragHandler extends DragHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override isCancelled(_event: DragEvent): boolean {
|
override isCancelled(_event: DragEvent): boolean {
|
||||||
if (this.group.isFloating && !_event.shiftKey) {
|
if (this.group.api.isFloating && !_event.shiftKey) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -7,7 +7,6 @@ import {
|
|||||||
} from '../events';
|
} from '../events';
|
||||||
import { CompositeDisposable, MutableDisposable } from '../lifecycle';
|
import { CompositeDisposable, MutableDisposable } from '../lifecycle';
|
||||||
import { clamp } from '../math';
|
import { clamp } from '../math';
|
||||||
import { getPaneData, getPanelData } from './dataTransfer';
|
|
||||||
|
|
||||||
const bringElementToFront = (() => {
|
const bringElementToFront = (() => {
|
||||||
let previous: HTMLElement | null = null;
|
let previous: HTMLElement | null = null;
|
||||||
@ -66,6 +65,30 @@ export class Overlay extends CompositeDisposable {
|
|||||||
this.renderWithinBoundaryConditions();
|
this.renderWithinBoundaryConditions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setBounds(
|
||||||
|
bounds: Partial<{
|
||||||
|
height: number;
|
||||||
|
width: number;
|
||||||
|
top: number;
|
||||||
|
left: number;
|
||||||
|
}>
|
||||||
|
): void {
|
||||||
|
if (typeof bounds.height === 'number') {
|
||||||
|
this._element.style.height = `${bounds.height}px`;
|
||||||
|
}
|
||||||
|
if (typeof bounds.width === 'number') {
|
||||||
|
this._element.style.width = `${bounds.width}px`;
|
||||||
|
}
|
||||||
|
if (typeof bounds.top === 'number') {
|
||||||
|
this._element.style.top = `${bounds.top}px`;
|
||||||
|
}
|
||||||
|
if (typeof bounds.left === 'number') {
|
||||||
|
this._element.style.left = `${bounds.left}px`;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.renderWithinBoundaryConditions();
|
||||||
|
}
|
||||||
|
|
||||||
toJSON(): { top: number; left: number; height: number; width: number } {
|
toJSON(): { top: number; left: number; height: number; width: number } {
|
||||||
const container = this.options.container.getBoundingClientRect();
|
const container = this.options.container.getBoundingClientRect();
|
||||||
const element = this._element.getBoundingClientRect();
|
const element = this._element.getBoundingClientRect();
|
||||||
@ -78,6 +101,173 @@ export class Overlay extends CompositeDisposable {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderWithinBoundaryConditions(): void {
|
||||||
|
const containerRect = this.options.container.getBoundingClientRect();
|
||||||
|
const overlayRect = this._element.getBoundingClientRect();
|
||||||
|
|
||||||
|
// a minimum width of minimumViewportWidth must be inside the viewport
|
||||||
|
const xOffset = Math.max(
|
||||||
|
0,
|
||||||
|
overlayRect.width - this.options.minimumInViewportWidth
|
||||||
|
);
|
||||||
|
|
||||||
|
// a minimum height of minimumViewportHeight must be inside the viewport
|
||||||
|
const yOffset = Math.max(
|
||||||
|
0,
|
||||||
|
overlayRect.height - this.options.minimumInViewportHeight
|
||||||
|
);
|
||||||
|
|
||||||
|
const left = clamp(
|
||||||
|
overlayRect.left - containerRect.left,
|
||||||
|
-xOffset,
|
||||||
|
Math.max(0, containerRect.width - overlayRect.width + xOffset)
|
||||||
|
);
|
||||||
|
|
||||||
|
const top = clamp(
|
||||||
|
overlayRect.top - containerRect.top,
|
||||||
|
-yOffset,
|
||||||
|
Math.max(0, containerRect.height - overlayRect.height + yOffset)
|
||||||
|
);
|
||||||
|
|
||||||
|
this._element.style.left = `${left}px`;
|
||||||
|
this._element.style.top = `${top}px`;
|
||||||
|
}
|
||||||
|
|
||||||
|
setupDrag(
|
||||||
|
dragTarget: HTMLElement,
|
||||||
|
options: { inDragMode: boolean } = { inDragMode: false }
|
||||||
|
): void {
|
||||||
|
const move = new MutableDisposable();
|
||||||
|
|
||||||
|
const track = () => {
|
||||||
|
let offset: { x: number; y: number } | null = null;
|
||||||
|
|
||||||
|
move.value = new CompositeDisposable(
|
||||||
|
addDisposableWindowListener(window, 'mousemove', (e) => {
|
||||||
|
const containerRect =
|
||||||
|
this.options.container.getBoundingClientRect();
|
||||||
|
const x = e.clientX - containerRect.left;
|
||||||
|
const y = e.clientY - containerRect.top;
|
||||||
|
|
||||||
|
toggleClass(
|
||||||
|
this._element,
|
||||||
|
'dv-resize-container-dragging',
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
const overlayRect = this._element.getBoundingClientRect();
|
||||||
|
if (offset === null) {
|
||||||
|
offset = {
|
||||||
|
x: e.clientX - overlayRect.left,
|
||||||
|
y: e.clientY - overlayRect.top,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const xOffset = Math.max(
|
||||||
|
0,
|
||||||
|
overlayRect.width - this.options.minimumInViewportWidth
|
||||||
|
);
|
||||||
|
const yOffset = Math.max(
|
||||||
|
0,
|
||||||
|
overlayRect.height -
|
||||||
|
this.options.minimumInViewportHeight
|
||||||
|
);
|
||||||
|
|
||||||
|
const left = clamp(
|
||||||
|
x - offset.x,
|
||||||
|
-xOffset,
|
||||||
|
Math.max(
|
||||||
|
0,
|
||||||
|
containerRect.width - overlayRect.width + xOffset
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
const top = clamp(
|
||||||
|
y - offset.y,
|
||||||
|
-yOffset,
|
||||||
|
Math.max(
|
||||||
|
0,
|
||||||
|
containerRect.height - overlayRect.height + yOffset
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
this._element.style.left = `${left}px`;
|
||||||
|
this._element.style.top = `${top}px`;
|
||||||
|
}),
|
||||||
|
addDisposableWindowListener(window, 'mouseup', () => {
|
||||||
|
toggleClass(
|
||||||
|
this._element,
|
||||||
|
'dv-resize-container-dragging',
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
move.dispose();
|
||||||
|
this._onDidChange.fire();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.addDisposables(
|
||||||
|
move,
|
||||||
|
addDisposableListener(dragTarget, 'mousedown', (event) => {
|
||||||
|
if (event.defaultPrevented) {
|
||||||
|
event.preventDefault();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if somebody has marked this event then treat as a defaultPrevented
|
||||||
|
// without actually calling event.preventDefault()
|
||||||
|
if (quasiDefaultPrevented(event)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
track();
|
||||||
|
}),
|
||||||
|
addDisposableListener(
|
||||||
|
this.options.content,
|
||||||
|
'mousedown',
|
||||||
|
(event) => {
|
||||||
|
if (event.defaultPrevented) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if somebody has marked this event then treat as a defaultPrevented
|
||||||
|
// without actually calling event.preventDefault()
|
||||||
|
if (quasiDefaultPrevented(event)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.shiftKey) {
|
||||||
|
track();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
addDisposableListener(
|
||||||
|
this.options.content,
|
||||||
|
'mousedown',
|
||||||
|
() => {
|
||||||
|
bringElementToFront(this._element);
|
||||||
|
},
|
||||||
|
true
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
bringElementToFront(this._element);
|
||||||
|
|
||||||
|
if (options.inDragMode) {
|
||||||
|
track();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private setupOverlay(): void {
|
||||||
|
this._element.style.height = `${this.options.height}px`;
|
||||||
|
this._element.style.width = `${this.options.width}px`;
|
||||||
|
this._element.style.left = `${this.options.left}px`;
|
||||||
|
this._element.style.top = `${this.options.top}px`;
|
||||||
|
|
||||||
|
this._element.className = 'dv-resize-container';
|
||||||
|
}
|
||||||
|
|
||||||
private setupResize(
|
private setupResize(
|
||||||
direction:
|
direction:
|
||||||
| 'top'
|
| 'top'
|
||||||
@ -252,173 +442,6 @@ export class Overlay extends CompositeDisposable {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private setupOverlay(): void {
|
|
||||||
this._element.style.height = `${this.options.height}px`;
|
|
||||||
this._element.style.width = `${this.options.width}px`;
|
|
||||||
this._element.style.left = `${this.options.left}px`;
|
|
||||||
this._element.style.top = `${this.options.top}px`;
|
|
||||||
|
|
||||||
this._element.className = 'dv-resize-container';
|
|
||||||
}
|
|
||||||
|
|
||||||
setupDrag(
|
|
||||||
dragTarget: HTMLElement,
|
|
||||||
options: { inDragMode: boolean } = { inDragMode: false }
|
|
||||||
): void {
|
|
||||||
const move = new MutableDisposable();
|
|
||||||
|
|
||||||
const track = () => {
|
|
||||||
let offset: { x: number; y: number } | null = null;
|
|
||||||
|
|
||||||
move.value = new CompositeDisposable(
|
|
||||||
addDisposableWindowListener(window, 'mousemove', (e) => {
|
|
||||||
const containerRect =
|
|
||||||
this.options.container.getBoundingClientRect();
|
|
||||||
const x = e.clientX - containerRect.left;
|
|
||||||
const y = e.clientY - containerRect.top;
|
|
||||||
|
|
||||||
toggleClass(
|
|
||||||
this._element,
|
|
||||||
'dv-resize-container-dragging',
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
const overlayRect = this._element.getBoundingClientRect();
|
|
||||||
if (offset === null) {
|
|
||||||
offset = {
|
|
||||||
x: e.clientX - overlayRect.left,
|
|
||||||
y: e.clientY - overlayRect.top,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const xOffset = Math.max(
|
|
||||||
0,
|
|
||||||
overlayRect.width - this.options.minimumInViewportWidth
|
|
||||||
);
|
|
||||||
const yOffset = Math.max(
|
|
||||||
0,
|
|
||||||
overlayRect.height -
|
|
||||||
this.options.minimumInViewportHeight
|
|
||||||
);
|
|
||||||
|
|
||||||
const left = clamp(
|
|
||||||
x - offset.x,
|
|
||||||
-xOffset,
|
|
||||||
Math.max(
|
|
||||||
0,
|
|
||||||
containerRect.width - overlayRect.width + xOffset
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
const top = clamp(
|
|
||||||
y - offset.y,
|
|
||||||
-yOffset,
|
|
||||||
Math.max(
|
|
||||||
0,
|
|
||||||
containerRect.height - overlayRect.height + yOffset
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
this._element.style.left = `${left}px`;
|
|
||||||
this._element.style.top = `${top}px`;
|
|
||||||
}),
|
|
||||||
addDisposableWindowListener(window, 'mouseup', () => {
|
|
||||||
toggleClass(
|
|
||||||
this._element,
|
|
||||||
'dv-resize-container-dragging',
|
|
||||||
false
|
|
||||||
);
|
|
||||||
|
|
||||||
move.dispose();
|
|
||||||
this._onDidChange.fire();
|
|
||||||
})
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.addDisposables(
|
|
||||||
move,
|
|
||||||
addDisposableListener(dragTarget, 'mousedown', (event) => {
|
|
||||||
if (event.defaultPrevented) {
|
|
||||||
event.preventDefault();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if somebody has marked this event then treat as a defaultPrevented
|
|
||||||
// without actually calling event.preventDefault()
|
|
||||||
if (quasiDefaultPrevented(event)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
track();
|
|
||||||
}),
|
|
||||||
addDisposableListener(
|
|
||||||
this.options.content,
|
|
||||||
'mousedown',
|
|
||||||
(event) => {
|
|
||||||
if (event.defaultPrevented) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if somebody has marked this event then treat as a defaultPrevented
|
|
||||||
// without actually calling event.preventDefault()
|
|
||||||
if (quasiDefaultPrevented(event)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.shiftKey) {
|
|
||||||
track();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
),
|
|
||||||
addDisposableListener(
|
|
||||||
this.options.content,
|
|
||||||
'mousedown',
|
|
||||||
() => {
|
|
||||||
bringElementToFront(this._element);
|
|
||||||
},
|
|
||||||
true
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
bringElementToFront(this._element);
|
|
||||||
|
|
||||||
if (options.inDragMode) {
|
|
||||||
track();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
renderWithinBoundaryConditions(): void {
|
|
||||||
const containerRect = this.options.container.getBoundingClientRect();
|
|
||||||
const overlayRect = this._element.getBoundingClientRect();
|
|
||||||
|
|
||||||
// a minimum width of minimumViewportWidth must be inside the viewport
|
|
||||||
const xOffset = Math.max(
|
|
||||||
0,
|
|
||||||
overlayRect.width - this.options.minimumInViewportWidth
|
|
||||||
);
|
|
||||||
|
|
||||||
// a minimum height of minimumViewportHeight must be inside the viewport
|
|
||||||
const yOffset = Math.max(
|
|
||||||
0,
|
|
||||||
overlayRect.height - this.options.minimumInViewportHeight
|
|
||||||
);
|
|
||||||
|
|
||||||
const left = clamp(
|
|
||||||
this.options.left,
|
|
||||||
-xOffset,
|
|
||||||
Math.max(0, containerRect.width - overlayRect.width + xOffset)
|
|
||||||
);
|
|
||||||
|
|
||||||
const top = clamp(
|
|
||||||
this.options.top,
|
|
||||||
-yOffset,
|
|
||||||
Math.max(0, containerRect.height - overlayRect.height + yOffset)
|
|
||||||
);
|
|
||||||
|
|
||||||
this._element.style.left = `${left}px`;
|
|
||||||
this._element.style.top = `${top}px`;
|
|
||||||
}
|
|
||||||
|
|
||||||
override dispose(): void {
|
override dispose(): void {
|
||||||
this._element.remove();
|
this._element.remove();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
|
@ -197,7 +197,7 @@ export class TabsContainer
|
|||||||
if (
|
if (
|
||||||
isFloatingGroupsEnabled &&
|
isFloatingGroupsEnabled &&
|
||||||
event.shiftKey &&
|
event.shiftKey &&
|
||||||
!this.group.isFloating
|
!this.group.api.isFloating
|
||||||
) {
|
) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
@ -206,10 +206,14 @@ export class TabsContainer
|
|||||||
const { top: rootTop, left: rootLeft } =
|
const { top: rootTop, left: rootLeft } =
|
||||||
this.accessor.element.getBoundingClientRect();
|
this.accessor.element.getBoundingClientRect();
|
||||||
|
|
||||||
this.accessor.addFloatingGroup(this.group, {
|
this.accessor.addFloatingGroup(
|
||||||
x: left - rootLeft + 20,
|
this.group,
|
||||||
y: top - rootTop + 20,
|
{
|
||||||
});
|
x: left - rootLeft + 20,
|
||||||
|
y: top - rootTop + 20,
|
||||||
|
},
|
||||||
|
{ inDragMode: true }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
@ -302,10 +306,14 @@ export class TabsContainer
|
|||||||
const { top: rootTop, left: rootLeft } =
|
const { top: rootTop, left: rootLeft } =
|
||||||
this.accessor.element.getBoundingClientRect();
|
this.accessor.element.getBoundingClientRect();
|
||||||
|
|
||||||
this.accessor.addFloatingGroup(panel as DockviewPanel, {
|
this.accessor.addFloatingGroup(
|
||||||
x: left - rootLeft,
|
panel as DockviewPanel,
|
||||||
y: top - rootTop,
|
{
|
||||||
});
|
x: left - rootLeft,
|
||||||
|
y: top - rootTop,
|
||||||
|
},
|
||||||
|
{ inDragMode: true }
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { GroupviewPanelState } from './types';
|
import { GroupviewPanelState } from './types';
|
||||||
import { DockviewGroupPanel } from './dockviewGroupPanel';
|
import { DockviewGroupPanel } from './dockviewGroupPanel';
|
||||||
import { DockviewPanel, IDockviewPanel } from './dockviewPanel';
|
import { DockviewPanel, IDockviewPanel } from './dockviewPanel';
|
||||||
import { IDockviewComponent } from './dockviewComponent';
|
import { DockviewComponent } from './dockviewComponent';
|
||||||
import { DockviewPanelModel } from './dockviewPanelModel';
|
import { DockviewPanelModel } from './dockviewPanelModel';
|
||||||
import { DockviewApi } from '../api/component.api';
|
import { DockviewApi } from '../api/component.api';
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ interface LegacyState extends GroupviewPanelState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class DefaultDockviewDeserialzier implements IPanelDeserializer {
|
export class DefaultDockviewDeserialzier implements IPanelDeserializer {
|
||||||
constructor(private readonly layout: IDockviewComponent) {}
|
constructor(private readonly layout: DockviewComponent) {}
|
||||||
|
|
||||||
public fromJSON(
|
public fromJSON(
|
||||||
panelData: GroupviewPanelState,
|
panelData: GroupviewPanelState,
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
left: 0px;
|
left: 0px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
z-index: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import {
|
|||||||
import { directionToPosition, Droptarget, Position } from '../dnd/droptarget';
|
import { directionToPosition, Droptarget, Position } from '../dnd/droptarget';
|
||||||
import { tail, sequenceEquals, remove } from '../array';
|
import { tail, sequenceEquals, remove } from '../array';
|
||||||
import { DockviewPanel, IDockviewPanel } from './dockviewPanel';
|
import { DockviewPanel, IDockviewPanel } from './dockviewPanel';
|
||||||
import { CompositeDisposable, IDisposable } from '../lifecycle';
|
import { CompositeDisposable } from '../lifecycle';
|
||||||
import { Event, Emitter } from '../events';
|
import { Event, Emitter } from '../events';
|
||||||
import { Watermark } from './components/watermark/watermark';
|
import { Watermark } from './components/watermark/watermark';
|
||||||
import {
|
import {
|
||||||
@ -41,11 +41,15 @@ import {
|
|||||||
GroupPanelViewState,
|
GroupPanelViewState,
|
||||||
GroupviewDropEvent,
|
GroupviewDropEvent,
|
||||||
} from './dockviewGroupPanelModel';
|
} from './dockviewGroupPanelModel';
|
||||||
import { DockviewGroupPanel, IDockviewGroupPanel } from './dockviewGroupPanel';
|
import { DockviewGroupPanel } from './dockviewGroupPanel';
|
||||||
import { DockviewPanelModel } from './dockviewPanelModel';
|
import { DockviewPanelModel } from './dockviewPanelModel';
|
||||||
import { getPanelData } from '../dnd/dataTransfer';
|
import { getPanelData } from '../dnd/dataTransfer';
|
||||||
import { Overlay } from '../dnd/overlay';
|
import { Overlay } from '../dnd/overlay';
|
||||||
import { toggleClass } from '../dom';
|
import { toggleClass } from '../dom';
|
||||||
|
import {
|
||||||
|
DockviewFloatingGroupPanel,
|
||||||
|
IDockviewFloatingGroupPanel,
|
||||||
|
} from './dockviewFloatingGroupPanel';
|
||||||
|
|
||||||
export interface PanelReference {
|
export interface PanelReference {
|
||||||
update: (event: { params: { [key: string]: any } }) => void;
|
update: (event: { params: { [key: string]: any } }) => void;
|
||||||
@ -92,6 +96,7 @@ export interface IDockviewComponent extends IBaseGrid<DockviewGroupPanel> {
|
|||||||
readonly activePanel: IDockviewPanel | undefined;
|
readonly activePanel: IDockviewPanel | undefined;
|
||||||
readonly totalPanels: number;
|
readonly totalPanels: number;
|
||||||
readonly panels: IDockviewPanel[];
|
readonly panels: IDockviewPanel[];
|
||||||
|
readonly floatingGroups: IDockviewFloatingGroupPanel[];
|
||||||
readonly onDidDrop: Event<DockviewDropEvent>;
|
readonly onDidDrop: Event<DockviewDropEvent>;
|
||||||
readonly orientation: Orientation;
|
readonly orientation: Orientation;
|
||||||
updateOptions(options: DockviewComponentUpdateOptions): void;
|
updateOptions(options: DockviewComponentUpdateOptions): void;
|
||||||
@ -110,7 +115,7 @@ export interface IDockviewComponent extends IBaseGrid<DockviewGroupPanel> {
|
|||||||
getGroupPanel: (id: string) => IDockviewPanel | undefined;
|
getGroupPanel: (id: string) => IDockviewPanel | undefined;
|
||||||
createWatermarkComponent(): IWatermarkRenderer;
|
createWatermarkComponent(): IWatermarkRenderer;
|
||||||
// lifecycle
|
// lifecycle
|
||||||
addGroup(options?: AddGroupOptions): IDockviewGroupPanel;
|
addGroup(options?: AddGroupOptions): DockviewGroupPanel;
|
||||||
closeAllGroups(): void;
|
closeAllGroups(): void;
|
||||||
// events
|
// events
|
||||||
moveToNext(options?: MovementOptions): void;
|
moveToNext(options?: MovementOptions): void;
|
||||||
@ -159,11 +164,7 @@ export class DockviewComponent
|
|||||||
readonly onDidActivePanelChange: Event<IDockviewPanel | undefined> =
|
readonly onDidActivePanelChange: Event<IDockviewPanel | undefined> =
|
||||||
this._onDidActivePanelChange.event;
|
this._onDidActivePanelChange.event;
|
||||||
|
|
||||||
private readonly floatingGroups: {
|
readonly floatingGroups: DockviewFloatingGroupPanel[] = [];
|
||||||
instance: DockviewGroupPanel;
|
|
||||||
disposable: IDisposable;
|
|
||||||
overlay: Overlay;
|
|
||||||
}[] = [];
|
|
||||||
|
|
||||||
get orientation(): Orientation {
|
get orientation(): Orientation {
|
||||||
return this.gridview.orientation;
|
return this.gridview.orientation;
|
||||||
@ -306,7 +307,7 @@ export class DockviewComponent
|
|||||||
addFloatingGroup(
|
addFloatingGroup(
|
||||||
item: DockviewPanel | DockviewGroupPanel,
|
item: DockviewPanel | DockviewGroupPanel,
|
||||||
coord?: { x?: number; y?: number; height?: number; width?: number },
|
coord?: { x?: number; y?: number; height?: number; width?: number },
|
||||||
options?: { skipRemoveGroup: boolean; inDragMode: boolean }
|
options?: { skipRemoveGroup?: boolean; inDragMode: boolean }
|
||||||
): void {
|
): void {
|
||||||
let group: DockviewGroupPanel;
|
let group: DockviewGroupPanel;
|
||||||
|
|
||||||
@ -356,29 +357,30 @@ export class DockviewComponent
|
|||||||
inDragMode:
|
inDragMode:
|
||||||
typeof options?.inDragMode === 'boolean'
|
typeof options?.inDragMode === 'boolean'
|
||||||
? options.inDragMode
|
? options.inDragMode
|
||||||
: true,
|
: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const instance = {
|
const floatingGroupPanel = new DockviewFloatingGroupPanel(
|
||||||
instance: group,
|
group,
|
||||||
|
overlay
|
||||||
|
);
|
||||||
|
|
||||||
overlay,
|
floatingGroupPanel.addDisposables(
|
||||||
disposable: new CompositeDisposable(
|
overlay.onDidChange(() => {
|
||||||
overlay,
|
this._bufferOnDidLayoutChange.fire();
|
||||||
overlay.onDidChange(() => {
|
}),
|
||||||
this._bufferOnDidLayoutChange.fire();
|
{
|
||||||
}),
|
dispose: () => {
|
||||||
{
|
group.model.isFloating = false;
|
||||||
dispose: () => {
|
remove(this.floatingGroups, floatingGroupPanel);
|
||||||
group.model.isFloating = false;
|
this.updateWatermark();
|
||||||
remove(this.floatingGroups, instance);
|
},
|
||||||
},
|
}
|
||||||
}
|
);
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
this.floatingGroups.push(instance);
|
this.floatingGroups.push(floatingGroupPanel);
|
||||||
|
this.updateWatermark();
|
||||||
}
|
}
|
||||||
|
|
||||||
private orthogonalize(position: Position): DockviewGroupPanel {
|
private orthogonalize(position: Position): DockviewGroupPanel {
|
||||||
@ -519,7 +521,7 @@ export class DockviewComponent
|
|||||||
const floats: SerializedFloatingGroup[] = this.floatingGroups.map(
|
const floats: SerializedFloatingGroup[] = this.floatingGroups.map(
|
||||||
(floatingGroup) => {
|
(floatingGroup) => {
|
||||||
return {
|
return {
|
||||||
data: floatingGroup.instance.toJSON() as GroupPanelViewState,
|
data: floatingGroup.group.toJSON() as GroupPanelViewState,
|
||||||
position: floatingGroup.overlay.toJSON(),
|
position: floatingGroup.overlay.toJSON(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -726,7 +728,7 @@ export class DockviewComponent
|
|||||||
inDragMode: false,
|
inDragMode: false,
|
||||||
skipRemoveGroup: true,
|
skipRemoveGroup: true,
|
||||||
});
|
});
|
||||||
} else if (referenceGroup.model.isFloating || target === 'center') {
|
} else if (referenceGroup.api.isFloating || target === 'center') {
|
||||||
panel = this.createPanel(options, referenceGroup);
|
panel = this.createPanel(options, referenceGroup);
|
||||||
referenceGroup.model.openPanel(panel);
|
referenceGroup.model.openPanel(panel);
|
||||||
} else {
|
} else {
|
||||||
@ -807,7 +809,7 @@ export class DockviewComponent
|
|||||||
}
|
}
|
||||||
|
|
||||||
private updateWatermark(): void {
|
private updateWatermark(): void {
|
||||||
if (this.groups.filter((x) => !x.model.isFloating).length === 0) {
|
if (this.groups.filter((x) => !x.api.isFloating).length === 0) {
|
||||||
if (!this.watermark) {
|
if (!this.watermark) {
|
||||||
this.watermark = this.createWatermarkComponent();
|
this.watermark = this.createWatermarkComponent();
|
||||||
|
|
||||||
@ -920,17 +922,17 @@ export class DockviewComponent
|
|||||||
| undefined
|
| undefined
|
||||||
): DockviewGroupPanel {
|
): DockviewGroupPanel {
|
||||||
const floatingGroup = this.floatingGroups.find(
|
const floatingGroup = this.floatingGroups.find(
|
||||||
(_) => _.instance === group
|
(_) => _.group === group
|
||||||
);
|
);
|
||||||
|
|
||||||
if (floatingGroup) {
|
if (floatingGroup) {
|
||||||
if (!options?.skipDispose) {
|
if (!options?.skipDispose) {
|
||||||
floatingGroup.instance.dispose();
|
floatingGroup.group.dispose();
|
||||||
this._groups.delete(group.id);
|
this._groups.delete(group.id);
|
||||||
}
|
}
|
||||||
floatingGroup.disposable.dispose();
|
floatingGroup.dispose();
|
||||||
|
|
||||||
return floatingGroup.instance;
|
return floatingGroup.group;
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.doRemoveGroup(group, options);
|
return super.doRemoveGroup(group, options);
|
||||||
@ -986,7 +988,7 @@ export class DockviewComponent
|
|||||||
const [targetParentLocation, to] = tail(targetLocation);
|
const [targetParentLocation, to] = tail(targetLocation);
|
||||||
|
|
||||||
const isFloating = this.floatingGroups.find(
|
const isFloating = this.floatingGroups.find(
|
||||||
(x) => x.instance === sourceGroup
|
(x) => x.group === sourceGroup
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!isFloating) {
|
if (!isFloating) {
|
||||||
@ -1066,11 +1068,11 @@ export class DockviewComponent
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const floatingGroup = this.floatingGroups.find(
|
const floatingGroup = this.floatingGroups.find(
|
||||||
(x) => x.instance === sourceGroup
|
(x) => x.group === sourceGroup
|
||||||
);
|
);
|
||||||
|
|
||||||
if (floatingGroup) {
|
if (floatingGroup) {
|
||||||
floatingGroup.disposable.dispose();
|
floatingGroup.dispose();
|
||||||
} else {
|
} else {
|
||||||
this.gridview.removeView(
|
this.gridview.removeView(
|
||||||
getGridLocation(sourceGroup.element)
|
getGridLocation(sourceGroup.element)
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
import { Overlay } from '../dnd/overlay';
|
||||||
|
import { CompositeDisposable } from '../lifecycle';
|
||||||
|
import { DockviewGroupPanel, IDockviewGroupPanel } from './dockviewGroupPanel';
|
||||||
|
|
||||||
|
export interface IDockviewFloatingGroupPanel {
|
||||||
|
readonly group: IDockviewGroupPanel;
|
||||||
|
position(
|
||||||
|
bounds: Partial<{
|
||||||
|
top: number;
|
||||||
|
left: number;
|
||||||
|
height: number;
|
||||||
|
width: number;
|
||||||
|
}>
|
||||||
|
): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DockviewFloatingGroupPanel
|
||||||
|
extends CompositeDisposable
|
||||||
|
implements IDockviewFloatingGroupPanel
|
||||||
|
{
|
||||||
|
constructor(readonly group: DockviewGroupPanel, readonly overlay: Overlay) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.addDisposables(overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
position(
|
||||||
|
bounds: Partial<{
|
||||||
|
top: number;
|
||||||
|
left: number;
|
||||||
|
height: number;
|
||||||
|
width: number;
|
||||||
|
}>
|
||||||
|
): void {
|
||||||
|
this.overlay.setBounds(bounds);
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
import { IFrameworkPart } from '../panel/types';
|
import { IFrameworkPart } from '../panel/types';
|
||||||
import { DockviewComponent } from '../dockview/dockviewComponent';
|
import { DockviewComponent } from '../dockview/dockviewComponent';
|
||||||
import { GridviewPanelApi } from '../api/gridviewPanelApi';
|
|
||||||
import {
|
import {
|
||||||
DockviewGroupPanelModel,
|
DockviewGroupPanelModel,
|
||||||
GroupOptions,
|
GroupOptions,
|
||||||
@ -9,8 +8,13 @@ import {
|
|||||||
} from './dockviewGroupPanelModel';
|
} from './dockviewGroupPanelModel';
|
||||||
import { GridviewPanel, IGridviewPanel } from '../gridview/gridviewPanel';
|
import { GridviewPanel, IGridviewPanel } from '../gridview/gridviewPanel';
|
||||||
import { IDockviewPanel } from '../dockview/dockviewPanel';
|
import { IDockviewPanel } from '../dockview/dockviewPanel';
|
||||||
|
import {
|
||||||
|
DockviewGroupPanelApi,
|
||||||
|
DockviewGroupPanelApiImpl,
|
||||||
|
} from '../api/dockviewGroupPanelApi';
|
||||||
|
|
||||||
export interface IDockviewGroupPanel extends IGridviewPanel {
|
export interface IDockviewGroupPanel
|
||||||
|
extends IGridviewPanel<DockviewGroupPanelApi> {
|
||||||
model: IDockviewGroupPanelModel;
|
model: IDockviewGroupPanelModel;
|
||||||
locked: boolean;
|
locked: boolean;
|
||||||
readonly size: number;
|
readonly size: number;
|
||||||
@ -20,10 +24,8 @@ export interface IDockviewGroupPanel extends IGridviewPanel {
|
|||||||
|
|
||||||
export type IDockviewGroupPanelPublic = IDockviewGroupPanel;
|
export type IDockviewGroupPanelPublic = IDockviewGroupPanel;
|
||||||
|
|
||||||
export type DockviewGroupPanelApi = GridviewPanelApi;
|
|
||||||
|
|
||||||
export class DockviewGroupPanel
|
export class DockviewGroupPanel
|
||||||
extends GridviewPanel
|
extends GridviewPanel<DockviewGroupPanelApiImpl>
|
||||||
implements IDockviewGroupPanel
|
implements IDockviewGroupPanel
|
||||||
{
|
{
|
||||||
private readonly _model: DockviewGroupPanelModel;
|
private readonly _model: DockviewGroupPanelModel;
|
||||||
@ -52,10 +54,6 @@ export class DockviewGroupPanel
|
|||||||
this._model.locked = value;
|
this._model.locked = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
get isFloating(): boolean {
|
|
||||||
return this._model.isFloating;
|
|
||||||
}
|
|
||||||
|
|
||||||
get header(): IHeader {
|
get header(): IHeader {
|
||||||
return this._model.header;
|
return this._model.header;
|
||||||
}
|
}
|
||||||
@ -65,10 +63,17 @@ export class DockviewGroupPanel
|
|||||||
id: string,
|
id: string,
|
||||||
options: GroupOptions
|
options: GroupOptions
|
||||||
) {
|
) {
|
||||||
super(id, 'groupview_default', {
|
super(
|
||||||
minimumHeight: 100,
|
id,
|
||||||
minimumWidth: 100,
|
'groupview_default',
|
||||||
});
|
{
|
||||||
|
minimumHeight: 100,
|
||||||
|
minimumWidth: 100,
|
||||||
|
},
|
||||||
|
new DockviewGroupPanelApiImpl(id, accessor)
|
||||||
|
);
|
||||||
|
|
||||||
|
this.api.initialize(this); // cannot use 'this' after after 'super' call
|
||||||
|
|
||||||
this._model = new DockviewGroupPanelModel(
|
this._model = new DockviewGroupPanelModel(
|
||||||
this.element,
|
this.element,
|
||||||
|
@ -237,6 +237,10 @@ export class DockviewGroupPanelModel
|
|||||||
);
|
);
|
||||||
|
|
||||||
toggleClass(this.container, 'dv-groupview-floating', value);
|
toggleClass(this.container, 'dv-groupview-floating', value);
|
||||||
|
|
||||||
|
this.groupPanel.api._onDidFloatingStateChange.fire({
|
||||||
|
isFloating: this.isFloating,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -8,7 +8,7 @@ import { DockviewGroupPanel } from './dockviewGroupPanel';
|
|||||||
import { CompositeDisposable, IDisposable } from '../lifecycle';
|
import { CompositeDisposable, IDisposable } from '../lifecycle';
|
||||||
import { IPanel, PanelUpdateEvent, Parameters } from '../panel/types';
|
import { IPanel, PanelUpdateEvent, Parameters } from '../panel/types';
|
||||||
import { IDockviewPanelModel } from './dockviewPanelModel';
|
import { IDockviewPanelModel } from './dockviewPanelModel';
|
||||||
import { IDockviewComponent } from './dockviewComponent';
|
import { DockviewComponent } from './dockviewComponent';
|
||||||
|
|
||||||
export interface IDockviewPanel extends IDisposable, IPanel {
|
export interface IDockviewPanel extends IDisposable, IPanel {
|
||||||
readonly view: IDockviewPanelModel;
|
readonly view: IDockviewPanelModel;
|
||||||
@ -47,7 +47,7 @@ export class DockviewPanel
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public readonly id: string,
|
public readonly id: string,
|
||||||
accessor: IDockviewComponent,
|
accessor: DockviewComponent,
|
||||||
private readonly containerApi: DockviewApi,
|
private readonly containerApi: DockviewApi,
|
||||||
group: DockviewGroupPanel,
|
group: DockviewGroupPanel,
|
||||||
readonly view: IDockviewPanelModel
|
readonly view: IDockviewPanelModel
|
||||||
@ -55,7 +55,7 @@ export class DockviewPanel
|
|||||||
super();
|
super();
|
||||||
this._group = group;
|
this._group = group;
|
||||||
|
|
||||||
this.api = new DockviewPanelApiImpl(this, this._group);
|
this.api = new DockviewPanelApiImpl(this, this._group, accessor);
|
||||||
|
|
||||||
this.addDisposables(
|
this.addDisposables(
|
||||||
this.api.onActiveChange(() => {
|
this.api.onActiveChange(() => {
|
||||||
|
@ -8,16 +8,14 @@ import {
|
|||||||
IWatermarkRenderer,
|
IWatermarkRenderer,
|
||||||
DockviewDropTargets,
|
DockviewDropTargets,
|
||||||
} from './types';
|
} from './types';
|
||||||
import {
|
import { DockviewGroupPanel } from './dockviewGroupPanel';
|
||||||
DockviewGroupPanel,
|
|
||||||
DockviewGroupPanelApi,
|
|
||||||
} from './dockviewGroupPanel';
|
|
||||||
import { ISplitviewStyles, Orientation } from '../splitview/splitview';
|
import { ISplitviewStyles, Orientation } from '../splitview/splitview';
|
||||||
import { PanelTransfer } from '../dnd/dataTransfer';
|
import { PanelTransfer } from '../dnd/dataTransfer';
|
||||||
import { IDisposable } from '../lifecycle';
|
import { IDisposable } from '../lifecycle';
|
||||||
import { Position } from '../dnd/droptarget';
|
import { Position } from '../dnd/droptarget';
|
||||||
import { IDockviewPanel } from './dockviewPanel';
|
import { IDockviewPanel } from './dockviewPanel';
|
||||||
import { FrameworkFactory } from '../panel/componentFactory';
|
import { FrameworkFactory } from '../panel/componentFactory';
|
||||||
|
import { DockviewGroupPanelApi } from '../api/dockviewGroupPanelApi';
|
||||||
|
|
||||||
export interface IHeaderActionsRenderer extends IDisposable {
|
export interface IHeaderActionsRenderer extends IDisposable {
|
||||||
readonly element: HTMLElement;
|
readonly element: HTMLElement;
|
||||||
|
@ -28,8 +28,8 @@ export interface GridviewInitParameters extends PanelInitParameters {
|
|||||||
isVisible?: boolean;
|
isVisible?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IGridviewPanel
|
export interface IGridviewPanel<T extends GridviewPanelApi = GridviewPanelApi>
|
||||||
extends BasePanelViewExported<GridviewPanelApi> {
|
extends BasePanelViewExported<T> {
|
||||||
readonly minimumWidth: number;
|
readonly minimumWidth: number;
|
||||||
readonly maximumWidth: number;
|
readonly maximumWidth: number;
|
||||||
readonly minimumHeight: number;
|
readonly minimumHeight: number;
|
||||||
@ -38,8 +38,10 @@ export interface IGridviewPanel
|
|||||||
readonly snap: boolean;
|
readonly snap: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class GridviewPanel
|
export abstract class GridviewPanel<
|
||||||
extends BasePanelView<GridviewPanelApiImpl>
|
T extends GridviewPanelApiImpl = GridviewPanelApiImpl
|
||||||
|
>
|
||||||
|
extends BasePanelView<T>
|
||||||
implements IGridPanelComponentView, IGridviewPanel
|
implements IGridPanelComponentView, IGridviewPanel
|
||||||
{
|
{
|
||||||
private _evaluatedMinimumWidth = 0;
|
private _evaluatedMinimumWidth = 0;
|
||||||
@ -134,9 +136,10 @@ export abstract class GridviewPanel
|
|||||||
maximumWidth?: number;
|
maximumWidth?: number;
|
||||||
minimumHeight?: number;
|
minimumHeight?: number;
|
||||||
maximumHeight?: number;
|
maximumHeight?: number;
|
||||||
}
|
},
|
||||||
|
api?: T
|
||||||
) {
|
) {
|
||||||
super(id, component, new GridviewPanelApiImpl(id));
|
super(id, component, api ?? <T>new GridviewPanelApiImpl(id));
|
||||||
|
|
||||||
if (typeof options?.minimumWidth === 'number') {
|
if (typeof options?.minimumWidth === 'number') {
|
||||||
this._minimumWidth = options.minimumWidth;
|
this._minimumWidth = options.minimumWidth;
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
export * from './dnd/dataTransfer';
|
export * from './dnd/dataTransfer';
|
||||||
|
|
||||||
export { watchElementResize } from './dom';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Events, Emitters and Disposables are very common concepts that most codebases will contain.
|
* Events, Emitters and Disposables are very common concepts that most codebases will contain.
|
||||||
* We export them with a 'Dockview' prefix here to prevent accidental use by others.
|
* We export them with a 'Dockview' prefix here to prevent accidental use by others.
|
||||||
@ -71,6 +69,10 @@ export {
|
|||||||
SplitviewPanelApi,
|
SplitviewPanelApi,
|
||||||
} from './api/splitviewPanelApi';
|
} from './api/splitviewPanelApi';
|
||||||
export { ExpansionEvent, PaneviewPanelApi } from './api/paneviewPanelApi';
|
export { ExpansionEvent, PaneviewPanelApi } from './api/paneviewPanelApi';
|
||||||
|
export {
|
||||||
|
DockviewGroupPanelApi,
|
||||||
|
DockviewGroupPanelFloatingChangeEvent,
|
||||||
|
} from './api/dockviewGroupPanelApi';
|
||||||
export {
|
export {
|
||||||
CommonApi,
|
CommonApi,
|
||||||
SplitviewApi,
|
SplitviewApi,
|
||||||
|
@ -1,3 +1,24 @@
|
|||||||
|
.dv-debug {
|
||||||
|
.split-view-container {
|
||||||
|
.sash-container {
|
||||||
|
.sash {
|
||||||
|
&.enabled {
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
|
&.disabled {
|
||||||
|
background-color: orange;
|
||||||
|
}
|
||||||
|
&.maximum {
|
||||||
|
background-color: green;
|
||||||
|
}
|
||||||
|
&.minimum {
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.split-view-container {
|
.split-view-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -12,22 +33,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// debug
|
|
||||||
// .sash {
|
|
||||||
// &.enabled {
|
|
||||||
// background-color: black;
|
|
||||||
// }
|
|
||||||
// &.disabled {
|
|
||||||
// background-color: orange;
|
|
||||||
// }
|
|
||||||
// &.maximum {
|
|
||||||
// background-color: green;
|
|
||||||
// }
|
|
||||||
// &.minimum {
|
|
||||||
// background-color: red;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
&.horizontal {
|
&.horizontal {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
|
@ -383,7 +383,7 @@ Floating groups can be interacted with whilst holding the `shift` key activating
|
|||||||
<img style={{ width: '60%' }} src={useBaseUrl('/img/float_group.svg')} />
|
<img style={{ width: '60%' }} src={useBaseUrl('/img/float_group.svg')} />
|
||||||
|
|
||||||
Floating groups can be programatically added through the dockview `api` method `api.addFloatingGroup(...)` and you can check whether
|
Floating groups can be programatically added through the dockview `api` method `api.addFloatingGroup(...)` and you can check whether
|
||||||
a group is floating via the `group.isFloating` property. See examples for full code.
|
a group is floating via the `group.api.isFloating` property. See examples for full code.
|
||||||
|
|
||||||
<Container height={600} sandboxId="floatinggroup-dockview">
|
<Container height={600} sandboxId="floatinggroup-dockview">
|
||||||
<DockviewFloating />
|
<DockviewFloating />
|
||||||
@ -499,6 +499,21 @@ panel.api.updateParameters({
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Move panel
|
||||||
|
|
||||||
|
You can programatically move a panel using the panel `api`.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
panel.api.moveTo({ group, position, index });
|
||||||
|
```
|
||||||
|
|
||||||
|
An equivalent method for moving groups is avaliable on the group `api`.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const group = panel.api.group;
|
||||||
|
group.api.moveTo({ group, position });
|
||||||
|
```
|
||||||
|
|
||||||
### Panel Rendering
|
### Panel Rendering
|
||||||
|
|
||||||
By default `DockviewReact` only adds to the DOM those panels that are visible,
|
By default `DockviewReact` only adds to the DOM those panels that are visible,
|
||||||
|
@ -11,28 +11,6 @@ import * as ReactDOM from 'react-dom';
|
|||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
import './app.scss';
|
import './app.scss';
|
||||||
|
|
||||||
function useLocalStorageItem(key: string, defaultValue: string): string {
|
|
||||||
const [item, setItem] = React.useState<string | null>(
|
|
||||||
localStorage.getItem(key)
|
|
||||||
);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
const listener = (event: StorageEvent) => {
|
|
||||||
setItem(localStorage.getItem(key));
|
|
||||||
};
|
|
||||||
|
|
||||||
window.addEventListener('storage', listener);
|
|
||||||
|
|
||||||
setItem(localStorage.getItem(key));
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
window.removeEventListener('storage', listener);
|
|
||||||
};
|
|
||||||
}, [key]);
|
|
||||||
|
|
||||||
return item === null ? defaultValue : item;
|
|
||||||
}
|
|
||||||
|
|
||||||
const components = {
|
const components = {
|
||||||
default: (props: IDockviewPanelProps<{ title: string }>) => {
|
default: (props: IDockviewPanelProps<{ title: string }>) => {
|
||||||
return <div style={{ padding: '20px' }}>{props.params.title}</div>;
|
return <div style={{ padding: '20px' }}>{props.params.title}</div>;
|
||||||
@ -213,7 +191,7 @@ const LeftControls = (props: IDockviewHeaderActionsProps) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const DockviewDemo = () => {
|
const DockviewDemo = (props: { theme?: string }) => {
|
||||||
const onReady = (event: DockviewReadyEvent) => {
|
const onReady = (event: DockviewReadyEvent) => {
|
||||||
event.api.addPanel({
|
event.api.addPanel({
|
||||||
id: 'panel_1',
|
id: 'panel_1',
|
||||||
@ -264,11 +242,6 @@ const DockviewDemo = () => {
|
|||||||
event.api.getPanel('panel_1')!.api.setActive();
|
event.api.getPanel('panel_1')!.api.setActive();
|
||||||
};
|
};
|
||||||
|
|
||||||
const theme = useLocalStorageItem(
|
|
||||||
'dv-theme-class-name',
|
|
||||||
'dockview-theme-abyss'
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DockviewReact
|
<DockviewReact
|
||||||
components={components}
|
components={components}
|
||||||
@ -276,7 +249,7 @@ const DockviewDemo = () => {
|
|||||||
rightHeaderActionsComponent={RightControls}
|
rightHeaderActionsComponent={RightControls}
|
||||||
leftHeaderActionsComponent={LeftControls}
|
leftHeaderActionsComponent={LeftControls}
|
||||||
onReady={onReady}
|
onReady={onReady}
|
||||||
className={theme}
|
className={props.theme || 'dockview-theme-abyss'}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
import {
|
import {
|
||||||
DockviewApi,
|
DockviewApi,
|
||||||
|
DockviewGroupPanel,
|
||||||
DockviewReact,
|
DockviewReact,
|
||||||
DockviewReadyEvent,
|
DockviewReadyEvent,
|
||||||
|
IDockviewHeaderActionsProps,
|
||||||
IDockviewPanelProps,
|
IDockviewPanelProps,
|
||||||
SerializedDockview,
|
SerializedDockview,
|
||||||
} from 'dockview';
|
} from 'dockview';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import { Icon } from './utils';
|
||||||
|
|
||||||
const components = {
|
const components = {
|
||||||
default: (props: IDockviewPanelProps<{ title: string }>) => {
|
default: (props: IDockviewPanelProps<{ title: string }>) => {
|
||||||
@ -68,12 +71,11 @@ function loadDefaultLayout(api: DockviewApi) {
|
|||||||
|
|
||||||
let panelCount = 0;
|
let panelCount = 0;
|
||||||
|
|
||||||
function addFloatingPanel(api: DockviewApi) {
|
function addPanel(api: DockviewApi) {
|
||||||
api.addPanel({
|
api.addPanel({
|
||||||
id: (++panelCount).toString(),
|
id: (++panelCount).toString(),
|
||||||
title: `Tab ${panelCount}`,
|
title: `Tab ${panelCount}`,
|
||||||
component: 'default',
|
component: 'default',
|
||||||
floating: true,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,6 +205,8 @@ export const DockviewPersistance = () => {
|
|||||||
onReady={onReady}
|
onReady={onReady}
|
||||||
components={components}
|
components={components}
|
||||||
watermarkComponent={Watermark}
|
watermarkComponent={Watermark}
|
||||||
|
leftHeaderActionsComponent={LeftComponent}
|
||||||
|
rightHeaderActionsComponent={RightComponent}
|
||||||
className="dockview-theme-abyss"
|
className="dockview-theme-abyss"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -210,6 +214,51 @@ export const DockviewPersistance = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const LeftComponent = (props: IDockviewHeaderActionsProps) => {
|
||||||
|
const onClick = () => {
|
||||||
|
addPanel(props.containerApi);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div style={{ height: '100%', color: 'white', padding: '0px 4px' }}>
|
||||||
|
<Icon onClick={onClick} icon={'add'} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const RightComponent = (props: IDockviewHeaderActionsProps) => {
|
||||||
|
const [floating, setFloating] = React.useState<boolean>(
|
||||||
|
props.api.isFloating
|
||||||
|
);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
const disposable = props.group.api.onDidFloatingStateChange((event) => [
|
||||||
|
setFloating(event.isFloating),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
disposable.dispose();
|
||||||
|
};
|
||||||
|
}, [props.group.api]);
|
||||||
|
|
||||||
|
const onClick = () => {
|
||||||
|
if (floating) {
|
||||||
|
const group = props.containerApi.addGroup();
|
||||||
|
props.group.api.moveTo({ group });
|
||||||
|
} else {
|
||||||
|
props.containerApi.addFloatingGroup(props.group);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ height: '100%', color: 'white', padding: '0px 4px' }}>
|
||||||
|
<Icon
|
||||||
|
onClick={onClick}
|
||||||
|
icon={floating ? 'jump_to_element' : 'back_to_tab'}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default DockviewPersistance;
|
export default DockviewPersistance;
|
||||||
|
|
||||||
const Watermark = () => {
|
const Watermark = () => {
|
||||||
|
30
packages/docs/sandboxes/floatinggroup-dockview/src/utils.tsx
Normal file
30
packages/docs/sandboxes/floatinggroup-dockview/src/utils.tsx
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
export const Icon = (props: {
|
||||||
|
icon: string;
|
||||||
|
title?: string;
|
||||||
|
onClick?: (event: React.MouseEvent) => void;
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
title={props.title}
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
width: '30px',
|
||||||
|
height: '100%',
|
||||||
|
|
||||||
|
fontSize: '18px',
|
||||||
|
}}
|
||||||
|
onClick={props.onClick}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
style={{ fontSize: 'inherit', cursor: 'pointer' }}
|
||||||
|
className="material-symbols-outlined"
|
||||||
|
>
|
||||||
|
{props.icon}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
@ -15,7 +15,7 @@ const components = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const App: React.FC = () => {
|
export const App: React.FC = (props: { theme?: string }) => {
|
||||||
const onReady = (event: DockviewReadyEvent) => {
|
const onReady = (event: DockviewReadyEvent) => {
|
||||||
const panel = event.api.addPanel({
|
const panel = event.api.addPanel({
|
||||||
id: 'panel_1',
|
id: 'panel_1',
|
||||||
@ -88,7 +88,7 @@ export const App: React.FC = () => {
|
|||||||
<DockviewReact
|
<DockviewReact
|
||||||
components={components}
|
components={components}
|
||||||
onReady={onReady}
|
onReady={onReady}
|
||||||
className="dockview-theme-abyss"
|
className={props.theme || 'dockview-theme-abyss'}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -77,6 +77,28 @@ const themes = [
|
|||||||
'dockview-theme-replit',
|
'dockview-theme-replit',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
function useLocalStorageItem(key: string, defaultValue: string): string {
|
||||||
|
const [item, setItem] = React.useState<string | null>(
|
||||||
|
localStorage.getItem(key)
|
||||||
|
);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
const listener = (event: StorageEvent) => {
|
||||||
|
setItem(localStorage.getItem(key));
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('storage', listener);
|
||||||
|
|
||||||
|
setItem(localStorage.getItem(key));
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('storage', listener);
|
||||||
|
};
|
||||||
|
}, [key]);
|
||||||
|
|
||||||
|
return item === null ? defaultValue : item;
|
||||||
|
}
|
||||||
|
|
||||||
export const ThemePicker = () => {
|
export const ThemePicker = () => {
|
||||||
const [theme, setTheme] = React.useState<string>(
|
const [theme, setTheme] = React.useState<string>(
|
||||||
localStorage.getItem('dv-theme-class-name') || themes[0]
|
localStorage.getItem('dv-theme-class-name') || themes[0]
|
||||||
@ -124,6 +146,11 @@ export const MultiFrameworkContainer = (props: {
|
|||||||
|
|
||||||
const [animation, setAnimation] = React.useState<boolean>(false);
|
const [animation, setAnimation] = React.useState<boolean>(false);
|
||||||
|
|
||||||
|
const theme = useLocalStorageItem(
|
||||||
|
'dv-theme-class-name',
|
||||||
|
'dockview-theme-abyss'
|
||||||
|
);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
setAnimation(true);
|
setAnimation(true);
|
||||||
|
|
||||||
@ -182,7 +209,7 @@ export const MultiFrameworkContainer = (props: {
|
|||||||
<Spinner />
|
<Spinner />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{framework === 'React' && <props.react />}
|
{framework === 'React' && <props.react theme={theme} />}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
@ -226,7 +253,6 @@ export const MultiFrameworkContainer = (props: {
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<span style={{ flexGrow: 1 }} />
|
<span style={{ flexGrow: 1 }} />
|
||||||
<ThemePicker />
|
|
||||||
<CodeSandboxButton id={sandboxId} />
|
<CodeSandboxButton id={sandboxId} />
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user