mirror of
https://github.com/mathuo/dockview
synced 2025-09-08 10:26:34 +00:00
Merge pull request #136 from mathuo/133-dnd-enhancements
feat: dnd changes
This commit is contained in:
commit
a92fb3f554
@ -16,16 +16,14 @@ import {
|
|||||||
GroupOptions,
|
GroupOptions,
|
||||||
Groupview,
|
Groupview,
|
||||||
} from '../../groupview/groupview';
|
} from '../../groupview/groupview';
|
||||||
import {
|
import { DockviewPanelApi } from '../../api/groupPanelApi';
|
||||||
DockviewPanelApi,
|
|
||||||
DockviewPanelApiImpl,
|
|
||||||
} from '../../api/groupPanelApi';
|
|
||||||
import {
|
import {
|
||||||
DefaultGroupPanelView,
|
DefaultGroupPanelView,
|
||||||
IGroupPanelView,
|
IGroupPanelView,
|
||||||
} from '../../dockview/defaultGroupPanelView';
|
} from '../../dockview/defaultGroupPanelView';
|
||||||
import { GroupPanel } from '../../groupview/groupviewPanel';
|
import { GroupPanel } from '../../groupview/groupviewPanel';
|
||||||
import { DockviewApi } from '../../api/component.api';
|
import { fireEvent } from '@testing-library/dom';
|
||||||
|
import { LocalSelectionTransfer, PanelTransfer } from '../../dnd/dataTransfer';
|
||||||
|
|
||||||
class Watermark implements IWatermarkRenderer {
|
class Watermark implements IWatermarkRenderer {
|
||||||
public readonly element = document.createElement('div');
|
public readonly element = document.createElement('div');
|
||||||
@ -134,7 +132,7 @@ class TestHeaderPart implements ITabRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestPanel implements IDockviewPanel {
|
export class TestPanel implements IDockviewPanel {
|
||||||
private _view: IGroupPanelView | undefined;
|
private _view: IGroupPanelView | undefined;
|
||||||
private _group: GroupPanel | undefined;
|
private _group: GroupPanel | undefined;
|
||||||
private _params: IGroupPanelInitParameters;
|
private _params: IGroupPanelInitParameters;
|
||||||
@ -148,7 +146,7 @@ class TestPanel implements IDockviewPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get group() {
|
get group() {
|
||||||
return this._group;
|
return this._group!;
|
||||||
}
|
}
|
||||||
|
|
||||||
get view() {
|
get view() {
|
||||||
@ -544,7 +542,7 @@ describe('groupview', () => {
|
|||||||
);
|
);
|
||||||
const contentContainer = groupviewContainer
|
const contentContainer = groupviewContainer
|
||||||
.getElementsByClassName('content-container')
|
.getElementsByClassName('content-container')
|
||||||
.item(0).childNodes;
|
.item(0)!.childNodes;
|
||||||
|
|
||||||
const panel1 = new TestPanel('id_1', null);
|
const panel1 = new TestPanel('id_1', null);
|
||||||
|
|
||||||
@ -568,4 +566,246 @@ describe('groupview', () => {
|
|||||||
expect(contentContainer.length).toBe(1);
|
expect(contentContainer.length).toBe(1);
|
||||||
expect(contentContainer.item(0)).toBe(panel3.view.content.element);
|
expect(contentContainer.item(0)).toBe(panel3.view.content.element);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('that should not show drop target is external event', () => {
|
||||||
|
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => {
|
||||||
|
return {
|
||||||
|
id: 'testcomponentid',
|
||||||
|
options: {
|
||||||
|
showDndOverlay: jest.fn(),
|
||||||
|
},
|
||||||
|
getPanel: jest.fn(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const accessor = new accessorMock() as DockviewComponent;
|
||||||
|
const groupviewMock = jest.fn<Partial<Groupview>, []>(() => {
|
||||||
|
return {
|
||||||
|
canDisplayOverlay: jest.fn(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const groupView = new groupviewMock() as Groupview;
|
||||||
|
|
||||||
|
const groupPanelMock = jest.fn<Partial<GroupPanel>, []>(() => {
|
||||||
|
return {
|
||||||
|
id: 'testgroupid',
|
||||||
|
model: groupView,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const container = document.createElement('div');
|
||||||
|
const cut = new Groupview(
|
||||||
|
container,
|
||||||
|
accessor,
|
||||||
|
'groupviewid',
|
||||||
|
{},
|
||||||
|
new groupPanelMock() as GroupPanel
|
||||||
|
);
|
||||||
|
|
||||||
|
const element = container
|
||||||
|
.getElementsByClassName('content-container')
|
||||||
|
.item(0)!;
|
||||||
|
|
||||||
|
jest.spyOn(element, 'clientHeight', 'get').mockImplementation(
|
||||||
|
() => 100
|
||||||
|
);
|
||||||
|
jest.spyOn(element, 'clientWidth', 'get').mockImplementation(() => 100);
|
||||||
|
|
||||||
|
fireEvent.dragEnter(element);
|
||||||
|
fireEvent.dragOver(element);
|
||||||
|
|
||||||
|
expect(accessor.options.showDndOverlay).toBeCalledTimes(1);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
element.getElementsByClassName('drop-target-dropzone').length
|
||||||
|
).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('that should not show drop target if dropping on self', () => {
|
||||||
|
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => {
|
||||||
|
return {
|
||||||
|
id: 'testcomponentid',
|
||||||
|
options: {
|
||||||
|
showDndOverlay: jest.fn(),
|
||||||
|
},
|
||||||
|
getPanel: jest.fn(),
|
||||||
|
doSetGroupActive: jest.fn(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const accessor = new accessorMock() as DockviewComponent;
|
||||||
|
const groupviewMock = jest.fn<Partial<Groupview>, []>(() => {
|
||||||
|
return {
|
||||||
|
canDisplayOverlay: jest.fn(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const groupView = new groupviewMock() as Groupview;
|
||||||
|
|
||||||
|
const groupPanelMock = jest.fn<Partial<GroupPanel>, []>(() => {
|
||||||
|
return {
|
||||||
|
id: 'testgroupid',
|
||||||
|
model: groupView,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const container = document.createElement('div');
|
||||||
|
const cut = new Groupview(
|
||||||
|
container,
|
||||||
|
accessor,
|
||||||
|
'groupviewid',
|
||||||
|
{},
|
||||||
|
new groupPanelMock() as GroupPanel
|
||||||
|
);
|
||||||
|
|
||||||
|
cut.openPanel(new TestPanel('panel1', jest.fn() as any));
|
||||||
|
|
||||||
|
const element = container
|
||||||
|
.getElementsByClassName('content-container')
|
||||||
|
.item(0)!;
|
||||||
|
|
||||||
|
jest.spyOn(element, 'clientHeight', 'get').mockImplementation(
|
||||||
|
() => 100
|
||||||
|
);
|
||||||
|
jest.spyOn(element, 'clientWidth', 'get').mockImplementation(() => 100);
|
||||||
|
|
||||||
|
LocalSelectionTransfer.getInstance().setData(
|
||||||
|
[new PanelTransfer('testcomponentid', 'groupviewid', 'panel1')],
|
||||||
|
PanelTransfer.prototype
|
||||||
|
);
|
||||||
|
|
||||||
|
fireEvent.dragEnter(element);
|
||||||
|
fireEvent.dragOver(element);
|
||||||
|
|
||||||
|
expect(accessor.options.showDndOverlay).toBeCalledTimes(0);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
element.getElementsByClassName('drop-target-dropzone').length
|
||||||
|
).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('that should allow drop when not dropping on self for same component id', () => {
|
||||||
|
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => {
|
||||||
|
return {
|
||||||
|
id: 'testcomponentid',
|
||||||
|
options: {
|
||||||
|
showDndOverlay: jest.fn(),
|
||||||
|
},
|
||||||
|
getPanel: jest.fn(),
|
||||||
|
doSetGroupActive: jest.fn(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const accessor = new accessorMock() as DockviewComponent;
|
||||||
|
const groupviewMock = jest.fn<Partial<Groupview>, []>(() => {
|
||||||
|
return {
|
||||||
|
canDisplayOverlay: jest.fn(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const groupView = new groupviewMock() as Groupview;
|
||||||
|
|
||||||
|
const groupPanelMock = jest.fn<Partial<GroupPanel>, []>(() => {
|
||||||
|
return {
|
||||||
|
id: 'testgroupid',
|
||||||
|
model: groupView,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const container = document.createElement('div');
|
||||||
|
const cut = new Groupview(
|
||||||
|
container,
|
||||||
|
accessor,
|
||||||
|
'groupviewid',
|
||||||
|
{},
|
||||||
|
new groupPanelMock() as GroupPanel
|
||||||
|
);
|
||||||
|
|
||||||
|
cut.openPanel(new TestPanel('panel1', jest.fn() as any));
|
||||||
|
cut.openPanel(new TestPanel('panel2', jest.fn() as any));
|
||||||
|
|
||||||
|
const element = container
|
||||||
|
.getElementsByClassName('content-container')
|
||||||
|
.item(0)!;
|
||||||
|
|
||||||
|
jest.spyOn(element, 'clientHeight', 'get').mockImplementation(
|
||||||
|
() => 100
|
||||||
|
);
|
||||||
|
jest.spyOn(element, 'clientWidth', 'get').mockImplementation(() => 100);
|
||||||
|
|
||||||
|
LocalSelectionTransfer.getInstance().setData(
|
||||||
|
[new PanelTransfer('testcomponentid', 'groupviewid', 'panel1')],
|
||||||
|
PanelTransfer.prototype
|
||||||
|
);
|
||||||
|
|
||||||
|
fireEvent.dragEnter(element);
|
||||||
|
fireEvent.dragOver(element);
|
||||||
|
|
||||||
|
expect(accessor.options.showDndOverlay).toBeCalledTimes(0);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
element.getElementsByClassName('drop-target-dropzone').length
|
||||||
|
).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('that should not allow drop when not dropping for different component id', () => {
|
||||||
|
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => {
|
||||||
|
return {
|
||||||
|
id: 'testcomponentid',
|
||||||
|
options: {
|
||||||
|
showDndOverlay: jest.fn(),
|
||||||
|
},
|
||||||
|
getPanel: jest.fn(),
|
||||||
|
doSetGroupActive: jest.fn(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const accessor = new accessorMock() as DockviewComponent;
|
||||||
|
const groupviewMock = jest.fn<Partial<Groupview>, []>(() => {
|
||||||
|
return {
|
||||||
|
canDisplayOverlay: jest.fn(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const groupView = new groupviewMock() as Groupview;
|
||||||
|
|
||||||
|
const groupPanelMock = jest.fn<Partial<GroupPanel>, []>(() => {
|
||||||
|
return {
|
||||||
|
id: 'testgroupid',
|
||||||
|
model: groupView,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const container = document.createElement('div');
|
||||||
|
const cut = new Groupview(
|
||||||
|
container,
|
||||||
|
accessor,
|
||||||
|
'groupviewid',
|
||||||
|
{},
|
||||||
|
new groupPanelMock() as GroupPanel
|
||||||
|
);
|
||||||
|
|
||||||
|
cut.openPanel(new TestPanel('panel1', jest.fn() as any));
|
||||||
|
cut.openPanel(new TestPanel('panel2', jest.fn() as any));
|
||||||
|
|
||||||
|
const element = container
|
||||||
|
.getElementsByClassName('content-container')
|
||||||
|
.item(0)!;
|
||||||
|
|
||||||
|
jest.spyOn(element, 'clientHeight', 'get').mockImplementation(
|
||||||
|
() => 100
|
||||||
|
);
|
||||||
|
jest.spyOn(element, 'clientWidth', 'get').mockImplementation(() => 100);
|
||||||
|
|
||||||
|
LocalSelectionTransfer.getInstance().setData(
|
||||||
|
[new PanelTransfer('anothercomponentid', 'groupviewid', 'panel1')],
|
||||||
|
PanelTransfer.prototype
|
||||||
|
);
|
||||||
|
|
||||||
|
fireEvent.dragEnter(element);
|
||||||
|
fireEvent.dragOver(element);
|
||||||
|
|
||||||
|
expect(accessor.options.showDndOverlay).toBeCalledTimes(1);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
element.getElementsByClassName('drop-target-dropzone').length
|
||||||
|
).toBe(0);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
import { fireEvent } from '@testing-library/dom';
|
||||||
|
import { LocalSelectionTransfer, PanelTransfer } from '../../dnd/dataTransfer';
|
||||||
|
import { DockviewComponent } from '../../dockview/dockviewComponent';
|
||||||
|
import { Groupview } from '../../groupview/groupview';
|
||||||
|
import { GroupPanel } from '../../groupview/groupviewPanel';
|
||||||
import { Tab } from '../../groupview/tab';
|
import { Tab } from '../../groupview/tab';
|
||||||
|
|
||||||
describe('tab', () => {
|
describe('tab', () => {
|
||||||
@ -22,4 +27,251 @@ describe('tab', () => {
|
|||||||
cut.setActive(false);
|
cut.setActive(false);
|
||||||
expect(cut.element.className).toBe('tab inactive-tab');
|
expect(cut.element.className).toBe('tab inactive-tab');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('that an external event does not render a drop target and calls through to the group model', () => {
|
||||||
|
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => {
|
||||||
|
return {
|
||||||
|
id: 'testcomponentid',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const groupviewMock = jest.fn<Partial<Groupview>, []>(() => {
|
||||||
|
return {
|
||||||
|
canDisplayOverlay: jest.fn(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const groupView = new groupviewMock() as Groupview;
|
||||||
|
|
||||||
|
const groupPanelMock = jest.fn<Partial<GroupPanel>, []>(() => {
|
||||||
|
return {
|
||||||
|
id: 'testgroupid',
|
||||||
|
model: groupView,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const accessor = new accessorMock() as DockviewComponent;
|
||||||
|
const groupPanel = new groupPanelMock() as GroupPanel;
|
||||||
|
|
||||||
|
const cut = new Tab('panelId', accessor, groupPanel);
|
||||||
|
|
||||||
|
jest.spyOn(cut.element, 'clientHeight', 'get').mockImplementation(
|
||||||
|
() => 100
|
||||||
|
);
|
||||||
|
jest.spyOn(cut.element, 'clientWidth', 'get').mockImplementation(
|
||||||
|
() => 100
|
||||||
|
);
|
||||||
|
|
||||||
|
fireEvent.dragEnter(cut.element);
|
||||||
|
fireEvent.dragOver(cut.element);
|
||||||
|
|
||||||
|
expect(groupView.canDisplayOverlay).toBeCalled();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
cut.element.getElementsByClassName('drop-target-dropzone').length
|
||||||
|
).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('that if you drag over yourself no drop target is shown', () => {
|
||||||
|
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => {
|
||||||
|
return {
|
||||||
|
id: 'testcomponentid',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const groupviewMock = jest.fn<Partial<Groupview>, []>(() => {
|
||||||
|
return {
|
||||||
|
canDisplayOverlay: jest.fn(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const groupView = new groupviewMock() as Groupview;
|
||||||
|
|
||||||
|
const groupPanelMock = jest.fn<Partial<GroupPanel>, []>(() => {
|
||||||
|
return {
|
||||||
|
id: 'testgroupid',
|
||||||
|
model: groupView,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const accessor = new accessorMock() as DockviewComponent;
|
||||||
|
const groupPanel = new groupPanelMock() as GroupPanel;
|
||||||
|
|
||||||
|
const cut = new Tab('panel1', accessor, groupPanel);
|
||||||
|
|
||||||
|
jest.spyOn(cut.element, 'clientHeight', 'get').mockImplementation(
|
||||||
|
() => 100
|
||||||
|
);
|
||||||
|
jest.spyOn(cut.element, 'clientWidth', 'get').mockImplementation(
|
||||||
|
() => 100
|
||||||
|
);
|
||||||
|
|
||||||
|
LocalSelectionTransfer.getInstance().setData(
|
||||||
|
[new PanelTransfer('testcomponentid', 'anothergroupid', 'panel1')],
|
||||||
|
PanelTransfer.prototype
|
||||||
|
);
|
||||||
|
|
||||||
|
fireEvent.dragEnter(cut.element);
|
||||||
|
fireEvent.dragOver(cut.element);
|
||||||
|
|
||||||
|
expect(groupView.canDisplayOverlay).toBeCalledTimes(0);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
cut.element.getElementsByClassName('drop-target-dropzone').length
|
||||||
|
).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('that if you drag over another tab a drop target is shown', () => {
|
||||||
|
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => {
|
||||||
|
return {
|
||||||
|
id: 'testcomponentid',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const groupviewMock = jest.fn<Partial<Groupview>, []>(() => {
|
||||||
|
return {
|
||||||
|
canDisplayOverlay: jest.fn(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const groupView = new groupviewMock() as Groupview;
|
||||||
|
|
||||||
|
const groupPanelMock = jest.fn<Partial<GroupPanel>, []>(() => {
|
||||||
|
return {
|
||||||
|
id: 'testgroupid',
|
||||||
|
model: groupView,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const accessor = new accessorMock() as DockviewComponent;
|
||||||
|
const groupPanel = new groupPanelMock() as GroupPanel;
|
||||||
|
|
||||||
|
const cut = new Tab('panel1', accessor, groupPanel);
|
||||||
|
|
||||||
|
jest.spyOn(cut.element, 'clientHeight', 'get').mockImplementation(
|
||||||
|
() => 100
|
||||||
|
);
|
||||||
|
jest.spyOn(cut.element, 'clientWidth', 'get').mockImplementation(
|
||||||
|
() => 100
|
||||||
|
);
|
||||||
|
|
||||||
|
LocalSelectionTransfer.getInstance().setData(
|
||||||
|
[new PanelTransfer('testcomponentid', 'anothergroupid', 'panel2')],
|
||||||
|
PanelTransfer.prototype
|
||||||
|
);
|
||||||
|
|
||||||
|
fireEvent.dragEnter(cut.element);
|
||||||
|
fireEvent.dragOver(cut.element);
|
||||||
|
|
||||||
|
expect(groupView.canDisplayOverlay).toBeCalledTimes(0);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
cut.element.getElementsByClassName('drop-target-dropzone').length
|
||||||
|
).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('that dropping on a tab with the same id but from a different component should not render a drop over and call through to the group model', () => {
|
||||||
|
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => {
|
||||||
|
return {
|
||||||
|
id: 'testcomponentid',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const groupviewMock = jest.fn<Partial<Groupview>, []>(() => {
|
||||||
|
return {
|
||||||
|
canDisplayOverlay: jest.fn(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const groupView = new groupviewMock() as Groupview;
|
||||||
|
|
||||||
|
const groupPanelMock = jest.fn<Partial<GroupPanel>, []>(() => {
|
||||||
|
return {
|
||||||
|
id: 'testgroupid',
|
||||||
|
model: groupView,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const accessor = new accessorMock() as DockviewComponent;
|
||||||
|
const groupPanel = new groupPanelMock() as GroupPanel;
|
||||||
|
|
||||||
|
const cut = new Tab('panel1', accessor, groupPanel);
|
||||||
|
|
||||||
|
jest.spyOn(cut.element, 'clientHeight', 'get').mockImplementation(
|
||||||
|
() => 100
|
||||||
|
);
|
||||||
|
jest.spyOn(cut.element, 'clientWidth', 'get').mockImplementation(
|
||||||
|
() => 100
|
||||||
|
);
|
||||||
|
|
||||||
|
LocalSelectionTransfer.getInstance().setData(
|
||||||
|
[
|
||||||
|
new PanelTransfer(
|
||||||
|
'anothercomponentid',
|
||||||
|
'anothergroupid',
|
||||||
|
'panel1'
|
||||||
|
),
|
||||||
|
],
|
||||||
|
PanelTransfer.prototype
|
||||||
|
);
|
||||||
|
|
||||||
|
fireEvent.dragEnter(cut.element);
|
||||||
|
fireEvent.dragOver(cut.element);
|
||||||
|
|
||||||
|
expect(groupView.canDisplayOverlay).toBeCalledTimes(1);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
cut.element.getElementsByClassName('drop-target-dropzone').length
|
||||||
|
).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('that dropping on a tab from a different component should not render a drop over and call through to the group model', () => {
|
||||||
|
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => {
|
||||||
|
return {
|
||||||
|
id: 'testcomponentid',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const groupviewMock = jest.fn<Partial<Groupview>, []>(() => {
|
||||||
|
return {
|
||||||
|
canDisplayOverlay: jest.fn(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const groupView = new groupviewMock() as Groupview;
|
||||||
|
|
||||||
|
const groupPanelMock = jest.fn<Partial<GroupPanel>, []>(() => {
|
||||||
|
return {
|
||||||
|
id: 'testgroupid',
|
||||||
|
model: groupView,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const accessor = new accessorMock() as DockviewComponent;
|
||||||
|
const groupPanel = new groupPanelMock() as GroupPanel;
|
||||||
|
|
||||||
|
const cut = new Tab('panel1', accessor, groupPanel);
|
||||||
|
|
||||||
|
jest.spyOn(cut.element, 'clientHeight', 'get').mockImplementation(
|
||||||
|
() => 100
|
||||||
|
);
|
||||||
|
jest.spyOn(cut.element, 'clientWidth', 'get').mockImplementation(
|
||||||
|
() => 100
|
||||||
|
);
|
||||||
|
|
||||||
|
LocalSelectionTransfer.getInstance().setData(
|
||||||
|
[
|
||||||
|
new PanelTransfer(
|
||||||
|
'anothercomponentid',
|
||||||
|
'anothergroupid',
|
||||||
|
'panel2'
|
||||||
|
),
|
||||||
|
],
|
||||||
|
PanelTransfer.prototype
|
||||||
|
);
|
||||||
|
|
||||||
|
fireEvent.dragEnter(cut.element);
|
||||||
|
fireEvent.dragOver(cut.element);
|
||||||
|
|
||||||
|
expect(groupView.canDisplayOverlay).toBeCalledTimes(1);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
cut.element.getElementsByClassName('drop-target-dropzone').length
|
||||||
|
).toBe(0);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -0,0 +1,305 @@
|
|||||||
|
import { DockviewComponent } from '../../../dockview/dockviewComponent';
|
||||||
|
import { GroupPanel } from '../../../groupview/groupviewPanel';
|
||||||
|
import { TabsContainer } from '../../../groupview/titlebar/tabsContainer';
|
||||||
|
import { fireEvent } from '@testing-library/dom';
|
||||||
|
import { Groupview } from '../../../groupview/groupview';
|
||||||
|
import {
|
||||||
|
LocalSelectionTransfer,
|
||||||
|
PanelTransfer,
|
||||||
|
} from '../../../dnd/dataTransfer';
|
||||||
|
import { TestPanel } from '../groupview.spec';
|
||||||
|
|
||||||
|
describe('tabsContainer', () => {
|
||||||
|
test('that an external event does not render a drop target and calls through to the group mode', () => {
|
||||||
|
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => {
|
||||||
|
return {};
|
||||||
|
});
|
||||||
|
const groupviewMock = jest.fn<Partial<Groupview>, []>(() => {
|
||||||
|
return {
|
||||||
|
canDisplayOverlay: jest.fn(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const groupView = new groupviewMock() as Groupview;
|
||||||
|
|
||||||
|
const groupPanelMock = jest.fn<Partial<GroupPanel>, []>(() => {
|
||||||
|
return {
|
||||||
|
model: groupView,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const accessor = new accessorMock() as DockviewComponent;
|
||||||
|
const groupPanel = new groupPanelMock() as GroupPanel;
|
||||||
|
|
||||||
|
const cut = new TabsContainer(accessor, groupPanel, {});
|
||||||
|
|
||||||
|
const emptySpace = cut.element
|
||||||
|
.getElementsByClassName('void-container')
|
||||||
|
.item(0);
|
||||||
|
|
||||||
|
if (!emptySpace) {
|
||||||
|
fail('element not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
jest.spyOn(emptySpace, 'clientHeight', 'get').mockImplementation(
|
||||||
|
() => 100
|
||||||
|
);
|
||||||
|
jest.spyOn(emptySpace, 'clientWidth', 'get').mockImplementation(
|
||||||
|
() => 100
|
||||||
|
);
|
||||||
|
|
||||||
|
fireEvent.dragEnter(emptySpace);
|
||||||
|
fireEvent.dragOver(emptySpace);
|
||||||
|
|
||||||
|
expect(groupView.canDisplayOverlay).toBeCalled();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
cut.element.getElementsByClassName('drop-target-dropzone').length
|
||||||
|
).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('that a drag over event from another tab should render a drop target', () => {
|
||||||
|
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => {
|
||||||
|
return {
|
||||||
|
id: 'testcomponentid',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const groupviewMock = jest.fn<Partial<Groupview>, []>(() => {
|
||||||
|
return {
|
||||||
|
canDisplayOverlay: jest.fn(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const groupView = new groupviewMock() as Groupview;
|
||||||
|
|
||||||
|
const groupPanelMock = jest.fn<Partial<GroupPanel>, []>(() => {
|
||||||
|
return {
|
||||||
|
id: 'testgroupid',
|
||||||
|
model: groupView,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const accessor = new accessorMock() as DockviewComponent;
|
||||||
|
const groupPanel = new groupPanelMock() as GroupPanel;
|
||||||
|
|
||||||
|
const cut = new TabsContainer(accessor, groupPanel, {});
|
||||||
|
|
||||||
|
const emptySpace = cut.element
|
||||||
|
.getElementsByClassName('void-container')
|
||||||
|
.item(0);
|
||||||
|
|
||||||
|
if (!emptySpace) {
|
||||||
|
fail('element not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
jest.spyOn(emptySpace, 'clientHeight', 'get').mockImplementation(
|
||||||
|
() => 100
|
||||||
|
);
|
||||||
|
jest.spyOn(emptySpace, 'clientWidth', 'get').mockImplementation(
|
||||||
|
() => 100
|
||||||
|
);
|
||||||
|
|
||||||
|
LocalSelectionTransfer.getInstance().setData(
|
||||||
|
[
|
||||||
|
new PanelTransfer(
|
||||||
|
'testcomponentid',
|
||||||
|
'anothergroupid',
|
||||||
|
'anotherpanelid'
|
||||||
|
),
|
||||||
|
],
|
||||||
|
PanelTransfer.prototype
|
||||||
|
);
|
||||||
|
|
||||||
|
fireEvent.dragEnter(emptySpace);
|
||||||
|
fireEvent.dragOver(emptySpace);
|
||||||
|
|
||||||
|
expect(groupView.canDisplayOverlay).toBeCalledTimes(0);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
cut.element.getElementsByClassName('drop-target-dropzone').length
|
||||||
|
).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('that dropping the last tab should render no drop target', () => {
|
||||||
|
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => {
|
||||||
|
return {
|
||||||
|
id: 'testcomponentid',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const groupviewMock = jest.fn<Partial<Groupview>, []>(() => {
|
||||||
|
return {
|
||||||
|
canDisplayOverlay: jest.fn(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const groupView = new groupviewMock() as Groupview;
|
||||||
|
|
||||||
|
const groupPanelMock = jest.fn<Partial<GroupPanel>, []>(() => {
|
||||||
|
return {
|
||||||
|
id: 'testgroupid',
|
||||||
|
model: groupView,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const accessor = new accessorMock() as DockviewComponent;
|
||||||
|
const groupPanel = new groupPanelMock() as GroupPanel;
|
||||||
|
|
||||||
|
const cut = new TabsContainer(accessor, groupPanel, {});
|
||||||
|
|
||||||
|
cut.openPanel(new TestPanel('panel1', jest.fn() as any));
|
||||||
|
cut.openPanel(new TestPanel('panel2', jest.fn() as any));
|
||||||
|
|
||||||
|
const emptySpace = cut.element
|
||||||
|
.getElementsByClassName('void-container')
|
||||||
|
.item(0);
|
||||||
|
|
||||||
|
if (!emptySpace) {
|
||||||
|
fail('element not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
jest.spyOn(emptySpace, 'clientHeight', 'get').mockImplementation(
|
||||||
|
() => 100
|
||||||
|
);
|
||||||
|
jest.spyOn(emptySpace, 'clientWidth', 'get').mockImplementation(
|
||||||
|
() => 100
|
||||||
|
);
|
||||||
|
|
||||||
|
LocalSelectionTransfer.getInstance().setData(
|
||||||
|
[new PanelTransfer('testcomponentid', 'anothergroupid', 'panel2')],
|
||||||
|
PanelTransfer.prototype
|
||||||
|
);
|
||||||
|
|
||||||
|
fireEvent.dragEnter(emptySpace);
|
||||||
|
fireEvent.dragOver(emptySpace);
|
||||||
|
|
||||||
|
expect(groupView.canDisplayOverlay).toBeCalledTimes(0);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
cut.element.getElementsByClassName('drop-target-dropzone').length
|
||||||
|
).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('that dropping the first tab should render a drop target', () => {
|
||||||
|
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => {
|
||||||
|
return {
|
||||||
|
id: 'testcomponentid',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const groupviewMock = jest.fn<Partial<Groupview>, []>(() => {
|
||||||
|
return {
|
||||||
|
canDisplayOverlay: jest.fn(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const groupView = new groupviewMock() as Groupview;
|
||||||
|
|
||||||
|
const groupPanelMock = jest.fn<Partial<GroupPanel>, []>(() => {
|
||||||
|
return {
|
||||||
|
id: 'testgroupid',
|
||||||
|
model: groupView,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const accessor = new accessorMock() as DockviewComponent;
|
||||||
|
const groupPanel = new groupPanelMock() as GroupPanel;
|
||||||
|
|
||||||
|
const cut = new TabsContainer(accessor, groupPanel, {});
|
||||||
|
|
||||||
|
cut.openPanel(new TestPanel('panel1', jest.fn() as any));
|
||||||
|
cut.openPanel(new TestPanel('panel2', jest.fn() as any));
|
||||||
|
|
||||||
|
const emptySpace = cut.element
|
||||||
|
.getElementsByClassName('void-container')
|
||||||
|
.item(0);
|
||||||
|
|
||||||
|
if (!emptySpace) {
|
||||||
|
fail('element not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
jest.spyOn(emptySpace, 'clientHeight', 'get').mockImplementation(
|
||||||
|
() => 100
|
||||||
|
);
|
||||||
|
jest.spyOn(emptySpace, 'clientWidth', 'get').mockImplementation(
|
||||||
|
() => 100
|
||||||
|
);
|
||||||
|
|
||||||
|
LocalSelectionTransfer.getInstance().setData(
|
||||||
|
[new PanelTransfer('testcomponentid', 'anothergroupid', 'panel1')],
|
||||||
|
PanelTransfer.prototype
|
||||||
|
);
|
||||||
|
|
||||||
|
fireEvent.dragEnter(emptySpace);
|
||||||
|
fireEvent.dragOver(emptySpace);
|
||||||
|
|
||||||
|
expect(groupView.canDisplayOverlay).toBeCalledTimes(0);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
cut.element.getElementsByClassName('drop-target-dropzone').length
|
||||||
|
).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('that dropping a tab from another component should not render a drop target', () => {
|
||||||
|
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => {
|
||||||
|
return {
|
||||||
|
id: 'testcomponentid',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const groupviewMock = jest.fn<Partial<Groupview>, []>(() => {
|
||||||
|
return {
|
||||||
|
canDisplayOverlay: jest.fn(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const groupView = new groupviewMock() as Groupview;
|
||||||
|
|
||||||
|
const groupPanelMock = jest.fn<Partial<GroupPanel>, []>(() => {
|
||||||
|
return {
|
||||||
|
id: 'testgroupid',
|
||||||
|
model: groupView,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const accessor = new accessorMock() as DockviewComponent;
|
||||||
|
const groupPanel = new groupPanelMock() as GroupPanel;
|
||||||
|
|
||||||
|
const cut = new TabsContainer(accessor, groupPanel, {});
|
||||||
|
|
||||||
|
cut.openPanel(new TestPanel('panel1', jest.fn() as any));
|
||||||
|
cut.openPanel(new TestPanel('panel2', jest.fn() as any));
|
||||||
|
|
||||||
|
const emptySpace = cut.element
|
||||||
|
.getElementsByClassName('void-container')
|
||||||
|
.item(0);
|
||||||
|
|
||||||
|
if (!emptySpace) {
|
||||||
|
fail('element not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
jest.spyOn(emptySpace, 'clientHeight', 'get').mockImplementation(
|
||||||
|
() => 100
|
||||||
|
);
|
||||||
|
jest.spyOn(emptySpace, 'clientWidth', 'get').mockImplementation(
|
||||||
|
() => 100
|
||||||
|
);
|
||||||
|
|
||||||
|
LocalSelectionTransfer.getInstance().setData(
|
||||||
|
[
|
||||||
|
new PanelTransfer(
|
||||||
|
'anothercomponentid',
|
||||||
|
'anothergroupid',
|
||||||
|
'panel1'
|
||||||
|
),
|
||||||
|
],
|
||||||
|
PanelTransfer.prototype
|
||||||
|
);
|
||||||
|
|
||||||
|
fireEvent.dragEnter(emptySpace);
|
||||||
|
fireEvent.dragOver(emptySpace);
|
||||||
|
|
||||||
|
expect(groupView.canDisplayOverlay).toBeCalledTimes(1);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
cut.element.getElementsByClassName('drop-target-dropzone').length
|
||||||
|
).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
@ -12,6 +12,7 @@ import { GroupPanel } from '../groupview/groupviewPanel';
|
|||||||
import { ISplitviewStyles, Orientation } from '../splitview/core/splitview';
|
import { ISplitviewStyles, Orientation } from '../splitview/core/splitview';
|
||||||
import { FrameworkFactory } from '../types';
|
import { FrameworkFactory } from '../types';
|
||||||
import { DockviewDropTargets } from '../groupview/dnd';
|
import { DockviewDropTargets } from '../groupview/dnd';
|
||||||
|
import { PanelTransfer } from '../dnd/dataTransfer';
|
||||||
|
|
||||||
export interface GroupPanelFrameworkComponentFactory {
|
export interface GroupPanelFrameworkComponentFactory {
|
||||||
content: FrameworkFactory<IContentRenderer>;
|
content: FrameworkFactory<IContentRenderer>;
|
||||||
@ -53,6 +54,7 @@ export interface DockviewDndOverlayEvent {
|
|||||||
nativeEvent: DragEvent;
|
nativeEvent: DragEvent;
|
||||||
target: DockviewDropTargets;
|
target: DockviewDropTargets;
|
||||||
group: GroupPanel;
|
group: GroupPanel;
|
||||||
|
getData: () => PanelTransfer | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DockviewComponentOptions extends DockviewRenderFunctions {
|
export interface DockviewComponentOptions extends DockviewRenderFunctions {
|
||||||
|
@ -247,7 +247,7 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
|||||||
|
|
||||||
const data = getPanelData();
|
const data = getPanelData();
|
||||||
|
|
||||||
if (data) {
|
if (data && data.viewId === this.accessor.id) {
|
||||||
const groupHasOnePanelAndIsActiveDragElement =
|
const groupHasOnePanelAndIsActiveDragElement =
|
||||||
this._panels.length === 1 && data.groupId === this.id;
|
this._panels.length === 1 && data.groupId === this.id;
|
||||||
|
|
||||||
@ -670,6 +670,7 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
|||||||
nativeEvent: event,
|
nativeEvent: event,
|
||||||
target,
|
target,
|
||||||
group: this.accessor.getPanel(this.id)!,
|
group: this.accessor.getPanel(this.id)!,
|
||||||
|
getData: getPanelData,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -52,7 +52,7 @@ export class Tab extends CompositeDisposable implements ITab {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public readonly panelId: string,
|
public readonly panelId: string,
|
||||||
accessor: IDockviewComponent,
|
private readonly accessor: IDockviewComponent,
|
||||||
private readonly group: GroupPanel
|
private readonly group: GroupPanel
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
@ -119,7 +119,7 @@ export class Tab extends CompositeDisposable implements ITab {
|
|||||||
validOverlays: 'none',
|
validOverlays: 'none',
|
||||||
canDisplayOverlay: (event) => {
|
canDisplayOverlay: (event) => {
|
||||||
const data = getPanelData();
|
const data = getPanelData();
|
||||||
if (data) {
|
if (data && this.accessor.id === data.viewId) {
|
||||||
return this.panelId !== data.panelId;
|
return this.panelId !== data.panelId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,7 +169,7 @@ export class TabsContainer
|
|||||||
canDisplayOverlay: (event) => {
|
canDisplayOverlay: (event) => {
|
||||||
const data = getPanelData();
|
const data = getPanelData();
|
||||||
|
|
||||||
if (data) {
|
if (data && this.accessor.id === data.viewId) {
|
||||||
// don't show the overlay if the tab being dragged is the last panel of this group
|
// don't show the overlay if the tab being dragged is the last panel of this group
|
||||||
return last(this.tabs)?.value.panelId !== data.panelId;
|
return last(this.tabs)?.value.panelId !== data.panelId;
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ export * from './dockview/dockviewComponent';
|
|||||||
export * from './gridview/gridviewComponent';
|
export * from './gridview/gridviewComponent';
|
||||||
export * from './splitview/splitviewComponent';
|
export * from './splitview/splitviewComponent';
|
||||||
export * from './paneview/paneviewComponent';
|
export * from './paneview/paneviewComponent';
|
||||||
|
export { PaneviewComponentOptions } from './paneview/options';
|
||||||
|
|
||||||
export * from './gridview/gridviewPanel';
|
export * from './gridview/gridviewPanel';
|
||||||
export * from './splitview/splitviewPanel';
|
export * from './splitview/splitviewPanel';
|
||||||
|
@ -8,6 +8,7 @@ import { Droptarget, DroptargetEvent, Position } from '../dnd/droptarget';
|
|||||||
import { Emitter } from '../events';
|
import { Emitter } from '../events';
|
||||||
import { IDisposable } from '../lifecycle';
|
import { IDisposable } from '../lifecycle';
|
||||||
import { Orientation } from '../splitview/core/splitview';
|
import { Orientation } from '../splitview/core/splitview';
|
||||||
|
import { IPaneviewComponent } from './paneviewComponent';
|
||||||
import {
|
import {
|
||||||
IPaneviewPanel,
|
IPaneviewPanel,
|
||||||
PanePanelInitParameter,
|
PanePanelInitParameter,
|
||||||
@ -27,6 +28,7 @@ export abstract class DraggablePaneviewPanel extends PaneviewPanel {
|
|||||||
readonly onDidDrop = this._onDidDrop.event;
|
readonly onDidDrop = this._onDidDrop.event;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
private readonly accessor: IPaneviewComponent,
|
||||||
id: string,
|
id: string,
|
||||||
component: string,
|
component: string,
|
||||||
headerComponent: string | undefined,
|
headerComponent: string | undefined,
|
||||||
@ -47,12 +49,13 @@ export abstract class DraggablePaneviewPanel extends PaneviewPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const id = this.id;
|
const id = this.id;
|
||||||
|
const accessorId = this.accessor.id;
|
||||||
this.header.draggable = true;
|
this.header.draggable = true;
|
||||||
|
|
||||||
this.handler = new (class PaneDragHandler extends DragHandler {
|
this.handler = new (class PaneDragHandler extends DragHandler {
|
||||||
getData(): IDisposable {
|
getData(): IDisposable {
|
||||||
LocalSelectionTransfer.getInstance().setData(
|
LocalSelectionTransfer.getInstance().setData(
|
||||||
[new PaneTransfer('paneview', id)],
|
[new PaneTransfer(accessorId, id)],
|
||||||
PaneTransfer.prototype
|
PaneTransfer.prototype
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -68,14 +71,27 @@ export abstract class DraggablePaneviewPanel extends PaneviewPanel {
|
|||||||
|
|
||||||
this.target = new Droptarget(this.element, {
|
this.target = new Droptarget(this.element, {
|
||||||
validOverlays: 'vertical',
|
validOverlays: 'vertical',
|
||||||
canDisplayOverlay: () => {
|
canDisplayOverlay: (event) => {
|
||||||
const data = getPaneData();
|
const data = getPaneData();
|
||||||
|
|
||||||
if (!data) {
|
if (data) {
|
||||||
return true;
|
if (
|
||||||
|
data.paneId !== this.id &&
|
||||||
|
data.viewId === this.accessor.id
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return data.paneId !== this.id;
|
if (this.accessor.options.showDndOverlay) {
|
||||||
|
return this.accessor.options.showDndOverlay({
|
||||||
|
nativeEvent: event,
|
||||||
|
getData: getPaneData,
|
||||||
|
panel: this,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -92,11 +108,13 @@ export abstract class DraggablePaneviewPanel extends PaneviewPanel {
|
|||||||
private onDrop(event: DroptargetEvent) {
|
private onDrop(event: DroptargetEvent) {
|
||||||
const data = getPaneData();
|
const data = getPaneData();
|
||||||
|
|
||||||
if (!data) {
|
if (!data || data.viewId !== this.accessor.id) {
|
||||||
|
// if there is no local drag event for this panel
|
||||||
|
// or if the drag event was creating by another Paneview instance
|
||||||
this._onDidDrop.fire({
|
this._onDidDrop.fire({
|
||||||
...event,
|
...event,
|
||||||
panel: this,
|
panel: this,
|
||||||
getData: () => getPaneData(),
|
getData: getPaneData,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -107,10 +125,11 @@ export abstract class DraggablePaneviewPanel extends PaneviewPanel {
|
|||||||
|
|
||||||
const existingPanel = containerApi.getPanel(panelId);
|
const existingPanel = containerApi.getPanel(panelId);
|
||||||
if (!existingPanel) {
|
if (!existingPanel) {
|
||||||
|
// if the panel doesn't exist
|
||||||
this._onDidDrop.fire({
|
this._onDidDrop.fire({
|
||||||
...event,
|
...event,
|
||||||
panel: this,
|
panel: this,
|
||||||
getData: () => getPaneData(),
|
getData: getPaneData,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { FrameworkFactory } from '../types';
|
import { FrameworkFactory } from '../types';
|
||||||
|
import { PaneviewDndOverlayEvent } from './paneviewComponent';
|
||||||
import { IPaneBodyPart, IPaneHeaderPart, PaneviewPanel } from './paneviewPanel';
|
import { IPaneBodyPart, IPaneHeaderPart, PaneviewPanel } from './paneviewPanel';
|
||||||
|
|
||||||
export interface PaneviewComponentOptions {
|
export interface PaneviewComponentOptions {
|
||||||
@ -23,4 +24,5 @@ export interface PaneviewComponentOptions {
|
|||||||
body: FrameworkFactory<IPaneBodyPart>;
|
body: FrameworkFactory<IPaneBodyPart>;
|
||||||
};
|
};
|
||||||
disableDnd?: boolean;
|
disableDnd?: boolean;
|
||||||
|
showDndOverlay?: (event: PaneviewDndOverlayEvent) => boolean;
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,16 @@ import {
|
|||||||
PaneviewDropEvent2,
|
PaneviewDropEvent2,
|
||||||
} from './draggablePaneviewPanel';
|
} from './draggablePaneviewPanel';
|
||||||
import { DefaultHeader } from './defaultPaneviewHeader';
|
import { DefaultHeader } from './defaultPaneviewHeader';
|
||||||
|
import { sequentialNumberGenerator } from '../math';
|
||||||
|
import { PaneTransfer } from '../dnd/dataTransfer';
|
||||||
|
|
||||||
|
const nextLayoutId = sequentialNumberGenerator();
|
||||||
|
|
||||||
|
export interface PaneviewDndOverlayEvent {
|
||||||
|
nativeEvent: DragEvent;
|
||||||
|
panel: IPaneviewPanel;
|
||||||
|
getData: () => PaneTransfer | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
export interface SerializedPaneviewPanel {
|
export interface SerializedPaneviewPanel {
|
||||||
snap?: boolean;
|
snap?: boolean;
|
||||||
@ -57,9 +67,11 @@ export class PaneFramework extends DraggablePaneviewPanel {
|
|||||||
orientation: Orientation;
|
orientation: Orientation;
|
||||||
isExpanded: boolean;
|
isExpanded: boolean;
|
||||||
disableDnd: boolean;
|
disableDnd: boolean;
|
||||||
|
accessor: IPaneviewComponent;
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
|
options.accessor,
|
||||||
options.id,
|
options.id,
|
||||||
options.component,
|
options.component,
|
||||||
options.headerComponent,
|
options.headerComponent,
|
||||||
@ -94,11 +106,13 @@ export interface AddPaneviewComponentOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IPaneviewComponent extends IDisposable {
|
export interface IPaneviewComponent extends IDisposable {
|
||||||
|
readonly id: string;
|
||||||
readonly width: number;
|
readonly width: number;
|
||||||
readonly height: number;
|
readonly height: number;
|
||||||
readonly minimumSize: number;
|
readonly minimumSize: number;
|
||||||
readonly maximumSize: number;
|
readonly maximumSize: number;
|
||||||
readonly panels: IPaneviewPanel[];
|
readonly panels: IPaneviewPanel[];
|
||||||
|
readonly options: PaneviewComponentOptions;
|
||||||
readonly onDidAddView: Event<PaneviewPanel>;
|
readonly onDidAddView: Event<PaneviewPanel>;
|
||||||
readonly onDidRemoveView: Event<PaneviewPanel>;
|
readonly onDidRemoveView: Event<PaneviewPanel>;
|
||||||
readonly onDidDrop: Event<PaneviewDropEvent2>;
|
readonly onDidDrop: Event<PaneviewDropEvent2>;
|
||||||
@ -120,6 +134,8 @@ export class PaneviewComponent
|
|||||||
extends CompositeDisposable
|
extends CompositeDisposable
|
||||||
implements IPaneviewComponent
|
implements IPaneviewComponent
|
||||||
{
|
{
|
||||||
|
private readonly _id = nextLayoutId.next();
|
||||||
|
private _options: PaneviewComponentOptions;
|
||||||
private _disposable = new MutableDisposable();
|
private _disposable = new MutableDisposable();
|
||||||
private _viewDisposables = new Map<string, IDisposable>();
|
private _viewDisposables = new Map<string, IDisposable>();
|
||||||
private _paneview!: Paneview;
|
private _paneview!: Paneview;
|
||||||
@ -139,6 +155,10 @@ export class PaneviewComponent
|
|||||||
private readonly _onDidRemoveView = new Emitter<PaneviewPanel>();
|
private readonly _onDidRemoveView = new Emitter<PaneviewPanel>();
|
||||||
readonly onDidRemoveView = this._onDidRemoveView.event;
|
readonly onDidRemoveView = this._onDidRemoveView.event;
|
||||||
|
|
||||||
|
get id(): string {
|
||||||
|
return this._id;
|
||||||
|
}
|
||||||
|
|
||||||
get panels(): PaneviewPanel[] {
|
get panels(): PaneviewPanel[] {
|
||||||
return this.paneview.getPanes();
|
return this.paneview.getPanes();
|
||||||
}
|
}
|
||||||
@ -179,9 +199,7 @@ export class PaneviewComponent
|
|||||||
: this.paneview.orthogonalSize;
|
: this.paneview.orthogonalSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _options: PaneviewComponentOptions;
|
get options(): PaneviewComponentOptions {
|
||||||
|
|
||||||
get options() {
|
|
||||||
return this._options;
|
return this._options;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,6 +285,7 @@ export class PaneviewComponent
|
|||||||
orientation: Orientation.VERTICAL,
|
orientation: Orientation.VERTICAL,
|
||||||
isExpanded: !!options.isExpanded,
|
isExpanded: !!options.isExpanded,
|
||||||
disableDnd: !!this.options.disableDnd,
|
disableDnd: !!this.options.disableDnd,
|
||||||
|
accessor: this,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.doAddPanel(view);
|
this.doAddPanel(view);
|
||||||
@ -400,6 +419,7 @@ export class PaneviewComponent
|
|||||||
orientation: Orientation.VERTICAL,
|
orientation: Orientation.VERTICAL,
|
||||||
isExpanded: !!view.expanded,
|
isExpanded: !!view.expanded,
|
||||||
disableDnd: !!this.options.disableDnd,
|
disableDnd: !!this.options.disableDnd,
|
||||||
|
accessor: this,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.doAddPanel(panel);
|
this.doAddPanel(panel);
|
||||||
|
@ -137,6 +137,7 @@ export const DockviewReact = React.forwardRef(
|
|||||||
styles: props.hideBorders
|
styles: props.hideBorders
|
||||||
? { separatorBorder: 'transparent' }
|
? { separatorBorder: 'transparent' }
|
||||||
: undefined,
|
: undefined,
|
||||||
|
showDndOverlay: props.showDndOverlay,
|
||||||
});
|
});
|
||||||
|
|
||||||
domRef.current?.appendChild(dockview.element);
|
domRef.current?.appendChild(dockview.element);
|
||||||
|
@ -3,6 +3,7 @@ import { PaneviewPanelApi } from '../../api/paneviewPanelApi';
|
|||||||
import {
|
import {
|
||||||
PaneviewComponent,
|
PaneviewComponent,
|
||||||
IPaneviewComponent,
|
IPaneviewComponent,
|
||||||
|
PaneviewDndOverlayEvent,
|
||||||
} from '../../paneview/paneviewComponent';
|
} from '../../paneview/paneviewComponent';
|
||||||
import { usePortalsLifecycle } from '../react';
|
import { usePortalsLifecycle } from '../react';
|
||||||
import { PaneviewApi } from '../../api/component.api';
|
import { PaneviewApi } from '../../api/component.api';
|
||||||
@ -33,6 +34,7 @@ export interface IPaneviewReactProps {
|
|||||||
className?: string;
|
className?: string;
|
||||||
disableAutoResizing?: boolean;
|
disableAutoResizing?: boolean;
|
||||||
disableDnd?: boolean;
|
disableDnd?: boolean;
|
||||||
|
showDndOverlay?: (event: PaneviewDndOverlayEvent) => boolean;
|
||||||
onDidDrop?(event: PaneviewDropEvent): void;
|
onDidDrop?(event: PaneviewDropEvent): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,6 +87,7 @@ export const PaneviewReact = React.forwardRef(
|
|||||||
createComponent,
|
createComponent,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
showDndOverlay: props.showDndOverlay,
|
||||||
});
|
});
|
||||||
|
|
||||||
const api = new PaneviewApi(paneview);
|
const api = new PaneviewApi(paneview);
|
||||||
@ -144,6 +147,15 @@ export const PaneviewReact = React.forwardRef(
|
|||||||
};
|
};
|
||||||
}, [props.onDidDrop]);
|
}, [props.onDidDrop]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (!paneviewRef.current) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
paneviewRef.current.updateOptions({
|
||||||
|
showDndOverlay: props.showDndOverlay,
|
||||||
|
});
|
||||||
|
}, [props.showDndOverlay]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={props.className}
|
className={props.className}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user