mirror of
https://github.com/mathuo/dockview
synced 2025-02-13 03:45:47 +00:00
Merge branch 'master' of https://github.com/mathuo/dockview into 479-is-there-any-way-to-focus-the-panel-content
This commit is contained in:
commit
89fe866ac5
8
.github/workflows/codeql-analysis.yml
vendored
8
.github/workflows/codeql-analysis.yml
vendored
@ -30,11 +30,11 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v1
|
uses: github/codeql-action/init@v3
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
@ -45,7 +45,7 @@ jobs:
|
|||||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||||
# If this step fails, then you should remove it and run the build manually (see below)
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
- name: Autobuild
|
- name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@v1
|
uses: github/codeql-action/autobuild@v3
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
# 📚 https://git.io/JvXDl
|
# 📚 https://git.io/JvXDl
|
||||||
@ -59,4 +59,4 @@ jobs:
|
|||||||
# make release
|
# make release
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v1
|
uses: github/codeql-action/analyze@v3
|
||||||
|
10
.github/workflows/deploy-docs.yml
vendored
10
.github/workflows/deploy-docs.yml
vendored
@ -2,21 +2,19 @@ name: Deploy Docs
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
schedule:
|
|
||||||
- cron: '0 3 * * *' # every day at 3 am UTC
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
deploy-nightly-demo-app:
|
deploy-nightly-demo-app:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout 🛎️
|
- name: Checkout 🛎️
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
- name: Use Node.js
|
- name: Use Node.js
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: '18.x'
|
node-version: '20.x'
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.npm
|
path: ~/.npm
|
||||||
key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }}
|
key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }}
|
||||||
|
8
.github/workflows/main.yml
vendored
8
.github/workflows/main.yml
vendored
@ -7,16 +7,16 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
# might be required for sonar to work correctly
|
# might be required for sonar to work correctly
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
|
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
|
||||||
- name: Use Node.js
|
- name: Use Node.js
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: '18.x'
|
node-version: '20.x'
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.npm
|
path: ~/.npm
|
||||||
key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }}
|
key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }}
|
||||||
|
12
.github/workflows/publish.yml
vendored
12
.github/workflows/publish.yml
vendored
@ -16,12 +16,12 @@ jobs:
|
|||||||
id-token: write
|
id-token: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: '18.x'
|
node-version: '20.x'
|
||||||
registry-url: 'https://registry.npmjs.org'
|
registry-url: 'https://registry.npmjs.org'
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.npm
|
path: ~/.npm
|
||||||
key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }}
|
key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }}
|
||||||
@ -44,12 +44,12 @@ jobs:
|
|||||||
id-token: write
|
id-token: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: '18.x'
|
node-version: '20.x'
|
||||||
registry-url: 'https://registry.npmjs.org'
|
registry-url: 'https://registry.npmjs.org'
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.npm
|
path: ~/.npm
|
||||||
key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }}
|
key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }}
|
||||||
|
@ -8,7 +8,7 @@ describe('groupPanelApi', () => {
|
|||||||
const accessor: Partial<DockviewComponent> = {
|
const accessor: Partial<DockviewComponent> = {
|
||||||
onDidAddPanel: jest.fn(),
|
onDidAddPanel: jest.fn(),
|
||||||
onDidRemovePanel: jest.fn(),
|
onDidRemovePanel: jest.fn(),
|
||||||
options: {},
|
options: { parentElement: document.createElement('div') },
|
||||||
};
|
};
|
||||||
|
|
||||||
const panelMock = jest.fn<DockviewPanel, []>(() => {
|
const panelMock = jest.fn<DockviewPanel, []>(() => {
|
||||||
@ -44,7 +44,7 @@ describe('groupPanelApi', () => {
|
|||||||
const accessor: Partial<DockviewComponent> = {
|
const accessor: Partial<DockviewComponent> = {
|
||||||
onDidAddPanel: jest.fn(),
|
onDidAddPanel: jest.fn(),
|
||||||
onDidRemovePanel: jest.fn(),
|
onDidRemovePanel: jest.fn(),
|
||||||
options: {},
|
options: { parentElement: document.createElement('div') },
|
||||||
};
|
};
|
||||||
const groupViewPanel = new DockviewGroupPanel(
|
const groupViewPanel = new DockviewGroupPanel(
|
||||||
<DockviewComponent>accessor,
|
<DockviewComponent>accessor,
|
||||||
@ -74,7 +74,7 @@ describe('groupPanelApi', () => {
|
|||||||
const accessor: Partial<DockviewComponent> = {
|
const accessor: Partial<DockviewComponent> = {
|
||||||
onDidAddPanel: jest.fn(),
|
onDidAddPanel: jest.fn(),
|
||||||
onDidRemovePanel: jest.fn(),
|
onDidRemovePanel: jest.fn(),
|
||||||
options: {},
|
options: { parentElement: document.createElement('div') },
|
||||||
};
|
};
|
||||||
const groupViewPanel = new DockviewGroupPanel(
|
const groupViewPanel = new DockviewGroupPanel(
|
||||||
<DockviewComponent>accessor,
|
<DockviewComponent>accessor,
|
||||||
|
@ -171,18 +171,37 @@ describe('droptarget', () => {
|
|||||||
createOffsetDragOverEvent({ clientX: 19, clientY: 0 })
|
createOffsetDragOverEvent({ clientX: 19, clientY: 0 })
|
||||||
);
|
);
|
||||||
|
|
||||||
|
function check(
|
||||||
|
element: HTMLElement,
|
||||||
|
box: {
|
||||||
|
left: string;
|
||||||
|
top: string;
|
||||||
|
width: string;
|
||||||
|
height: string;
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
expect(element.style.top).toBe(box.top);
|
||||||
|
expect(element.style.left).toBe(box.left);
|
||||||
|
expect(element.style.width).toBe(box.width);
|
||||||
|
expect(element.style.height).toBe(box.height);
|
||||||
|
}
|
||||||
|
|
||||||
viewQuery = element.querySelectorAll(
|
viewQuery = element.querySelectorAll(
|
||||||
'.drop-target > .drop-target-dropzone > .drop-target-selection'
|
'.drop-target > .drop-target-dropzone > .drop-target-selection'
|
||||||
);
|
);
|
||||||
expect(viewQuery.length).toBe(1);
|
expect(viewQuery.length).toBe(1);
|
||||||
expect(droptarget.state).toBe('left');
|
expect(droptarget.state).toBe('left');
|
||||||
expect(
|
check(
|
||||||
(
|
element
|
||||||
element
|
.getElementsByClassName('drop-target-selection')
|
||||||
.getElementsByClassName('drop-target-selection')
|
.item(0) as HTMLDivElement,
|
||||||
.item(0) as HTMLDivElement
|
{
|
||||||
).style.transform
|
top: '0px',
|
||||||
).toBe('translateX(-25%) scaleX(0.5)');
|
left: '0px',
|
||||||
|
width: '50%',
|
||||||
|
height: '100%',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
fireEvent(
|
fireEvent(
|
||||||
target,
|
target,
|
||||||
@ -194,13 +213,17 @@ describe('droptarget', () => {
|
|||||||
);
|
);
|
||||||
expect(viewQuery.length).toBe(1);
|
expect(viewQuery.length).toBe(1);
|
||||||
expect(droptarget.state).toBe('top');
|
expect(droptarget.state).toBe('top');
|
||||||
expect(
|
check(
|
||||||
(
|
element
|
||||||
element
|
.getElementsByClassName('drop-target-selection')
|
||||||
.getElementsByClassName('drop-target-selection')
|
.item(0) as HTMLDivElement,
|
||||||
.item(0) as HTMLDivElement
|
{
|
||||||
).style.transform
|
top: '0px',
|
||||||
).toBe('translateY(-25%) scaleY(0.5)');
|
left: '0px',
|
||||||
|
width: '100%',
|
||||||
|
height: '50%',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
fireEvent(
|
fireEvent(
|
||||||
target,
|
target,
|
||||||
@ -212,13 +235,17 @@ describe('droptarget', () => {
|
|||||||
);
|
);
|
||||||
expect(viewQuery.length).toBe(1);
|
expect(viewQuery.length).toBe(1);
|
||||||
expect(droptarget.state).toBe('bottom');
|
expect(droptarget.state).toBe('bottom');
|
||||||
expect(
|
check(
|
||||||
(
|
element
|
||||||
element
|
.getElementsByClassName('drop-target-selection')
|
||||||
.getElementsByClassName('drop-target-selection')
|
.item(0) as HTMLDivElement,
|
||||||
.item(0) as HTMLDivElement
|
{
|
||||||
).style.transform
|
top: '50%',
|
||||||
).toBe('translateY(25%) scaleY(0.5)');
|
left: '0px',
|
||||||
|
width: '100%',
|
||||||
|
height: '50%',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
fireEvent(
|
fireEvent(
|
||||||
target,
|
target,
|
||||||
@ -230,14 +257,17 @@ describe('droptarget', () => {
|
|||||||
);
|
);
|
||||||
expect(viewQuery.length).toBe(1);
|
expect(viewQuery.length).toBe(1);
|
||||||
expect(droptarget.state).toBe('right');
|
expect(droptarget.state).toBe('right');
|
||||||
expect(
|
check(
|
||||||
(
|
element
|
||||||
element
|
.getElementsByClassName('drop-target-selection')
|
||||||
.getElementsByClassName('drop-target-selection')
|
.item(0) as HTMLDivElement,
|
||||||
.item(0) as HTMLDivElement
|
{
|
||||||
).style.transform
|
top: '0px',
|
||||||
).toBe('translateX(25%) scaleX(0.5)');
|
left: '50%',
|
||||||
|
width: '50%',
|
||||||
|
height: '100%',
|
||||||
|
}
|
||||||
|
);
|
||||||
fireEvent(
|
fireEvent(
|
||||||
target,
|
target,
|
||||||
createOffsetDragOverEvent({ clientX: 100, clientY: 50 })
|
createOffsetDragOverEvent({ clientX: 100, clientY: 50 })
|
||||||
|
@ -11,7 +11,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',
|
||||||
api: { location: 'grid' } as any,
|
api: { location: { type: 'grid' } } as any,
|
||||||
};
|
};
|
||||||
return partial as DockviewGroupPanel;
|
return partial as DockviewGroupPanel;
|
||||||
});
|
});
|
||||||
@ -53,7 +53,7 @@ describe('groupDragHandler', () => {
|
|||||||
|
|
||||||
const groupMock = jest.fn<DockviewGroupPanel, []>(() => {
|
const groupMock = jest.fn<DockviewGroupPanel, []>(() => {
|
||||||
const partial: Partial<DockviewGroupPanel> = {
|
const partial: Partial<DockviewGroupPanel> = {
|
||||||
api: { location: 'floating' } as any,
|
api: { location: { type: 'floating' } } as any,
|
||||||
};
|
};
|
||||||
return partial as DockviewGroupPanel;
|
return partial as DockviewGroupPanel;
|
||||||
});
|
});
|
||||||
@ -85,7 +85,7 @@ describe('groupDragHandler', () => {
|
|||||||
|
|
||||||
const groupMock = jest.fn<DockviewGroupPanel, []>(() => {
|
const groupMock = jest.fn<DockviewGroupPanel, []>(() => {
|
||||||
const partial: Partial<DockviewGroupPanel> = {
|
const partial: Partial<DockviewGroupPanel> = {
|
||||||
api: { location: 'grid' } as any,
|
api: { location: { type: 'grid' } } as any,
|
||||||
};
|
};
|
||||||
return partial as DockviewGroupPanel;
|
return partial as DockviewGroupPanel;
|
||||||
});
|
});
|
||||||
|
@ -62,16 +62,19 @@ describe('contentContainer', () => {
|
|||||||
|
|
||||||
const disposable = new CompositeDisposable();
|
const disposable = new CompositeDisposable();
|
||||||
|
|
||||||
const dockviewComponent = jest.fn<DockviewComponent, []>(() => {
|
const overlayRenderContainer = new OverlayRenderContainer(
|
||||||
return {
|
document.createElement('div')
|
||||||
renderer: 'onlyWhenVisibile',
|
);
|
||||||
overlayRenderContainer: new OverlayRenderContainer(
|
|
||||||
document.createElement('div')
|
|
||||||
),
|
|
||||||
} as DockviewComponent;
|
|
||||||
});
|
|
||||||
|
|
||||||
const cut = new ContentContainer(dockviewComponent(), jest.fn() as any);
|
const cut = new ContentContainer(
|
||||||
|
fromPartial<DockviewComponent>({
|
||||||
|
renderer: 'onlyWhenVisibile',
|
||||||
|
overlayRenderContainer,
|
||||||
|
}),
|
||||||
|
fromPartial<DockviewGroupPanelModel>({
|
||||||
|
renderContainer: overlayRenderContainer,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
disposable.addDisposables(
|
disposable.addDisposables(
|
||||||
cut.onDidFocus(() => {
|
cut.onDidFocus(() => {
|
||||||
@ -84,12 +87,12 @@ describe('contentContainer', () => {
|
|||||||
|
|
||||||
const contentRenderer = new TestContentRenderer('id-1');
|
const contentRenderer = new TestContentRenderer('id-1');
|
||||||
|
|
||||||
const panel = {
|
const panel = fromPartial<IDockviewPanel>({
|
||||||
view: {
|
view: {
|
||||||
content: contentRenderer,
|
content: contentRenderer,
|
||||||
} as Partial<IDockviewPanelModel>,
|
},
|
||||||
api: { renderer: 'onlyWhenVisibile' },
|
api: { renderer: 'onlyWhenVisibile' },
|
||||||
} as Partial<IDockviewPanel>;
|
});
|
||||||
|
|
||||||
cut.openPanel(panel as IDockviewPanel);
|
cut.openPanel(panel as IDockviewPanel);
|
||||||
|
|
||||||
@ -151,13 +154,17 @@ describe('contentContainer', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("that panels renderered as 'onlyWhenVisibile' are removed when closed", () => {
|
test("that panels renderered as 'onlyWhenVisibile' are removed when closed", () => {
|
||||||
|
const overlayRenderContainer = fromPartial<OverlayRenderContainer>({
|
||||||
|
detatch: jest.fn(),
|
||||||
|
});
|
||||||
|
|
||||||
const cut = new ContentContainer(
|
const cut = new ContentContainer(
|
||||||
fromPartial<DockviewComponent>({
|
fromPartial<DockviewComponent>({
|
||||||
overlayRenderContainer: {
|
overlayRenderContainer,
|
||||||
detatch: jest.fn(),
|
|
||||||
},
|
|
||||||
}),
|
}),
|
||||||
fromPartial<DockviewGroupPanelModel>({})
|
fromPartial<DockviewGroupPanelModel>({
|
||||||
|
renderContainer: overlayRenderContainer,
|
||||||
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const panel1 = fromPartial<IDockviewPanel>({
|
const panel1 = fromPartial<IDockviewPanel>({
|
||||||
|
@ -9,6 +9,7 @@ import { DockviewGroupPanelModel } from '../../../../dockview/dockviewGroupPanel
|
|||||||
import { fireEvent } from '@testing-library/dom';
|
import { fireEvent } from '@testing-library/dom';
|
||||||
import { TestPanel } from '../../dockviewGroupPanelModel.spec';
|
import { TestPanel } from '../../dockviewGroupPanelModel.spec';
|
||||||
import { IDockviewPanel } from '../../../../dockview/dockviewPanel';
|
import { IDockviewPanel } from '../../../../dockview/dockviewPanel';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
|
|
||||||
describe('tabsContainer', () => {
|
describe('tabsContainer', () => {
|
||||||
test('that an external event does not render a drop target and calls through to the group mode', () => {
|
test('that an external event does not render a drop target and calls through to the group mode', () => {
|
||||||
@ -16,7 +17,7 @@ describe('tabsContainer', () => {
|
|||||||
return {
|
return {
|
||||||
onDidAddPanel: jest.fn(),
|
onDidAddPanel: jest.fn(),
|
||||||
onDidRemovePanel: jest.fn(),
|
onDidRemovePanel: jest.fn(),
|
||||||
options: {},
|
options: { parentElement: document.createElement('div') },
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
|
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
|
||||||
@ -71,7 +72,7 @@ describe('tabsContainer', () => {
|
|||||||
id: 'testcomponentid',
|
id: 'testcomponentid',
|
||||||
onDidAddPanel: jest.fn(),
|
onDidAddPanel: jest.fn(),
|
||||||
onDidRemovePanel: jest.fn(),
|
onDidRemovePanel: jest.fn(),
|
||||||
options: {},
|
options: { parentElement: document.createElement('div') },
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
|
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
|
||||||
@ -139,7 +140,7 @@ describe('tabsContainer', () => {
|
|||||||
id: 'testcomponentid',
|
id: 'testcomponentid',
|
||||||
onDidAddPanel: jest.fn(),
|
onDidAddPanel: jest.fn(),
|
||||||
onDidRemovePanel: jest.fn(),
|
onDidRemovePanel: jest.fn(),
|
||||||
options: {},
|
options: { parentElement: document.createElement('div') },
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
|
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
|
||||||
@ -204,7 +205,7 @@ describe('tabsContainer', () => {
|
|||||||
id: 'testcomponentid',
|
id: 'testcomponentid',
|
||||||
onDidAddPanel: jest.fn(),
|
onDidAddPanel: jest.fn(),
|
||||||
onDidRemovePanel: jest.fn(),
|
onDidRemovePanel: jest.fn(),
|
||||||
options: {},
|
options: { parentElement: document.createElement('div') },
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
|
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
|
||||||
@ -269,7 +270,7 @@ describe('tabsContainer', () => {
|
|||||||
id: 'testcomponentid',
|
id: 'testcomponentid',
|
||||||
onDidAddPanel: jest.fn(),
|
onDidAddPanel: jest.fn(),
|
||||||
onDidRemovePanel: jest.fn(),
|
onDidRemovePanel: jest.fn(),
|
||||||
options: {},
|
options: { parentElement: document.createElement('div') },
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
|
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
|
||||||
@ -336,7 +337,7 @@ describe('tabsContainer', () => {
|
|||||||
test('left actions', () => {
|
test('left actions', () => {
|
||||||
const accessorMock = jest.fn<DockviewComponent, []>(() => {
|
const accessorMock = jest.fn<DockviewComponent, []>(() => {
|
||||||
return (<Partial<DockviewComponent>>{
|
return (<Partial<DockviewComponent>>{
|
||||||
options: {},
|
options: { parentElement: document.createElement('div') },
|
||||||
onDidAddPanel: jest.fn(),
|
onDidAddPanel: jest.fn(),
|
||||||
onDidRemovePanel: jest.fn(),
|
onDidRemovePanel: jest.fn(),
|
||||||
}) as DockviewComponent;
|
}) as DockviewComponent;
|
||||||
@ -402,7 +403,7 @@ describe('tabsContainer', () => {
|
|||||||
test('right actions', () => {
|
test('right actions', () => {
|
||||||
const accessorMock = jest.fn<DockviewComponent, []>(() => {
|
const accessorMock = jest.fn<DockviewComponent, []>(() => {
|
||||||
return (<Partial<DockviewComponent>>{
|
return (<Partial<DockviewComponent>>{
|
||||||
options: {},
|
options: { parentElement: document.createElement('div') },
|
||||||
onDidAddPanel: jest.fn(),
|
onDidAddPanel: jest.fn(),
|
||||||
onDidRemovePanel: jest.fn(),
|
onDidRemovePanel: jest.fn(),
|
||||||
}) as DockviewComponent;
|
}) as DockviewComponent;
|
||||||
@ -468,7 +469,7 @@ describe('tabsContainer', () => {
|
|||||||
test('that a tab will become floating when clicked if not floating and shift is selected', () => {
|
test('that a tab will become floating when clicked if not floating and shift is selected', () => {
|
||||||
const accessorMock = jest.fn<DockviewComponent, []>(() => {
|
const accessorMock = jest.fn<DockviewComponent, []>(() => {
|
||||||
return (<Partial<DockviewComponent>>{
|
return (<Partial<DockviewComponent>>{
|
||||||
options: {},
|
options: { parentElement: document.createElement('div') },
|
||||||
onDidAddPanel: jest.fn(),
|
onDidAddPanel: jest.fn(),
|
||||||
onDidRemovePanel: jest.fn(),
|
onDidRemovePanel: jest.fn(),
|
||||||
element: document.createElement('div'),
|
element: document.createElement('div'),
|
||||||
@ -478,7 +479,7 @@ describe('tabsContainer', () => {
|
|||||||
|
|
||||||
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
|
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
|
||||||
return (<Partial<DockviewGroupPanel>>{
|
return (<Partial<DockviewGroupPanel>>{
|
||||||
api: { location: 'grid' } as any,
|
api: { location: { type: 'grid' } } as any,
|
||||||
}) as DockviewGroupPanel;
|
}) as DockviewGroupPanel;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -514,21 +515,21 @@ describe('tabsContainer', () => {
|
|||||||
},
|
},
|
||||||
{ inDragMode: true }
|
{ inDragMode: true }
|
||||||
);
|
);
|
||||||
expect(accessor.addFloatingGroup).toBeCalledTimes(1);
|
expect(accessor.addFloatingGroup).toHaveBeenCalledTimes(1);
|
||||||
expect(eventPreventDefaultSpy).toBeCalledTimes(1);
|
expect(eventPreventDefaultSpy).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
const event2 = new KeyboardEvent('mousedown', { shiftKey: false });
|
const event2 = new KeyboardEvent('mousedown', { shiftKey: false });
|
||||||
const eventPreventDefaultSpy2 = jest.spyOn(event2, 'preventDefault');
|
const eventPreventDefaultSpy2 = jest.spyOn(event2, 'preventDefault');
|
||||||
fireEvent(container, event2);
|
fireEvent(container, event2);
|
||||||
|
|
||||||
expect(accessor.addFloatingGroup).toBeCalledTimes(1);
|
expect(accessor.addFloatingGroup).toHaveBeenCalledTimes(1);
|
||||||
expect(eventPreventDefaultSpy2).toBeCalledTimes(0);
|
expect(eventPreventDefaultSpy2).toHaveBeenCalledTimes(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('that a tab that is already floating cannot be floated again', () => {
|
test('that a tab that is already floating cannot be floated again', () => {
|
||||||
const accessorMock = jest.fn<DockviewComponent, []>(() => {
|
const accessorMock = jest.fn<DockviewComponent, []>(() => {
|
||||||
return (<Partial<DockviewComponent>>{
|
return (<Partial<DockviewComponent>>{
|
||||||
options: {},
|
options: { parentElement: document.createElement('div') },
|
||||||
onDidAddPanel: jest.fn(),
|
onDidAddPanel: jest.fn(),
|
||||||
onDidRemovePanel: jest.fn(),
|
onDidRemovePanel: jest.fn(),
|
||||||
element: document.createElement('div'),
|
element: document.createElement('div'),
|
||||||
@ -538,7 +539,7 @@ describe('tabsContainer', () => {
|
|||||||
|
|
||||||
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
|
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
|
||||||
return (<Partial<DockviewGroupPanel>>{
|
return (<Partial<DockviewGroupPanel>>{
|
||||||
api: { location: 'floating' } as any,
|
api: { location: { type: 'floating' } } as any,
|
||||||
}) as DockviewGroupPanel;
|
}) as DockviewGroupPanel;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -580,7 +581,7 @@ describe('tabsContainer', () => {
|
|||||||
test('that selecting a tab with shift down will move that tab into a new floating group', () => {
|
test('that selecting a tab with shift down will move that tab into a new floating group', () => {
|
||||||
const accessorMock = jest.fn<DockviewComponent, []>(() => {
|
const accessorMock = jest.fn<DockviewComponent, []>(() => {
|
||||||
return (<Partial<DockviewComponent>>{
|
return (<Partial<DockviewComponent>>{
|
||||||
options: {},
|
options: { parentElement: document.createElement('div') },
|
||||||
onDidAddPanel: jest.fn(),
|
onDidAddPanel: jest.fn(),
|
||||||
onDidRemovePanel: jest.fn(),
|
onDidRemovePanel: jest.fn(),
|
||||||
element: document.createElement('div'),
|
element: document.createElement('div'),
|
||||||
@ -591,7 +592,7 @@ describe('tabsContainer', () => {
|
|||||||
|
|
||||||
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
|
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
|
||||||
return (<Partial<DockviewGroupPanel>>{
|
return (<Partial<DockviewGroupPanel>>{
|
||||||
api: { location: 'floating' } as any,
|
api: { location: { type: 'floating' } } as any,
|
||||||
model: {} as any,
|
model: {} as any,
|
||||||
}) as DockviewGroupPanel;
|
}) as DockviewGroupPanel;
|
||||||
});
|
});
|
||||||
@ -601,23 +602,20 @@ describe('tabsContainer', () => {
|
|||||||
|
|
||||||
const cut = new TabsContainer(accessor, groupPanel);
|
const cut = new TabsContainer(accessor, groupPanel);
|
||||||
|
|
||||||
const panelMock = jest.fn<IDockviewPanel, [string]>((id: string) => {
|
const createPanel = (id: string) =>
|
||||||
const partial: Partial<IDockviewPanel> = {
|
fromPartial<IDockviewPanel>({
|
||||||
id,
|
id,
|
||||||
|
|
||||||
view: {
|
view: {
|
||||||
tab: {
|
tab: {
|
||||||
element: document.createElement('div'),
|
element: document.createElement('div'),
|
||||||
} as any,
|
},
|
||||||
content: {
|
content: {
|
||||||
element: document.createElement('div'),
|
element: document.createElement('div'),
|
||||||
} as any,
|
},
|
||||||
} as any,
|
},
|
||||||
};
|
});
|
||||||
return partial as IDockviewPanel;
|
|
||||||
});
|
|
||||||
|
|
||||||
const panel = new panelMock('test_id');
|
const panel = createPanel('test_id');
|
||||||
cut.openPanel(panel);
|
cut.openPanel(panel);
|
||||||
|
|
||||||
const el = cut.element.querySelector('.tab')!;
|
const el = cut.element.querySelector('.tab')!;
|
||||||
@ -628,21 +626,21 @@ describe('tabsContainer', () => {
|
|||||||
fireEvent(el, event);
|
fireEvent(el, event);
|
||||||
|
|
||||||
// a floating group with a single tab shouldn't be eligible
|
// a floating group with a single tab shouldn't be eligible
|
||||||
expect(preventDefaultSpy).toBeCalledTimes(0);
|
expect(preventDefaultSpy).toHaveBeenCalledTimes(0);
|
||||||
expect(accessor.addFloatingGroup).toBeCalledTimes(0);
|
expect(accessor.addFloatingGroup).toHaveBeenCalledTimes(0);
|
||||||
|
|
||||||
const panel2 = new panelMock('test_id_2');
|
const panel2 = createPanel('test_id_2');
|
||||||
cut.openPanel(panel2);
|
cut.openPanel(panel2);
|
||||||
fireEvent(el, event);
|
fireEvent(el, event);
|
||||||
|
|
||||||
expect(preventDefaultSpy).toBeCalledTimes(1);
|
expect(preventDefaultSpy).toHaveBeenCalledTimes(1);
|
||||||
expect(accessor.addFloatingGroup).toBeCalledTimes(1);
|
expect(accessor.addFloatingGroup).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('pre header actions', () => {
|
test('pre header actions', () => {
|
||||||
const accessorMock = jest.fn<DockviewComponent, []>(() => {
|
const accessorMock = jest.fn<DockviewComponent, []>(() => {
|
||||||
return (<Partial<DockviewComponent>>{
|
return (<Partial<DockviewComponent>>{
|
||||||
options: {},
|
options: { parentElement: document.createElement('div') },
|
||||||
onDidAddPanel: jest.fn(),
|
onDidAddPanel: jest.fn(),
|
||||||
onDidRemovePanel: jest.fn(),
|
onDidRemovePanel: jest.fn(),
|
||||||
element: document.createElement('div'),
|
element: document.createElement('div'),
|
||||||
@ -653,7 +651,7 @@ describe('tabsContainer', () => {
|
|||||||
|
|
||||||
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
|
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
|
||||||
return (<Partial<DockviewGroupPanel>>{
|
return (<Partial<DockviewGroupPanel>>{
|
||||||
api: { location: 'grid' } as any,
|
api: { location: { type: 'grid' } } as any,
|
||||||
model: {} as any,
|
model: {} as any,
|
||||||
}) as DockviewGroupPanel;
|
}) as DockviewGroupPanel;
|
||||||
});
|
});
|
||||||
@ -712,7 +710,7 @@ describe('tabsContainer', () => {
|
|||||||
test('left header actions', () => {
|
test('left header actions', () => {
|
||||||
const accessorMock = jest.fn<DockviewComponent, []>(() => {
|
const accessorMock = jest.fn<DockviewComponent, []>(() => {
|
||||||
return (<Partial<DockviewComponent>>{
|
return (<Partial<DockviewComponent>>{
|
||||||
options: {},
|
options: { parentElement: document.createElement('div') },
|
||||||
onDidAddPanel: jest.fn(),
|
onDidAddPanel: jest.fn(),
|
||||||
onDidRemovePanel: jest.fn(),
|
onDidRemovePanel: jest.fn(),
|
||||||
element: document.createElement('div'),
|
element: document.createElement('div'),
|
||||||
@ -723,7 +721,7 @@ describe('tabsContainer', () => {
|
|||||||
|
|
||||||
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
|
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
|
||||||
return (<Partial<DockviewGroupPanel>>{
|
return (<Partial<DockviewGroupPanel>>{
|
||||||
api: { location: 'grid' } as any,
|
api: { location: { type: 'grid' } } as any,
|
||||||
model: {} as any,
|
model: {} as any,
|
||||||
}) as DockviewGroupPanel;
|
}) as DockviewGroupPanel;
|
||||||
});
|
});
|
||||||
@ -782,7 +780,7 @@ describe('tabsContainer', () => {
|
|||||||
test('right header actions', () => {
|
test('right header actions', () => {
|
||||||
const accessorMock = jest.fn<DockviewComponent, []>(() => {
|
const accessorMock = jest.fn<DockviewComponent, []>(() => {
|
||||||
return (<Partial<DockviewComponent>>{
|
return (<Partial<DockviewComponent>>{
|
||||||
options: {},
|
options: { parentElement: document.createElement('div') },
|
||||||
onDidAddPanel: jest.fn(),
|
onDidAddPanel: jest.fn(),
|
||||||
onDidRemovePanel: jest.fn(),
|
onDidRemovePanel: jest.fn(),
|
||||||
element: document.createElement('div'),
|
element: document.createElement('div'),
|
||||||
@ -793,7 +791,7 @@ describe('tabsContainer', () => {
|
|||||||
|
|
||||||
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
|
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
|
||||||
return (<Partial<DockviewGroupPanel>>{
|
return (<Partial<DockviewGroupPanel>>{
|
||||||
api: { location: 'grid' } as any,
|
api: { location: { type: 'grid' } } as any,
|
||||||
model: {} as any,
|
model: {} as any,
|
||||||
}) as DockviewGroupPanel;
|
}) as DockviewGroupPanel;
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { DockviewComponent } from '../../dockview/dockviewComponent';
|
import { DockviewComponent } from '../../dockview/dockviewComponent';
|
||||||
import {
|
import {
|
||||||
DockviewDropTargets,
|
|
||||||
GroupPanelPartInitParameters,
|
GroupPanelPartInitParameters,
|
||||||
IContentRenderer,
|
IContentRenderer,
|
||||||
ITabRenderer,
|
ITabRenderer,
|
||||||
@ -110,102 +109,109 @@ describe('dockviewComponent', () => {
|
|||||||
window.open = jest.fn(); // not implemented by jest
|
window.open = jest.fn(); // not implemented by jest
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('memory leakage', () => {
|
// describe('memory leakage', () => {
|
||||||
test('event leakage', () => {
|
// beforeEach(() => {
|
||||||
Emitter.setLeakageMonitorEnabled(true);
|
// window.open = () => fromPartial<Window>({
|
||||||
|
// addEventListener: jest.fn(),
|
||||||
|
// close: jest.fn(),
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
dockview = new DockviewComponent({
|
// test('event leakage', () => {
|
||||||
parentElement: container,
|
// Emitter.setLeakageMonitorEnabled(true);
|
||||||
components: {
|
|
||||||
default: PanelContentPartTest,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
dockview.layout(500, 1000);
|
// dockview = new DockviewComponent({
|
||||||
|
// parentElement: container,
|
||||||
|
// components: {
|
||||||
|
// default: PanelContentPartTest,
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
|
||||||
const panel1 = dockview.addPanel({
|
// dockview.layout(500, 1000);
|
||||||
id: 'panel1',
|
|
||||||
component: 'default',
|
|
||||||
});
|
|
||||||
|
|
||||||
const panel2 = dockview.addPanel({
|
// const panel1 = dockview.addPanel({
|
||||||
id: 'panel2',
|
// id: 'panel1',
|
||||||
component: 'default',
|
// component: 'default',
|
||||||
});
|
// });
|
||||||
|
|
||||||
dockview.removePanel(panel2);
|
// const panel2 = dockview.addPanel({
|
||||||
|
// id: 'panel2',
|
||||||
|
// component: 'default',
|
||||||
|
// });
|
||||||
|
|
||||||
const panel3 = dockview.addPanel({
|
// dockview.removePanel(panel2);
|
||||||
id: 'panel3',
|
|
||||||
component: 'default',
|
|
||||||
position: {
|
|
||||||
direction: 'right',
|
|
||||||
referencePanel: 'panel1',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const panel4 = dockview.addPanel({
|
// const panel3 = dockview.addPanel({
|
||||||
id: 'panel4',
|
// id: 'panel3',
|
||||||
component: 'default',
|
// component: 'default',
|
||||||
position: {
|
// position: {
|
||||||
direction: 'above',
|
// direction: 'right',
|
||||||
},
|
// referencePanel: 'panel1',
|
||||||
});
|
// },
|
||||||
|
// });
|
||||||
|
|
||||||
dockview.moveGroupOrPanel(
|
// const panel4 = dockview.addPanel({
|
||||||
panel4.group,
|
// id: 'panel4',
|
||||||
panel3.group.id,
|
// component: 'default',
|
||||||
panel3.id,
|
// position: {
|
||||||
'center'
|
// direction: 'above',
|
||||||
);
|
// },
|
||||||
|
// });
|
||||||
|
|
||||||
dockview.addPanel({
|
// dockview.moveGroupOrPanel(
|
||||||
id: 'panel5',
|
// panel4.group,
|
||||||
component: 'default',
|
// panel3.group.id,
|
||||||
floating: true,
|
// panel3.id,
|
||||||
});
|
// 'center'
|
||||||
|
// );
|
||||||
|
|
||||||
const panel6 = dockview.addPanel({
|
// dockview.addPanel({
|
||||||
id: 'panel6',
|
// id: 'panel5',
|
||||||
component: 'default',
|
// component: 'default',
|
||||||
position: {
|
// floating: true,
|
||||||
referencePanel: 'panel5',
|
// });
|
||||||
direction: 'within',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
dockview.addFloatingGroup(panel4.api.group);
|
// const panel6 = dockview.addPanel({
|
||||||
|
// id: 'panel6',
|
||||||
|
// component: 'default',
|
||||||
|
// position: {
|
||||||
|
// referencePanel: 'panel5',
|
||||||
|
// direction: 'within',
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
|
||||||
dockview.addPopoutGroup(panel6);
|
// dockview.addFloatingGroup(panel4.api.group);
|
||||||
|
|
||||||
dockview.moveGroupOrPanel(
|
// dockview.addPopoutGroup(panel6);
|
||||||
panel1.group,
|
|
||||||
panel6.group.id,
|
|
||||||
panel6.id,
|
|
||||||
'center'
|
|
||||||
);
|
|
||||||
|
|
||||||
dockview.moveGroupOrPanel(
|
// dockview.moveGroupOrPanel(
|
||||||
panel4.group,
|
// panel1.group,
|
||||||
panel6.group.id,
|
// panel6.group.id,
|
||||||
panel6.id,
|
// panel6.id,
|
||||||
'center'
|
// 'center'
|
||||||
);
|
// );
|
||||||
|
|
||||||
dockview.dispose();
|
// dockview.moveGroupOrPanel(
|
||||||
|
// panel4.group,
|
||||||
|
// panel6.group.id,
|
||||||
|
// panel6.id,
|
||||||
|
// 'center'
|
||||||
|
// );
|
||||||
|
|
||||||
if (Emitter.MEMORY_LEAK_WATCHER.size > 0) {
|
// dockview.dispose();
|
||||||
for (const entry of Array.from(
|
|
||||||
Emitter.MEMORY_LEAK_WATCHER.events
|
|
||||||
)) {
|
|
||||||
console.log('disposal', entry[1]);
|
|
||||||
}
|
|
||||||
throw new Error('not all listeners disposed');
|
|
||||||
}
|
|
||||||
|
|
||||||
Emitter.setLeakageMonitorEnabled(false);
|
// if (Emitter.MEMORY_LEAK_WATCHER.size > 0) {
|
||||||
});
|
// for (const entry of Array.from(
|
||||||
});
|
// Emitter.MEMORY_LEAK_WATCHER.events
|
||||||
|
// )) {
|
||||||
|
// console.log('disposal', entry[1]);
|
||||||
|
// }
|
||||||
|
// throw new Error('not all listeners disposed');
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Emitter.setLeakageMonitorEnabled(false);
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
test('duplicate panel', () => {
|
test('duplicate panel', () => {
|
||||||
dockview.layout(500, 1000);
|
dockview.layout(500, 1000);
|
||||||
@ -2967,7 +2973,7 @@ describe('dockviewComponent', () => {
|
|||||||
expect(showDndOverlay).toHaveBeenCalledWith({
|
expect(showDndOverlay).toHaveBeenCalledWith({
|
||||||
nativeEvent: eventLeft,
|
nativeEvent: eventLeft,
|
||||||
position: 'left',
|
position: 'left',
|
||||||
target: DockviewDropTargets.Edge,
|
target: 'edge',
|
||||||
getData: getPanelData,
|
getData: getPanelData,
|
||||||
});
|
});
|
||||||
expect(showDndOverlay).toBeCalledTimes(1);
|
expect(showDndOverlay).toBeCalledTimes(1);
|
||||||
@ -2986,7 +2992,7 @@ describe('dockviewComponent', () => {
|
|||||||
expect(showDndOverlay).toHaveBeenCalledWith({
|
expect(showDndOverlay).toHaveBeenCalledWith({
|
||||||
nativeEvent: eventRight,
|
nativeEvent: eventRight,
|
||||||
position: 'right',
|
position: 'right',
|
||||||
target: DockviewDropTargets.Edge,
|
target: 'edge',
|
||||||
getData: getPanelData,
|
getData: getPanelData,
|
||||||
});
|
});
|
||||||
expect(showDndOverlay).toBeCalledTimes(2);
|
expect(showDndOverlay).toBeCalledTimes(2);
|
||||||
@ -3005,7 +3011,7 @@ describe('dockviewComponent', () => {
|
|||||||
expect(showDndOverlay).toHaveBeenCalledWith({
|
expect(showDndOverlay).toHaveBeenCalledWith({
|
||||||
nativeEvent: eventTop,
|
nativeEvent: eventTop,
|
||||||
position: 'top',
|
position: 'top',
|
||||||
target: DockviewDropTargets.Edge,
|
target: 'edge',
|
||||||
getData: getPanelData,
|
getData: getPanelData,
|
||||||
});
|
});
|
||||||
expect(showDndOverlay).toBeCalledTimes(3);
|
expect(showDndOverlay).toBeCalledTimes(3);
|
||||||
@ -3024,7 +3030,7 @@ describe('dockviewComponent', () => {
|
|||||||
expect(showDndOverlay).toHaveBeenCalledWith({
|
expect(showDndOverlay).toHaveBeenCalledWith({
|
||||||
nativeEvent: eventBottom,
|
nativeEvent: eventBottom,
|
||||||
position: 'bottom',
|
position: 'bottom',
|
||||||
target: DockviewDropTargets.Edge,
|
target: 'edge',
|
||||||
getData: getPanelData,
|
getData: getPanelData,
|
||||||
});
|
});
|
||||||
expect(showDndOverlay).toBeCalledTimes(4);
|
expect(showDndOverlay).toBeCalledTimes(4);
|
||||||
@ -3060,7 +3066,7 @@ describe('dockviewComponent', () => {
|
|||||||
expect(showDndOverlay).toHaveBeenCalledWith({
|
expect(showDndOverlay).toHaveBeenCalledWith({
|
||||||
nativeEvent: eventTop,
|
nativeEvent: eventTop,
|
||||||
position: 'center',
|
position: 'center',
|
||||||
target: DockviewDropTargets.Edge,
|
target: 'edge',
|
||||||
getData: getPanelData,
|
getData: getPanelData,
|
||||||
});
|
});
|
||||||
expect(showDndOverlay).toBeCalledTimes(5);
|
expect(showDndOverlay).toBeCalledTimes(5);
|
||||||
@ -3452,8 +3458,8 @@ describe('dockviewComponent', () => {
|
|||||||
floating: true,
|
floating: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('floating');
|
expect(panel2.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
|
|
||||||
@ -3464,8 +3470,8 @@ describe('dockviewComponent', () => {
|
|||||||
'right'
|
'right'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('grid');
|
expect(panel2.group.api.location.type).toBe('grid');
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
});
|
});
|
||||||
@ -3497,8 +3503,8 @@ describe('dockviewComponent', () => {
|
|||||||
floating: true,
|
floating: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('floating');
|
expect(panel2.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
|
|
||||||
@ -3509,8 +3515,8 @@ describe('dockviewComponent', () => {
|
|||||||
'center'
|
'center'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('grid');
|
expect(panel2.group.api.location.type).toBe('grid');
|
||||||
expect(dockview.groups.length).toBe(1);
|
expect(dockview.groups.length).toBe(1);
|
||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
});
|
});
|
||||||
@ -3548,9 +3554,9 @@ describe('dockviewComponent', () => {
|
|||||||
floating: true,
|
floating: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('floating');
|
expect(panel2.group.api.location.type).toBe('floating');
|
||||||
expect(panel3.group.api.location).toBe('floating');
|
expect(panel3.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(3);
|
expect(dockview.groups.length).toBe(3);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
|
|
||||||
@ -3561,9 +3567,9 @@ describe('dockviewComponent', () => {
|
|||||||
'center'
|
'center'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('floating');
|
expect(panel2.group.api.location.type).toBe('floating');
|
||||||
expect(panel3.group.api.location).toBe('floating');
|
expect(panel3.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
});
|
});
|
||||||
@ -3601,9 +3607,9 @@ describe('dockviewComponent', () => {
|
|||||||
position: { referencePanel: panel2 },
|
position: { referencePanel: panel2 },
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('floating');
|
expect(panel2.group.api.location.type).toBe('floating');
|
||||||
expect(panel3.group.api.location).toBe('floating');
|
expect(panel3.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
|
|
||||||
@ -3614,9 +3620,9 @@ describe('dockviewComponent', () => {
|
|||||||
'right'
|
'right'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('grid');
|
expect(panel2.group.api.location.type).toBe('grid');
|
||||||
expect(panel3.group.api.location).toBe('grid');
|
expect(panel3.group.api.location.type).toBe('grid');
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
});
|
});
|
||||||
@ -3654,9 +3660,9 @@ describe('dockviewComponent', () => {
|
|||||||
position: { referencePanel: panel2 },
|
position: { referencePanel: panel2 },
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('floating');
|
expect(panel2.group.api.location.type).toBe('floating');
|
||||||
expect(panel3.group.api.location).toBe('floating');
|
expect(panel3.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
|
|
||||||
@ -3667,9 +3673,9 @@ describe('dockviewComponent', () => {
|
|||||||
'center'
|
'center'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('grid');
|
expect(panel2.group.api.location.type).toBe('grid');
|
||||||
expect(panel3.group.api.location).toBe('grid');
|
expect(panel3.group.api.location.type).toBe('grid');
|
||||||
expect(dockview.groups.length).toBe(1);
|
expect(dockview.groups.length).toBe(1);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
});
|
});
|
||||||
@ -3713,10 +3719,10 @@ describe('dockviewComponent', () => {
|
|||||||
floating: true,
|
floating: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('floating');
|
expect(panel2.group.api.location.type).toBe('floating');
|
||||||
expect(panel3.group.api.location).toBe('floating');
|
expect(panel3.group.api.location.type).toBe('floating');
|
||||||
expect(panel4.group.api.location).toBe('floating');
|
expect(panel4.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(3);
|
expect(dockview.groups.length).toBe(3);
|
||||||
expect(dockview.panels.length).toBe(4);
|
expect(dockview.panels.length).toBe(4);
|
||||||
|
|
||||||
@ -3727,10 +3733,10 @@ describe('dockviewComponent', () => {
|
|||||||
'center'
|
'center'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('floating');
|
expect(panel2.group.api.location.type).toBe('floating');
|
||||||
expect(panel3.group.api.location).toBe('floating');
|
expect(panel3.group.api.location.type).toBe('floating');
|
||||||
expect(panel4.group.api.location).toBe('floating');
|
expect(panel4.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(4);
|
expect(dockview.panels.length).toBe(4);
|
||||||
});
|
});
|
||||||
@ -3762,8 +3768,8 @@ describe('dockviewComponent', () => {
|
|||||||
floating: true,
|
floating: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('floating');
|
expect(panel2.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
|
|
||||||
@ -3774,8 +3780,8 @@ describe('dockviewComponent', () => {
|
|||||||
'right'
|
'right'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('grid');
|
expect(panel2.group.api.location.type).toBe('grid');
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
});
|
});
|
||||||
@ -3807,8 +3813,8 @@ describe('dockviewComponent', () => {
|
|||||||
floating: true,
|
floating: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('floating');
|
expect(panel2.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
|
|
||||||
@ -3819,8 +3825,8 @@ describe('dockviewComponent', () => {
|
|||||||
'center'
|
'center'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('grid');
|
expect(panel2.group.api.location.type).toBe('grid');
|
||||||
expect(dockview.groups.length).toBe(1);
|
expect(dockview.groups.length).toBe(1);
|
||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
});
|
});
|
||||||
@ -3858,9 +3864,9 @@ describe('dockviewComponent', () => {
|
|||||||
floating: true,
|
floating: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('floating');
|
expect(panel2.group.api.location.type).toBe('floating');
|
||||||
expect(panel3.group.api.location).toBe('floating');
|
expect(panel3.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(3);
|
expect(dockview.groups.length).toBe(3);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
|
|
||||||
@ -3871,9 +3877,9 @@ describe('dockviewComponent', () => {
|
|||||||
'center'
|
'center'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('floating');
|
expect(panel2.group.api.location.type).toBe('floating');
|
||||||
expect(panel3.group.api.location).toBe('floating');
|
expect(panel3.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
});
|
});
|
||||||
@ -3911,9 +3917,9 @@ describe('dockviewComponent', () => {
|
|||||||
position: { referencePanel: panel2 },
|
position: { referencePanel: panel2 },
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('floating');
|
expect(panel2.group.api.location.type).toBe('floating');
|
||||||
expect(panel3.group.api.location).toBe('floating');
|
expect(panel3.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
|
|
||||||
@ -3924,9 +3930,9 @@ describe('dockviewComponent', () => {
|
|||||||
'right'
|
'right'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('grid');
|
expect(panel2.group.api.location.type).toBe('grid');
|
||||||
expect(panel3.group.api.location).toBe('floating');
|
expect(panel3.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(3);
|
expect(dockview.groups.length).toBe(3);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
});
|
});
|
||||||
@ -3964,9 +3970,9 @@ describe('dockviewComponent', () => {
|
|||||||
position: { referencePanel: panel2 },
|
position: { referencePanel: panel2 },
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('floating');
|
expect(panel2.group.api.location.type).toBe('floating');
|
||||||
expect(panel3.group.api.location).toBe('floating');
|
expect(panel3.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
|
|
||||||
@ -3977,9 +3983,9 @@ describe('dockviewComponent', () => {
|
|||||||
'center'
|
'center'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('grid');
|
expect(panel2.group.api.location.type).toBe('grid');
|
||||||
expect(panel3.group.api.location).toBe('floating');
|
expect(panel3.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
});
|
});
|
||||||
@ -4023,10 +4029,10 @@ describe('dockviewComponent', () => {
|
|||||||
floating: true,
|
floating: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('floating');
|
expect(panel2.group.api.location.type).toBe('floating');
|
||||||
expect(panel3.group.api.location).toBe('floating');
|
expect(panel3.group.api.location.type).toBe('floating');
|
||||||
expect(panel4.group.api.location).toBe('floating');
|
expect(panel4.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(3);
|
expect(dockview.groups.length).toBe(3);
|
||||||
expect(dockview.panels.length).toBe(4);
|
expect(dockview.panels.length).toBe(4);
|
||||||
|
|
||||||
@ -4037,10 +4043,10 @@ describe('dockviewComponent', () => {
|
|||||||
'center'
|
'center'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('floating');
|
expect(panel2.group.api.location.type).toBe('floating');
|
||||||
expect(panel3.group.api.location).toBe('floating');
|
expect(panel3.group.api.location.type).toBe('floating');
|
||||||
expect(panel4.group.api.location).toBe('floating');
|
expect(panel4.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(3);
|
expect(dockview.groups.length).toBe(3);
|
||||||
expect(dockview.panels.length).toBe(4);
|
expect(dockview.panels.length).toBe(4);
|
||||||
});
|
});
|
||||||
@ -4078,9 +4084,9 @@ describe('dockviewComponent', () => {
|
|||||||
floating: true,
|
floating: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('grid');
|
expect(panel2.group.api.location.type).toBe('grid');
|
||||||
expect(panel3.group.api.location).toBe('floating');
|
expect(panel3.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(3);
|
expect(dockview.groups.length).toBe(3);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
|
|
||||||
@ -4091,9 +4097,9 @@ describe('dockviewComponent', () => {
|
|||||||
'center'
|
'center'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('floating');
|
expect(panel1.group.api.location.type).toBe('floating');
|
||||||
expect(panel2.group.api.location).toBe('grid');
|
expect(panel2.group.api.location.type).toBe('grid');
|
||||||
expect(panel3.group.api.location).toBe('floating');
|
expect(panel3.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
});
|
});
|
||||||
@ -4130,9 +4136,9 @@ describe('dockviewComponent', () => {
|
|||||||
floating: true,
|
floating: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('grid');
|
expect(panel2.group.api.location.type).toBe('grid');
|
||||||
expect(panel3.group.api.location).toBe('floating');
|
expect(panel3.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
|
|
||||||
@ -4143,9 +4149,9 @@ describe('dockviewComponent', () => {
|
|||||||
'center'
|
'center'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('floating');
|
expect(panel1.group.api.location.type).toBe('floating');
|
||||||
expect(panel2.group.api.location).toBe('grid');
|
expect(panel2.group.api.location.type).toBe('grid');
|
||||||
expect(panel3.group.api.location).toBe('floating');
|
expect(panel3.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
});
|
});
|
||||||
@ -4183,9 +4189,9 @@ describe('dockviewComponent', () => {
|
|||||||
floating: true,
|
floating: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('grid');
|
expect(panel2.group.api.location.type).toBe('grid');
|
||||||
expect(panel3.group.api.location).toBe('floating');
|
expect(panel3.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(3);
|
expect(dockview.groups.length).toBe(3);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
|
|
||||||
@ -4196,9 +4202,9 @@ describe('dockviewComponent', () => {
|
|||||||
'center'
|
'center'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('floating');
|
expect(panel1.group.api.location.type).toBe('floating');
|
||||||
expect(panel2.group.api.location).toBe('grid');
|
expect(panel2.group.api.location.type).toBe('grid');
|
||||||
expect(panel3.group.api.location).toBe('floating');
|
expect(panel3.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
});
|
});
|
||||||
@ -4235,9 +4241,9 @@ describe('dockviewComponent', () => {
|
|||||||
floating: true,
|
floating: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('grid');
|
expect(panel2.group.api.location.type).toBe('grid');
|
||||||
expect(panel3.group.api.location).toBe('floating');
|
expect(panel3.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
|
|
||||||
@ -4248,9 +4254,9 @@ describe('dockviewComponent', () => {
|
|||||||
'center'
|
'center'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('floating');
|
expect(panel1.group.api.location.type).toBe('floating');
|
||||||
expect(panel2.group.api.location).toBe('floating');
|
expect(panel2.group.api.location.type).toBe('floating');
|
||||||
expect(panel3.group.api.location).toBe('floating');
|
expect(panel3.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(1);
|
expect(dockview.groups.length).toBe(1);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
});
|
});
|
||||||
@ -4282,15 +4288,15 @@ describe('dockviewComponent', () => {
|
|||||||
position: { direction: 'right' },
|
position: { direction: 'right' },
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('grid');
|
expect(panel2.group.api.location.type).toBe('grid');
|
||||||
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.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('floating');
|
expect(panel2.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
});
|
});
|
||||||
@ -4321,15 +4327,15 @@ describe('dockviewComponent', () => {
|
|||||||
component: 'default',
|
component: 'default',
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('grid');
|
expect(panel2.group.api.location.type).toBe('grid');
|
||||||
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.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('floating');
|
expect(panel2.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
});
|
});
|
||||||
@ -4361,15 +4367,15 @@ describe('dockviewComponent', () => {
|
|||||||
position: { direction: 'right' },
|
position: { direction: 'right' },
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('grid');
|
expect(panel2.group.api.location.type).toBe('grid');
|
||||||
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.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('floating');
|
expect(panel2.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
});
|
});
|
||||||
@ -4400,55 +4406,41 @@ describe('dockviewComponent', () => {
|
|||||||
component: 'default',
|
component: 'default',
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('grid');
|
expect(panel2.group.api.location.type).toBe('grid');
|
||||||
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.api.location).toBe('floating');
|
expect(panel1.group.api.location.type).toBe('floating');
|
||||||
expect(panel2.group.api.location).toBe('floating');
|
expect(panel2.group.api.location.type).toBe('floating');
|
||||||
expect(dockview.groups.length).toBe(1);
|
expect(dockview.groups.length).toBe(1);
|
||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('popout group', () => {
|
describe('popout group', () => {
|
||||||
test('that can remove a popout group', () => {
|
beforeEach(() => {
|
||||||
const container = document.createElement('div');
|
jest.spyOn(window, 'open').mockReturnValue(
|
||||||
|
fromPartial<Window>({
|
||||||
const dockview = new DockviewComponent({
|
document: fromPartial<Document>({
|
||||||
parentElement: container,
|
body: document.createElement('body'),
|
||||||
components: {
|
}),
|
||||||
default: PanelContentPartTest,
|
addEventListener: jest
|
||||||
},
|
.fn()
|
||||||
tabComponents: {
|
.mockImplementation((name, cb) => {
|
||||||
test_tab_id: PanelTabPartTest,
|
if (name === 'load') {
|
||||||
},
|
cb();
|
||||||
orientation: Orientation.HORIZONTAL,
|
}
|
||||||
});
|
}),
|
||||||
|
removeEventListener: jest.fn(),
|
||||||
dockview.layout(1000, 500);
|
close: jest.fn(),
|
||||||
|
})
|
||||||
const panel1 = dockview.addPanel({
|
);
|
||||||
id: 'panel_1',
|
|
||||||
component: 'default',
|
|
||||||
});
|
|
||||||
|
|
||||||
dockview.addPopoutGroup(panel1);
|
|
||||||
|
|
||||||
expect(dockview.panels.length).toBe(1);
|
|
||||||
expect(dockview.groups.length).toBe(1);
|
|
||||||
expect(panel1.api.group.api.location).toBe('popout');
|
|
||||||
|
|
||||||
dockview.removePanel(panel1);
|
|
||||||
|
|
||||||
expect(dockview.panels.length).toBe(0);
|
|
||||||
expect(dockview.groups.length).toBe(0);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('add a popout group', () => {
|
test('add a popout group', async () => {
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
|
|
||||||
const dockview = new DockviewComponent({
|
const dockview = new DockviewComponent({
|
||||||
@ -4474,20 +4466,53 @@ describe('dockviewComponent', () => {
|
|||||||
component: 'default',
|
component: 'default',
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('grid');
|
expect(panel2.group.api.location.type).toBe('grid');
|
||||||
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.addPopoutGroup(panel2.group);
|
await dockview.addPopoutGroup(panel2.group);
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('popout');
|
expect(panel1.group.api.location.type).toBe('popout');
|
||||||
expect(panel2.group.api.location).toBe('popout');
|
expect(panel2.group.api.location.type).toBe('popout');
|
||||||
expect(dockview.groups.length).toBe(1);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(2);
|
expect(dockview.panels.length).toBe(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('move from fixed to popout group and back', () => {
|
test('that can remove a popout group', async () => {
|
||||||
|
const container = document.createElement('div');
|
||||||
|
|
||||||
|
const dockview = new DockviewComponent({
|
||||||
|
parentElement: container,
|
||||||
|
components: {
|
||||||
|
default: PanelContentPartTest,
|
||||||
|
},
|
||||||
|
tabComponents: {
|
||||||
|
test_tab_id: PanelTabPartTest,
|
||||||
|
},
|
||||||
|
orientation: Orientation.HORIZONTAL,
|
||||||
|
});
|
||||||
|
|
||||||
|
dockview.layout(1000, 500);
|
||||||
|
|
||||||
|
const panel1 = dockview.addPanel({
|
||||||
|
id: 'panel_1',
|
||||||
|
component: 'default',
|
||||||
|
});
|
||||||
|
|
||||||
|
await dockview.addPopoutGroup(panel1);
|
||||||
|
|
||||||
|
expect(dockview.panels.length).toBe(1);
|
||||||
|
expect(dockview.groups.length).toBe(2);
|
||||||
|
expect(panel1.api.group.api.location.type).toBe('popout');
|
||||||
|
|
||||||
|
dockview.removePanel(panel1);
|
||||||
|
|
||||||
|
expect(dockview.panels.length).toBe(0);
|
||||||
|
expect(dockview.groups.length).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('move from fixed to popout group and back', async () => {
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
|
|
||||||
const dockview = new DockviewComponent({
|
const dockview = new DockviewComponent({
|
||||||
@ -4521,18 +4546,18 @@ describe('dockviewComponent', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('grid');
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
expect(panel2.group.api.location).toBe('grid');
|
expect(panel2.group.api.location.type).toBe('grid');
|
||||||
expect(panel3.group.api.location).toBe('grid');
|
expect(panel3.group.api.location.type).toBe('grid');
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
|
|
||||||
dockview.addPopoutGroup(panel2.group);
|
await dockview.addPopoutGroup(panel2.group);
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('popout');
|
expect(panel1.group.api.location.type).toBe('popout');
|
||||||
expect(panel2.group.api.location).toBe('popout');
|
expect(panel2.group.api.location.type).toBe('popout');
|
||||||
expect(panel3.group.api.location).toBe('grid');
|
expect(panel3.group.api.location.type).toBe('grid');
|
||||||
expect(dockview.groups.length).toBe(2);
|
expect(dockview.groups.length).toBe(3);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
|
|
||||||
dockview.moveGroupOrPanel(
|
dockview.moveGroupOrPanel(
|
||||||
@ -4542,10 +4567,23 @@ describe('dockviewComponent', () => {
|
|||||||
'right'
|
'right'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(panel1.group.api.location).toBe('popout');
|
expect(panel1.group.api.location.type).toBe('popout');
|
||||||
expect(panel2.group.api.location).toBe('grid');
|
expect(panel2.group.api.location.type).toBe('grid');
|
||||||
expect(panel3.group.api.location).toBe('grid');
|
expect(panel3.group.api.location.type).toBe('grid');
|
||||||
expect(dockview.groups.length).toBe(3);
|
expect(dockview.groups.length).toBe(4);
|
||||||
|
expect(dockview.panels.length).toBe(3);
|
||||||
|
|
||||||
|
dockview.moveGroupOrPanel(
|
||||||
|
panel3.api.group,
|
||||||
|
panel1.api.group.id,
|
||||||
|
panel1.api.id,
|
||||||
|
'center'
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(panel1.group.api.location.type).toBe('grid');
|
||||||
|
expect(panel2.group.api.location.type).toBe('grid');
|
||||||
|
expect(panel3.group.api.location.type).toBe('grid');
|
||||||
|
expect(dockview.groups.length).toBe(2);
|
||||||
expect(dockview.panels.length).toBe(3);
|
expect(dockview.panels.length).toBe(3);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -243,7 +243,7 @@ describe('dockviewGroupPanelModel', () => {
|
|||||||
options = {};
|
options = {};
|
||||||
|
|
||||||
dockview = (<Partial<DockviewComponent>>{
|
dockview = (<Partial<DockviewComponent>>{
|
||||||
options: {},
|
options: { parentElement: document.createElement('div') },
|
||||||
createWatermarkComponent: () => new Watermark(),
|
createWatermarkComponent: () => new Watermark(),
|
||||||
doSetGroupActive: jest.fn(),
|
doSetGroupActive: jest.fn(),
|
||||||
id: 'dockview-1',
|
id: 'dockview-1',
|
||||||
@ -639,6 +639,7 @@ describe('dockviewGroupPanelModel', () => {
|
|||||||
id: 'testcomponentid',
|
id: 'testcomponentid',
|
||||||
options: {
|
options: {
|
||||||
showDndOverlay: jest.fn(),
|
showDndOverlay: jest.fn(),
|
||||||
|
parentElement: document.createElement('div'),
|
||||||
},
|
},
|
||||||
getPanel: jest.fn(),
|
getPanel: jest.fn(),
|
||||||
onDidAddPanel: jest.fn(),
|
onDidAddPanel: jest.fn(),
|
||||||
@ -699,6 +700,7 @@ describe('dockviewGroupPanelModel', () => {
|
|||||||
id: 'testcomponentid',
|
id: 'testcomponentid',
|
||||||
options: {
|
options: {
|
||||||
showDndOverlay: () => true,
|
showDndOverlay: () => true,
|
||||||
|
parentElement: document.createElement('div'),
|
||||||
},
|
},
|
||||||
getPanel: jest.fn(),
|
getPanel: jest.fn(),
|
||||||
onDidAddPanel: jest.fn(),
|
onDidAddPanel: jest.fn(),
|
||||||
@ -790,6 +792,7 @@ describe('dockviewGroupPanelModel', () => {
|
|||||||
id: 'testcomponentid',
|
id: 'testcomponentid',
|
||||||
options: {
|
options: {
|
||||||
showDndOverlay: jest.fn(),
|
showDndOverlay: jest.fn(),
|
||||||
|
parentElement: document.createElement('div'),
|
||||||
},
|
},
|
||||||
getPanel: jest.fn(),
|
getPanel: jest.fn(),
|
||||||
doSetGroupActive: jest.fn(),
|
doSetGroupActive: jest.fn(),
|
||||||
@ -863,6 +866,7 @@ describe('dockviewGroupPanelModel', () => {
|
|||||||
id: 'testcomponentid',
|
id: 'testcomponentid',
|
||||||
options: {
|
options: {
|
||||||
showDndOverlay: jest.fn(),
|
showDndOverlay: jest.fn(),
|
||||||
|
parentElement: document.createElement('div'),
|
||||||
},
|
},
|
||||||
getPanel: jest.fn(),
|
getPanel: jest.fn(),
|
||||||
doSetGroupActive: jest.fn(),
|
doSetGroupActive: jest.fn(),
|
||||||
@ -941,6 +945,7 @@ describe('dockviewGroupPanelModel', () => {
|
|||||||
id: 'testcomponentid',
|
id: 'testcomponentid',
|
||||||
options: {
|
options: {
|
||||||
showDndOverlay: jest.fn(),
|
showDndOverlay: jest.fn(),
|
||||||
|
parentElement: document.createElement('div'),
|
||||||
},
|
},
|
||||||
getPanel: jest.fn(),
|
getPanel: jest.fn(),
|
||||||
doSetGroupActive: jest.fn(),
|
doSetGroupActive: jest.fn(),
|
||||||
|
@ -38,6 +38,7 @@ describe('dockviewGroupPanel', () => {
|
|||||||
accessorMock = jest.fn<DockviewComponent, []>(() => {
|
accessorMock = jest.fn<DockviewComponent, []>(() => {
|
||||||
const partial: Partial<DockviewComponent> = {
|
const partial: Partial<DockviewComponent> = {
|
||||||
options: {
|
options: {
|
||||||
|
parentElement: document.createElement('div'),
|
||||||
components: {
|
components: {
|
||||||
contentComponent: contentMock,
|
contentComponent: contentMock,
|
||||||
},
|
},
|
||||||
@ -131,6 +132,7 @@ describe('dockviewGroupPanel', () => {
|
|||||||
accessorMock = jest.fn<DockviewComponent, []>(() => {
|
accessorMock = jest.fn<DockviewComponent, []>(() => {
|
||||||
const partial: Partial<DockviewComponent> = {
|
const partial: Partial<DockviewComponent> = {
|
||||||
options: {
|
options: {
|
||||||
|
parentElement: document.createElement('div'),
|
||||||
components: {
|
components: {
|
||||||
contentComponent: contentMock,
|
contentComponent: contentMock,
|
||||||
},
|
},
|
||||||
@ -159,6 +161,7 @@ describe('dockviewGroupPanel', () => {
|
|||||||
accessorMock = jest.fn<DockviewComponent, []>(() => {
|
accessorMock = jest.fn<DockviewComponent, []>(() => {
|
||||||
const partial: Partial<DockviewComponent> = {
|
const partial: Partial<DockviewComponent> = {
|
||||||
options: {
|
options: {
|
||||||
|
parentElement: document.createElement('div'),
|
||||||
components: {
|
components: {
|
||||||
contentComponent: contentMock,
|
contentComponent: contentMock,
|
||||||
},
|
},
|
||||||
@ -190,6 +193,7 @@ describe('dockviewGroupPanel', () => {
|
|||||||
accessorMock = jest.fn<DockviewComponent, []>(() => {
|
accessorMock = jest.fn<DockviewComponent, []>(() => {
|
||||||
const partial: Partial<DockviewComponent> = {
|
const partial: Partial<DockviewComponent> = {
|
||||||
options: {
|
options: {
|
||||||
|
parentElement: document.createElement('div'),
|
||||||
components: {
|
components: {
|
||||||
contentComponent: contentMock,
|
contentComponent: contentMock,
|
||||||
},
|
},
|
||||||
@ -222,6 +226,7 @@ describe('dockviewGroupPanel', () => {
|
|||||||
accessorMock = jest.fn<DockviewComponent, []>(() => {
|
accessorMock = jest.fn<DockviewComponent, []>(() => {
|
||||||
const partial: Partial<DockviewComponent> = {
|
const partial: Partial<DockviewComponent> = {
|
||||||
options: {
|
options: {
|
||||||
|
parentElement: document.createElement('div'),
|
||||||
components: {
|
components: {
|
||||||
contentComponent: contentMock,
|
contentComponent: contentMock,
|
||||||
},
|
},
|
||||||
@ -244,6 +249,7 @@ describe('dockviewGroupPanel', () => {
|
|||||||
accessorMock = jest.fn<DockviewComponent, []>(() => {
|
accessorMock = jest.fn<DockviewComponent, []>(() => {
|
||||||
const partial: Partial<DockviewComponent> = {
|
const partial: Partial<DockviewComponent> = {
|
||||||
options: {
|
options: {
|
||||||
|
parentElement: document.createElement('div'),
|
||||||
components: {
|
components: {
|
||||||
contentComponent: jest.fn().mockImplementation(() => {
|
contentComponent: jest.fn().mockImplementation(() => {
|
||||||
return contentMock;
|
return contentMock;
|
||||||
@ -271,6 +277,7 @@ describe('dockviewGroupPanel', () => {
|
|||||||
accessorMock = jest.fn<DockviewComponent, []>(() => {
|
accessorMock = jest.fn<DockviewComponent, []>(() => {
|
||||||
const partial: Partial<DockviewComponent> = {
|
const partial: Partial<DockviewComponent> = {
|
||||||
options: {
|
options: {
|
||||||
|
parentElement: document.createElement('div'),
|
||||||
frameworkComponents: {
|
frameworkComponents: {
|
||||||
contentComponent: contentMock,
|
contentComponent: contentMock,
|
||||||
},
|
},
|
||||||
|
@ -268,7 +268,7 @@ describe('gridview', () => {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
activePanel: 'panel_1',
|
activePanel: 'panel_2',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ describe('overlayRenderContainer', () => {
|
|||||||
},
|
},
|
||||||
group: {
|
group: {
|
||||||
api: {
|
api: {
|
||||||
location: 'grid',
|
location: { type: 'grid' },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -77,7 +77,7 @@ describe('overlayRenderContainer', () => {
|
|||||||
},
|
},
|
||||||
group: {
|
group: {
|
||||||
api: {
|
api: {
|
||||||
location: 'grid',
|
location: { type: 'grid' },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import {
|
import {
|
||||||
DockviewDropEvent,
|
|
||||||
IDockviewComponent,
|
IDockviewComponent,
|
||||||
SerializedDockview,
|
SerializedDockview,
|
||||||
} from '../dockview/dockviewComponent';
|
} from '../dockview/dockviewComponent';
|
||||||
@ -43,6 +42,11 @@ import {
|
|||||||
TabDragEvent,
|
TabDragEvent,
|
||||||
} from '../dockview/components/titlebar/tabsContainer';
|
} from '../dockview/components/titlebar/tabsContainer';
|
||||||
import { Box } from '../types';
|
import { Box } from '../types';
|
||||||
|
import {
|
||||||
|
DockviewDidDropEvent,
|
||||||
|
DockviewWillDropEvent,
|
||||||
|
WillShowOverlayLocationEvent,
|
||||||
|
} from '../dockview/dockviewGroupPanelModel';
|
||||||
|
|
||||||
export interface CommonApi<T = any> {
|
export interface CommonApi<T = any> {
|
||||||
readonly height: number;
|
readonly height: number;
|
||||||
@ -648,10 +652,27 @@ export class DockviewApi implements CommonApi<SerializedDockview> {
|
|||||||
/**
|
/**
|
||||||
* Invoked when a Drag'n'Drop event occurs that the component was unable to handle. Exposed for custom Drag'n'Drop functionality.
|
* Invoked when a Drag'n'Drop event occurs that the component was unable to handle. Exposed for custom Drag'n'Drop functionality.
|
||||||
*/
|
*/
|
||||||
get onDidDrop(): Event<DockviewDropEvent> {
|
get onDidDrop(): Event<DockviewDidDropEvent> {
|
||||||
return this.component.onDidDrop;
|
return this.component.onDidDrop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when a Drag'n'Drop event occurs but before dockview handles it giving the user an opportunity to intecept and
|
||||||
|
* prevent the event from occuring using the standard `preventDefault()` syntax.
|
||||||
|
*
|
||||||
|
* Preventing certain events may causes unexpected behaviours, use carefully.
|
||||||
|
*/
|
||||||
|
get onWillDrop(): Event<DockviewWillDropEvent> {
|
||||||
|
return this.component.onWillDrop;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
get onWillShowOverlay(): Event<WillShowOverlayLocationEvent> {
|
||||||
|
return this.component.onWillShowOverlay;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked before a group is dragged. Exposed for custom Drag'n'Drop functionality.
|
* Invoked before a group is dragged. Exposed for custom Drag'n'Drop functionality.
|
||||||
*/
|
*/
|
||||||
@ -830,8 +851,10 @@ export class DockviewApi implements CommonApi<SerializedDockview> {
|
|||||||
options?: {
|
options?: {
|
||||||
position?: Box;
|
position?: Box;
|
||||||
popoutUrl?: string;
|
popoutUrl?: string;
|
||||||
|
onDidOpen?: (event: { id: string; window: Window }) => void;
|
||||||
|
onWillClose?: (event: { id: string; window: Window }) => void;
|
||||||
}
|
}
|
||||||
): void {
|
): Promise<void> {
|
||||||
this.component.addPopoutGroup(item, options);
|
return this.component.addPopoutGroup(item, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,10 @@ import { GridviewPanelApi, GridviewPanelApiImpl } from './gridviewPanelApi';
|
|||||||
export interface DockviewGroupPanelApi extends GridviewPanelApi {
|
export interface DockviewGroupPanelApi extends GridviewPanelApi {
|
||||||
readonly onDidLocationChange: Event<DockviewGroupPanelFloatingChangeEvent>;
|
readonly onDidLocationChange: Event<DockviewGroupPanelFloatingChangeEvent>;
|
||||||
readonly location: DockviewGroupLocation;
|
readonly location: DockviewGroupLocation;
|
||||||
|
/**
|
||||||
|
* If you require the Window object
|
||||||
|
*/
|
||||||
|
getWindow(): Window;
|
||||||
moveTo(options: { group?: DockviewGroupPanel; position?: Position }): void;
|
moveTo(options: { group?: DockviewGroupPanel; position?: Position }): void;
|
||||||
maximize(): void;
|
maximize(): void;
|
||||||
isMaximized(): boolean;
|
isMaximized(): boolean;
|
||||||
@ -42,6 +46,12 @@ export class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl {
|
|||||||
this.addDisposables(this._onDidLocationChange);
|
this.addDisposables(this._onDidLocationChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getWindow(): Window {
|
||||||
|
return this.location.type === 'popout'
|
||||||
|
? this.location.getWindow()
|
||||||
|
: window;
|
||||||
|
}
|
||||||
|
|
||||||
moveTo(options: { group?: DockviewGroupPanel; position?: Position }): void {
|
moveTo(options: { group?: DockviewGroupPanel; position?: Position }): void {
|
||||||
if (!this._group) {
|
if (!this._group) {
|
||||||
throw new Error(NOT_INITIALIZED_MESSAGE);
|
throw new Error(NOT_INITIALIZED_MESSAGE);
|
||||||
@ -66,7 +76,7 @@ export class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl {
|
|||||||
throw new Error(NOT_INITIALIZED_MESSAGE);
|
throw new Error(NOT_INITIALIZED_MESSAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.location !== 'grid') {
|
if (this.location.type !== 'grid') {
|
||||||
// only grid groups can be maximized
|
// only grid groups can be maximized
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
import { Emitter, Event } from '../events';
|
import { Emitter, Event } from '../events';
|
||||||
import { GridviewPanelApiImpl, GridviewPanelApi } from './gridviewPanelApi';
|
import { GridviewPanelApiImpl, GridviewPanelApi } from './gridviewPanelApi';
|
||||||
import { DockviewGroupPanel } from '../dockview/dockviewGroupPanel';
|
import { DockviewGroupPanel } from '../dockview/dockviewGroupPanel';
|
||||||
import { MutableDisposable } from '../lifecycle';
|
import { CompositeDisposable, MutableDisposable } from '../lifecycle';
|
||||||
import { DockviewPanel } from '../dockview/dockviewPanel';
|
import { DockviewPanel } from '../dockview/dockviewPanel';
|
||||||
import { DockviewComponent } from '../dockview/dockviewComponent';
|
import { DockviewComponent } from '../dockview/dockviewComponent';
|
||||||
import { Position } from '../dnd/droptarget';
|
import { Position } from '../dnd/droptarget';
|
||||||
import { DockviewPanelRenderer } from '../overlayRenderContainer';
|
import { DockviewPanelRenderer } from '../overlayRenderContainer';
|
||||||
|
import { DockviewGroupPanelFloatingChangeEvent } from './dockviewGroupPanelApi';
|
||||||
|
import { DockviewGroupLocation } from '../dockview/dockviewGroupPanelModel';
|
||||||
|
|
||||||
export interface TitleEvent {
|
export interface TitleEvent {
|
||||||
readonly title: string;
|
readonly title: string;
|
||||||
@ -28,6 +30,8 @@ export interface DockviewPanelApi
|
|||||||
readonly onDidActiveGroupChange: Event<void>;
|
readonly onDidActiveGroupChange: Event<void>;
|
||||||
readonly onDidGroupChange: Event<void>;
|
readonly onDidGroupChange: Event<void>;
|
||||||
readonly onDidRendererChange: Event<RendererChangedEvent>;
|
readonly onDidRendererChange: Event<RendererChangedEvent>;
|
||||||
|
readonly location: DockviewGroupLocation;
|
||||||
|
readonly onDidLocationChange: Event<DockviewGroupPanelFloatingChangeEvent>;
|
||||||
close(): void;
|
close(): void;
|
||||||
setTitle(title: string): void;
|
setTitle(title: string): void;
|
||||||
setRenderer(renderer: DockviewPanelRenderer): void;
|
setRenderer(renderer: DockviewPanelRenderer): void;
|
||||||
@ -39,6 +43,10 @@ export interface DockviewPanelApi
|
|||||||
maximize(): void;
|
maximize(): void;
|
||||||
isMaximized(): boolean;
|
isMaximized(): boolean;
|
||||||
exitMaximized(): void;
|
exitMaximized(): void;
|
||||||
|
/**
|
||||||
|
* If you require the Window object
|
||||||
|
*/
|
||||||
|
getWindow(): Window;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DockviewPanelApiImpl
|
export class DockviewPanelApiImpl
|
||||||
@ -59,7 +67,16 @@ export class DockviewPanelApiImpl
|
|||||||
readonly _onDidRendererChange = new Emitter<RendererChangedEvent>();
|
readonly _onDidRendererChange = new Emitter<RendererChangedEvent>();
|
||||||
readonly onDidRendererChange = this._onDidRendererChange.event;
|
readonly onDidRendererChange = this._onDidRendererChange.event;
|
||||||
|
|
||||||
private readonly disposable = new MutableDisposable();
|
private readonly _onDidLocationChange =
|
||||||
|
new Emitter<DockviewGroupPanelFloatingChangeEvent>();
|
||||||
|
readonly onDidLocationChange: Event<DockviewGroupPanelFloatingChangeEvent> =
|
||||||
|
this._onDidLocationChange.event;
|
||||||
|
|
||||||
|
private readonly groupEventsDisposable = new MutableDisposable();
|
||||||
|
|
||||||
|
get location(): DockviewGroupLocation {
|
||||||
|
return this.group.api.location;
|
||||||
|
}
|
||||||
|
|
||||||
get title(): string | undefined {
|
get title(): string | undefined {
|
||||||
return this.panel.title;
|
return this.panel.title;
|
||||||
@ -81,13 +98,22 @@ export class DockviewPanelApiImpl
|
|||||||
this._onDidGroupChange.fire();
|
this._onDidGroupChange.fire();
|
||||||
|
|
||||||
if (this._group) {
|
if (this._group) {
|
||||||
this.disposable.value = this._group.api.onDidActiveChange(() => {
|
this.groupEventsDisposable.value = new CompositeDisposable(
|
||||||
this._onDidActiveGroupChange.fire();
|
this.group.api.onDidLocationChange((event) => {
|
||||||
});
|
this._onDidLocationChange.fire(event);
|
||||||
|
}),
|
||||||
|
this.group.api.onDidActiveChange(() => {
|
||||||
|
this._onDidActiveGroupChange.fire();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
if (this.isGroupActive !== isOldGroupActive) {
|
if (this.isGroupActive !== isOldGroupActive) {
|
||||||
this._onDidActiveGroupChange.fire();
|
this._onDidActiveGroupChange.fire();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._onDidLocationChange.fire({
|
||||||
|
location: this.group.api.location,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,14 +135,19 @@ export class DockviewPanelApiImpl
|
|||||||
|
|
||||||
|
|
||||||
this.addDisposables(
|
this.addDisposables(
|
||||||
this.disposable,
|
this.groupEventsDisposable,
|
||||||
this._onDidRendererChange,
|
this._onDidRendererChange,
|
||||||
this._onDidTitleChange,
|
this._onDidTitleChange,
|
||||||
this._onDidGroupChange,
|
this._onDidGroupChange,
|
||||||
this._onDidActiveGroupChange
|
this._onDidActiveGroupChange,
|
||||||
|
this._onDidLocationChange
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getWindow(): Window {
|
||||||
|
return this.group.api.getWindow();
|
||||||
|
}
|
||||||
|
|
||||||
moveTo(options: {
|
moveTo(options: {
|
||||||
group: DockviewGroupPanel;
|
group: DockviewGroupPanel;
|
||||||
position?: Position;
|
position?: Position;
|
||||||
|
@ -14,6 +14,10 @@ export interface VisibilityEvent {
|
|||||||
readonly isVisible: boolean;
|
readonly isVisible: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface HiddenEvent {
|
||||||
|
readonly isHidden: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ActiveEvent {
|
export interface ActiveEvent {
|
||||||
readonly isActive: boolean;
|
readonly isActive: boolean;
|
||||||
}
|
}
|
||||||
@ -24,7 +28,7 @@ export interface PanelApi {
|
|||||||
readonly onDidFocusChange: Event<FocusEvent>;
|
readonly onDidFocusChange: Event<FocusEvent>;
|
||||||
readonly onDidVisibilityChange: Event<VisibilityEvent>;
|
readonly onDidVisibilityChange: Event<VisibilityEvent>;
|
||||||
readonly onDidActiveChange: Event<ActiveEvent>;
|
readonly onDidActiveChange: Event<ActiveEvent>;
|
||||||
setVisible(isVisible: boolean): void;
|
readonly onDidHiddenChange: Event<HiddenEvent>;
|
||||||
setActive(): void;
|
setActive(): void;
|
||||||
updateParameters(parameters: Parameters): void;
|
updateParameters(parameters: Parameters): void;
|
||||||
/**
|
/**
|
||||||
@ -43,6 +47,10 @@ export interface PanelApi {
|
|||||||
* Whether the panel is visible
|
* Whether the panel is visible
|
||||||
*/
|
*/
|
||||||
readonly isVisible: boolean;
|
readonly isVisible: boolean;
|
||||||
|
/**
|
||||||
|
* Whether the panel is hidden
|
||||||
|
*/
|
||||||
|
readonly isHidden: boolean;
|
||||||
/**
|
/**
|
||||||
* The panel width in pixels
|
* The panel width in pixels
|
||||||
*/
|
*/
|
||||||
@ -68,6 +76,7 @@ export class PanelApiImpl extends CompositeDisposable implements PanelApi {
|
|||||||
private _isFocused = false;
|
private _isFocused = false;
|
||||||
private _isActive = false;
|
private _isActive = false;
|
||||||
private _isVisible = true;
|
private _isVisible = true;
|
||||||
|
private _isHidden = false;
|
||||||
private _width = 0;
|
private _width = 0;
|
||||||
private _height = 0;
|
private _height = 0;
|
||||||
|
|
||||||
@ -77,7 +86,7 @@ export class PanelApiImpl extends CompositeDisposable implements PanelApi {
|
|||||||
replay: true,
|
replay: true,
|
||||||
});
|
});
|
||||||
readonly onDidDimensionsChange = this._onDidDimensionChange.event;
|
readonly onDidDimensionsChange = this._onDidDimensionChange.event;
|
||||||
//
|
|
||||||
readonly _onDidChangeFocus = new Emitter<FocusEvent>({
|
readonly _onDidChangeFocus = new Emitter<FocusEvent>({
|
||||||
replay: true,
|
replay: true,
|
||||||
});
|
});
|
||||||
@ -91,41 +100,45 @@ export class PanelApiImpl extends CompositeDisposable implements PanelApi {
|
|||||||
});
|
});
|
||||||
readonly onDidVisibilityChange: Event<VisibilityEvent> =
|
readonly onDidVisibilityChange: Event<VisibilityEvent> =
|
||||||
this._onDidVisibilityChange.event;
|
this._onDidVisibilityChange.event;
|
||||||
//
|
|
||||||
|
|
||||||
readonly _onVisibilityChange = new Emitter<VisibilityEvent>();
|
readonly _onDidHiddenChange = new Emitter<HiddenEvent>();
|
||||||
readonly onVisibilityChange: Event<VisibilityEvent> =
|
readonly onDidHiddenChange: Event<HiddenEvent> =
|
||||||
this._onVisibilityChange.event;
|
this._onDidHiddenChange.event;
|
||||||
//
|
|
||||||
readonly _onDidActiveChange = new Emitter<ActiveEvent>({
|
readonly _onDidActiveChange = new Emitter<ActiveEvent>({
|
||||||
replay: true,
|
replay: true,
|
||||||
});
|
});
|
||||||
readonly onDidActiveChange: Event<ActiveEvent> =
|
readonly onDidActiveChange: Event<ActiveEvent> =
|
||||||
this._onDidActiveChange.event;
|
this._onDidActiveChange.event;
|
||||||
//
|
|
||||||
readonly _onActiveChange = new Emitter<void>();
|
readonly _onActiveChange = new Emitter<void>();
|
||||||
readonly onActiveChange: Event<void> = this._onActiveChange.event;
|
readonly onActiveChange: Event<void> = this._onActiveChange.event;
|
||||||
//
|
|
||||||
readonly _onUpdateParameters = new Emitter<Parameters>();
|
readonly _onUpdateParameters = new Emitter<Parameters>();
|
||||||
readonly onUpdateParameters: Event<Parameters> =
|
readonly onUpdateParameters: Event<Parameters> =
|
||||||
this._onUpdateParameters.event;
|
this._onUpdateParameters.event;
|
||||||
|
|
||||||
get isFocused() {
|
get isFocused(): boolean {
|
||||||
return this._isFocused;
|
return this._isFocused;
|
||||||
}
|
}
|
||||||
|
|
||||||
get isActive() {
|
get isActive(): boolean {
|
||||||
return this._isActive;
|
return this._isActive;
|
||||||
}
|
}
|
||||||
get isVisible() {
|
|
||||||
|
get isVisible(): boolean {
|
||||||
return this._isVisible;
|
return this._isVisible;
|
||||||
}
|
}
|
||||||
|
|
||||||
get width() {
|
get isHidden(): boolean {
|
||||||
|
return this._isHidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
get width(): number {
|
||||||
return this._width;
|
return this._width;
|
||||||
}
|
}
|
||||||
|
|
||||||
get height() {
|
get height(): number {
|
||||||
return this._height;
|
return this._height;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,6 +155,9 @@ export class PanelApiImpl extends CompositeDisposable implements PanelApi {
|
|||||||
this.onDidVisibilityChange((event) => {
|
this.onDidVisibilityChange((event) => {
|
||||||
this._isVisible = event.isVisible;
|
this._isVisible = event.isVisible;
|
||||||
}),
|
}),
|
||||||
|
this.onDidHiddenChange((event) => {
|
||||||
|
this._isHidden = event.isHidden;
|
||||||
|
}),
|
||||||
this.onDidDimensionsChange((event) => {
|
this.onDidDimensionsChange((event) => {
|
||||||
this._width = event.width;
|
this._width = event.width;
|
||||||
this._height = event.height;
|
this._height = event.height;
|
||||||
@ -153,9 +169,10 @@ export class PanelApiImpl extends CompositeDisposable implements PanelApi {
|
|||||||
this._onDidActiveChange,
|
this._onDidActiveChange,
|
||||||
this._onWillFocus,
|
this._onWillFocus,
|
||||||
this._onActiveChange,
|
this._onActiveChange,
|
||||||
this._onVisibilityChange,
|
|
||||||
this._onUpdateParameters,
|
this._onUpdateParameters,
|
||||||
this._onWillFocus
|
this._onWillFocus,
|
||||||
|
this._onDidHiddenChange,
|
||||||
|
this._onUpdateParameters
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,8 +186,8 @@ export class PanelApiImpl extends CompositeDisposable implements PanelApi {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
setVisible(isVisible: boolean) {
|
setHidden(isHidden: boolean): void {
|
||||||
this._onVisibilityChange.fire({ isVisible });
|
this._onDidHiddenChange.fire({ isHidden });
|
||||||
}
|
}
|
||||||
|
|
||||||
setActive(): void {
|
setActive(): void {
|
||||||
@ -180,8 +197,4 @@ export class PanelApiImpl extends CompositeDisposable implements PanelApi {
|
|||||||
updateParameters(parameters: Parameters): void {
|
updateParameters(parameters: Parameters): void {
|
||||||
this._onUpdateParameters.fire(parameters);
|
this._onUpdateParameters.fire(parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose() {
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,37 @@
|
|||||||
import { toggleClass } from '../dom';
|
import { toggleClass } from '../dom';
|
||||||
import { Emitter, Event } from '../events';
|
import { DockviewEvent, Emitter, Event } from '../events';
|
||||||
import { CompositeDisposable } from '../lifecycle';
|
import { CompositeDisposable } from '../lifecycle';
|
||||||
import { DragAndDropObserver } from './dnd';
|
import { DragAndDropObserver } from './dnd';
|
||||||
import { clamp } from '../math';
|
import { clamp } from '../math';
|
||||||
import { Direction } from '../gridview/baseComponentGridview';
|
import { Direction } from '../gridview/baseComponentGridview';
|
||||||
|
|
||||||
|
export interface DroptargetEvent {
|
||||||
|
readonly position: Position;
|
||||||
|
readonly nativeEvent: DragEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class WillShowOverlayEvent
|
||||||
|
extends DockviewEvent
|
||||||
|
implements DroptargetEvent
|
||||||
|
{
|
||||||
|
get nativeEvent(): DragEvent {
|
||||||
|
return this.options.nativeEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
get position(): Position {
|
||||||
|
return this.options.position;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private readonly options: {
|
||||||
|
nativeEvent: DragEvent;
|
||||||
|
position: Position;
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function directionToPosition(direction: Direction): Position {
|
export function directionToPosition(direction: Direction): Position {
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
case 'above':
|
case 'above':
|
||||||
@ -39,11 +66,6 @@ export function positionToDirection(position: Position): Direction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DroptargetEvent {
|
|
||||||
readonly position: Position;
|
|
||||||
readonly nativeEvent: DragEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Position = 'top' | 'bottom' | 'left' | 'right' | 'center';
|
export type Position = 'top' | 'bottom' | 'left' | 'right' | 'center';
|
||||||
|
|
||||||
export type CanDisplayOverlay =
|
export type CanDisplayOverlay =
|
||||||
@ -70,6 +92,12 @@ const DEFAULT_SIZE: MeasuredValue = {
|
|||||||
const SMALL_WIDTH_BOUNDARY = 100;
|
const SMALL_WIDTH_BOUNDARY = 100;
|
||||||
const SMALL_HEIGHT_BOUNDARY = 100;
|
const SMALL_HEIGHT_BOUNDARY = 100;
|
||||||
|
|
||||||
|
export interface DroptargetOptions {
|
||||||
|
canDisplayOverlay: CanDisplayOverlay;
|
||||||
|
acceptedTargetZones: Position[];
|
||||||
|
overlayModel?: DroptargetOverlayModel;
|
||||||
|
}
|
||||||
|
|
||||||
export class Droptarget extends CompositeDisposable {
|
export class Droptarget extends CompositeDisposable {
|
||||||
private targetElement: HTMLElement | undefined;
|
private targetElement: HTMLElement | undefined;
|
||||||
private overlayElement: HTMLElement | undefined;
|
private overlayElement: HTMLElement | undefined;
|
||||||
@ -79,6 +107,10 @@ export class Droptarget extends CompositeDisposable {
|
|||||||
private readonly _onDrop = new Emitter<DroptargetEvent>();
|
private readonly _onDrop = new Emitter<DroptargetEvent>();
|
||||||
readonly onDrop: Event<DroptargetEvent> = this._onDrop.event;
|
readonly onDrop: Event<DroptargetEvent> = this._onDrop.event;
|
||||||
|
|
||||||
|
private readonly _onWillShowOverlay = new Emitter<WillShowOverlayEvent>();
|
||||||
|
readonly onWillShowOverlay: Event<WillShowOverlayEvent> =
|
||||||
|
this._onWillShowOverlay.event;
|
||||||
|
|
||||||
readonly dnd: DragAndDropObserver;
|
readonly dnd: DragAndDropObserver;
|
||||||
|
|
||||||
private static USED_EVENT_ID = '__dockview_droptarget_event_is_used__';
|
private static USED_EVENT_ID = '__dockview_droptarget_event_is_used__';
|
||||||
@ -89,11 +121,7 @@ export class Droptarget extends CompositeDisposable {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly element: HTMLElement,
|
private readonly element: HTMLElement,
|
||||||
private readonly options: {
|
private readonly options: DroptargetOptions
|
||||||
canDisplayOverlay: CanDisplayOverlay;
|
|
||||||
acceptedTargetZones: Position[];
|
|
||||||
overlayModel?: DroptargetOverlayModel;
|
|
||||||
}
|
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
@ -142,6 +170,22 @@ export class Droptarget extends CompositeDisposable {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const willShowOverlayEvent = new WillShowOverlayEvent({
|
||||||
|
nativeEvent: e,
|
||||||
|
position: quadrant,
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide an opportunity to prevent the overlay appearing and in turn
|
||||||
|
* any dnd behaviours
|
||||||
|
*/
|
||||||
|
this._onWillShowOverlay.fire(willShowOverlayEvent);
|
||||||
|
|
||||||
|
if (willShowOverlayEvent.defaultPrevented) {
|
||||||
|
this.removeDropTarget();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof this.options.canDisplayOverlay === 'boolean') {
|
if (typeof this.options.canDisplayOverlay === 'boolean') {
|
||||||
if (!this.options.canDisplayOverlay) {
|
if (!this.options.canDisplayOverlay) {
|
||||||
this.removeDropTarget();
|
this.removeDropTarget();
|
||||||
@ -192,7 +236,7 @@ export class Droptarget extends CompositeDisposable {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
this.addDisposables(this._onDrop, this.dnd);
|
this.addDisposables(this._onDrop, this._onWillShowOverlay, this.dnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
setTargetZones(acceptedTargetZones: Position[]): void {
|
setTargetZones(acceptedTargetZones: Position[]): void {
|
||||||
@ -260,24 +304,43 @@ export class Droptarget extends CompositeDisposable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const translate = (1 - size) / 2;
|
const box = { top: '0px', left: '0px', width: '100%', height: '100%' };
|
||||||
const scale = size;
|
|
||||||
|
|
||||||
let transform: string;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You can also achieve the overlay placement using the transform CSS property
|
||||||
|
* to translate and scale the element however this has the undesired effect of
|
||||||
|
* 'skewing' the element. Comment left here for anybody that ever revisits this.
|
||||||
|
*
|
||||||
|
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/transform
|
||||||
|
*
|
||||||
|
* right
|
||||||
|
* translateX(${100 * (1 - size) / 2}%) scaleX(${scale})
|
||||||
|
*
|
||||||
|
* left
|
||||||
|
* translateX(-${100 * (1 - size) / 2}%) scaleX(${scale})
|
||||||
|
*
|
||||||
|
* top
|
||||||
|
* translateY(-${100 * (1 - size) / 2}%) scaleY(${scale})
|
||||||
|
*
|
||||||
|
* bottom
|
||||||
|
* translateY(${100 * (1 - size) / 2}%) scaleY(${scale})
|
||||||
|
*/
|
||||||
if (rightClass) {
|
if (rightClass) {
|
||||||
transform = `translateX(${100 * translate}%) scaleX(${scale})`;
|
box.left = `${100 * (1 - size)}%`;
|
||||||
|
box.width = `${100 * size}%`;
|
||||||
} else if (leftClass) {
|
} else if (leftClass) {
|
||||||
transform = `translateX(-${100 * translate}%) scaleX(${scale})`;
|
box.width = `${100 * size}%`;
|
||||||
} else if (topClass) {
|
} else if (topClass) {
|
||||||
transform = `translateY(-${100 * translate}%) scaleY(${scale})`;
|
box.height = `${100 * size}%`;
|
||||||
} else if (bottomClass) {
|
} else if (bottomClass) {
|
||||||
transform = `translateY(${100 * translate}%) scaleY(${scale})`;
|
box.top = `${100 * size}%`;
|
||||||
} else {
|
box.height = `${100 * size}%`;
|
||||||
transform = '';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.overlayElement.style.transform = transform;
|
this.overlayElement.style.top = box.top;
|
||||||
|
this.overlayElement.style.left = box.left;
|
||||||
|
this.overlayElement.style.width = box.width;
|
||||||
|
this.overlayElement.style.height = box.height;
|
||||||
|
|
||||||
toggleClass(
|
toggleClass(
|
||||||
this.overlayElement,
|
this.overlayElement,
|
||||||
|
@ -38,7 +38,7 @@ export class GroupDragHandler extends DragHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override isCancelled(_event: DragEvent): boolean {
|
override isCancelled(_event: DragEvent): boolean {
|
||||||
if (this.group.api.location === 'floating' && !_event.shiftKey) {
|
if (this.group.api.location.type === 'floating' && !_event.shiftKey) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -10,7 +10,6 @@ import { DockviewComponent } from '../../dockviewComponent';
|
|||||||
import { Droptarget } from '../../../dnd/droptarget';
|
import { Droptarget } from '../../../dnd/droptarget';
|
||||||
import { DockviewGroupPanelModel } from '../../dockviewGroupPanelModel';
|
import { DockviewGroupPanelModel } from '../../dockviewGroupPanelModel';
|
||||||
import { getPanelData } from '../../../dnd/dataTransfer';
|
import { getPanelData } from '../../../dnd/dataTransfer';
|
||||||
import { DockviewDropTargets } from '../../types';
|
|
||||||
|
|
||||||
export interface IContentContainer extends IDisposable {
|
export interface IContentContainer extends IDisposable {
|
||||||
readonly dropTarget: Droptarget;
|
readonly dropTarget: Droptarget;
|
||||||
@ -71,7 +70,7 @@ export class ContentContainer
|
|||||||
if (
|
if (
|
||||||
!data &&
|
!data &&
|
||||||
event.shiftKey &&
|
event.shiftKey &&
|
||||||
this.group.location !== 'floating'
|
this.group.location.type !== 'floating'
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -95,11 +94,7 @@ export class ContentContainer
|
|||||||
return !groupHasOnePanelAndIsActiveDragElement;
|
return !groupHasOnePanelAndIsActiveDragElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.group.canDisplayOverlay(
|
return this.group.canDisplayOverlay(event, position, 'panel');
|
||||||
event,
|
|
||||||
position,
|
|
||||||
DockviewDropTargets.Panel
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -138,7 +133,7 @@ export class ContentContainer
|
|||||||
|
|
||||||
switch (panel.api.renderer) {
|
switch (panel.api.renderer) {
|
||||||
case 'onlyWhenVisibile':
|
case 'onlyWhenVisibile':
|
||||||
this.accessor.overlayRenderContainer.detatch(panel);
|
this.group.renderContainer.detatch(panel);
|
||||||
if (this.panel) {
|
if (this.panel) {
|
||||||
if (doRender) {
|
if (doRender) {
|
||||||
this._element.appendChild(
|
this._element.appendChild(
|
||||||
@ -154,7 +149,7 @@ export class ContentContainer
|
|||||||
) {
|
) {
|
||||||
this._element.removeChild(panel.view.content.element);
|
this._element.removeChild(panel.view.content.element);
|
||||||
}
|
}
|
||||||
container = this.accessor.overlayRenderContainer.attach({
|
container = this.group.renderContainer.attach({
|
||||||
panel,
|
panel,
|
||||||
referenceContainer: this,
|
referenceContainer: this,
|
||||||
});
|
});
|
||||||
|
@ -7,9 +7,14 @@ import {
|
|||||||
} from '../../../dnd/dataTransfer';
|
} from '../../../dnd/dataTransfer';
|
||||||
import { toggleClass } from '../../../dom';
|
import { toggleClass } from '../../../dom';
|
||||||
import { DockviewComponent } from '../../dockviewComponent';
|
import { DockviewComponent } from '../../dockviewComponent';
|
||||||
import { DockviewDropTargets, ITabRenderer } from '../../types';
|
import { ITabRenderer } from '../../types';
|
||||||
import { DockviewGroupPanel } from '../../dockviewGroupPanel';
|
import { DockviewGroupPanel } from '../../dockviewGroupPanel';
|
||||||
import { DroptargetEvent, Droptarget } from '../../../dnd/droptarget';
|
import {
|
||||||
|
DroptargetEvent,
|
||||||
|
Droptarget,
|
||||||
|
Position,
|
||||||
|
WillShowOverlayEvent,
|
||||||
|
} from '../../../dnd/droptarget';
|
||||||
import { DragHandler } from '../../../dnd/abstractDragHandler';
|
import { DragHandler } from '../../../dnd/abstractDragHandler';
|
||||||
import { IDockviewPanel } from '../../dockviewPanel';
|
import { IDockviewPanel } from '../../dockviewPanel';
|
||||||
|
|
||||||
@ -40,18 +45,9 @@ class TabDragHandler extends DragHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ITab extends IDisposable {
|
export class Tab extends CompositeDisposable {
|
||||||
readonly panel: IDockviewPanel;
|
|
||||||
readonly element: HTMLElement;
|
|
||||||
setContent: (element: ITabRenderer) => void;
|
|
||||||
onChanged: Event<MouseEvent>;
|
|
||||||
onDrop: Event<DroptargetEvent>;
|
|
||||||
setActive(isActive: boolean): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Tab extends CompositeDisposable implements ITab {
|
|
||||||
private readonly _element: HTMLElement;
|
private readonly _element: HTMLElement;
|
||||||
private readonly droptarget: Droptarget;
|
private readonly dropTarget: Droptarget;
|
||||||
private content: ITabRenderer | undefined = undefined;
|
private content: ITabRenderer | undefined = undefined;
|
||||||
|
|
||||||
private readonly _onChanged = new Emitter<MouseEvent>();
|
private readonly _onChanged = new Emitter<MouseEvent>();
|
||||||
@ -63,6 +59,8 @@ export class Tab extends CompositeDisposable implements ITab {
|
|||||||
private readonly _onDragStart = new Emitter<DragEvent>();
|
private readonly _onDragStart = new Emitter<DragEvent>();
|
||||||
readonly onDragStart = this._onDragStart.event;
|
readonly onDragStart = this._onDragStart.event;
|
||||||
|
|
||||||
|
readonly onWillShowOverlay: Event<WillShowOverlayEvent>;
|
||||||
|
|
||||||
public get element(): HTMLElement {
|
public get element(): HTMLElement {
|
||||||
return this._element;
|
return this._element;
|
||||||
}
|
}
|
||||||
@ -88,7 +86,7 @@ export class Tab extends CompositeDisposable implements ITab {
|
|||||||
this.panel
|
this.panel
|
||||||
);
|
);
|
||||||
|
|
||||||
this.droptarget = new Droptarget(this._element, {
|
this.dropTarget = new Droptarget(this._element, {
|
||||||
acceptedTargetZones: ['center'],
|
acceptedTargetZones: ['center'],
|
||||||
canDisplayOverlay: (event, position) => {
|
canDisplayOverlay: (event, position) => {
|
||||||
if (this.group.locked) {
|
if (this.group.locked) {
|
||||||
@ -112,11 +110,13 @@ export class Tab extends CompositeDisposable implements ITab {
|
|||||||
return this.group.model.canDisplayOverlay(
|
return this.group.model.canDisplayOverlay(
|
||||||
event,
|
event,
|
||||||
position,
|
position,
|
||||||
DockviewDropTargets.Tab
|
'tab'
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.onWillShowOverlay = this.dropTarget.onWillShowOverlay;
|
||||||
|
|
||||||
this.addDisposables(
|
this.addDisposables(
|
||||||
this._onChanged,
|
this._onChanged,
|
||||||
this._onDropped,
|
this._onDropped,
|
||||||
@ -132,10 +132,10 @@ export class Tab extends CompositeDisposable implements ITab {
|
|||||||
|
|
||||||
this._onChanged.fire(event);
|
this._onChanged.fire(event);
|
||||||
}),
|
}),
|
||||||
this.droptarget.onDrop((event) => {
|
this.dropTarget.onDrop((event) => {
|
||||||
this._onDropped.fire(event);
|
this._onDropped.fire(event);
|
||||||
}),
|
}),
|
||||||
this.droptarget
|
this.dropTarget
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,12 +4,14 @@ import {
|
|||||||
IValueDisposable,
|
IValueDisposable,
|
||||||
} from '../../../lifecycle';
|
} from '../../../lifecycle';
|
||||||
import { addDisposableListener, Emitter, Event } from '../../../events';
|
import { addDisposableListener, Emitter, Event } from '../../../events';
|
||||||
import { ITab, Tab } from '../tab/tab';
|
import { Tab } from '../tab/tab';
|
||||||
import { DockviewComponent } from '../../dockviewComponent';
|
|
||||||
import { DockviewGroupPanel } from '../../dockviewGroupPanel';
|
import { DockviewGroupPanel } from '../../dockviewGroupPanel';
|
||||||
import { VoidContainer } from './voidContainer';
|
import { VoidContainer } from './voidContainer';
|
||||||
import { toggleClass } from '../../../dom';
|
import { toggleClass } from '../../../dom';
|
||||||
import { DockviewPanel, IDockviewPanel } from '../../dockviewPanel';
|
import { DockviewPanel, IDockviewPanel } from '../../dockviewPanel';
|
||||||
|
import { DockviewComponent } from '../../dockviewComponent';
|
||||||
|
import { WillShowOverlayEvent } from '../../../dnd/droptarget';
|
||||||
|
import { DockviewGroupDropLocation } from '../../dockviewGroupPanelModel';
|
||||||
|
|
||||||
export interface TabDropIndexEvent {
|
export interface TabDropIndexEvent {
|
||||||
readonly event: DragEvent;
|
readonly event: DragEvent;
|
||||||
@ -30,17 +32,21 @@ export interface ITabsContainer extends IDisposable {
|
|||||||
readonly element: HTMLElement;
|
readonly element: HTMLElement;
|
||||||
readonly panels: string[];
|
readonly panels: string[];
|
||||||
readonly size: number;
|
readonly size: number;
|
||||||
|
readonly onDrop: Event<TabDropIndexEvent>;
|
||||||
|
readonly onTabDragStart: Event<TabDragEvent>;
|
||||||
|
readonly onGroupDragStart: Event<GroupDragEvent>;
|
||||||
|
readonly onWillShowOverlay: Event<{
|
||||||
|
event: WillShowOverlayEvent;
|
||||||
|
kind: DockviewGroupDropLocation;
|
||||||
|
}>;
|
||||||
hidden: boolean;
|
hidden: boolean;
|
||||||
delete: (id: string) => void;
|
delete(id: string): void;
|
||||||
indexOf: (id: string) => number;
|
indexOf(id: string): number;
|
||||||
onDrop: Event<TabDropIndexEvent>;
|
setActive(isGroupActive: boolean): void;
|
||||||
onTabDragStart: Event<TabDragEvent>;
|
setActivePanel(panel: IDockviewPanel): void;
|
||||||
onGroupDragStart: Event<GroupDragEvent>;
|
isActive(tab: Tab): boolean;
|
||||||
setActive: (isGroupActive: boolean) => void;
|
closePanel(panel: IDockviewPanel): void;
|
||||||
setActivePanel: (panel: IDockviewPanel) => void;
|
openPanel(panel: IDockviewPanel, index?: number): void;
|
||||||
isActive: (tab: ITab) => boolean;
|
|
||||||
closePanel: (panel: IDockviewPanel) => void;
|
|
||||||
openPanel: (panel: IDockviewPanel, index?: number) => void;
|
|
||||||
setRightActionsElement(element: HTMLElement | undefined): void;
|
setRightActionsElement(element: HTMLElement | undefined): void;
|
||||||
setLeftActionsElement(element: HTMLElement | undefined): void;
|
setLeftActionsElement(element: HTMLElement | undefined): void;
|
||||||
setPrefixActionsElement(element: HTMLElement | undefined): void;
|
setPrefixActionsElement(element: HTMLElement | undefined): void;
|
||||||
@ -59,7 +65,7 @@ export class TabsContainer
|
|||||||
private readonly preActionsContainer: HTMLElement;
|
private readonly preActionsContainer: HTMLElement;
|
||||||
private readonly voidContainer: VoidContainer;
|
private readonly voidContainer: VoidContainer;
|
||||||
|
|
||||||
private tabs: IValueDisposable<ITab>[] = [];
|
private tabs: IValueDisposable<Tab>[] = [];
|
||||||
private selectedIndex = -1;
|
private selectedIndex = -1;
|
||||||
private rightActions: HTMLElement | undefined;
|
private rightActions: HTMLElement | undefined;
|
||||||
private leftActions: HTMLElement | undefined;
|
private leftActions: HTMLElement | undefined;
|
||||||
@ -77,6 +83,15 @@ export class TabsContainer
|
|||||||
readonly onGroupDragStart: Event<GroupDragEvent> =
|
readonly onGroupDragStart: Event<GroupDragEvent> =
|
||||||
this._onGroupDragStart.event;
|
this._onGroupDragStart.event;
|
||||||
|
|
||||||
|
private readonly _onWillShowOverlay = new Emitter<{
|
||||||
|
event: WillShowOverlayEvent;
|
||||||
|
kind: DockviewGroupDropLocation;
|
||||||
|
}>();
|
||||||
|
readonly onWillShowOverlay: Event<{
|
||||||
|
event: WillShowOverlayEvent;
|
||||||
|
kind: DockviewGroupDropLocation;
|
||||||
|
}> = this._onWillShowOverlay.event;
|
||||||
|
|
||||||
get panels(): string[] {
|
get panels(): string[] {
|
||||||
return this.tabs.map((_) => _.value.panel.id);
|
return this.tabs.map((_) => _.value.panel.id);
|
||||||
}
|
}
|
||||||
@ -150,7 +165,7 @@ export class TabsContainer
|
|||||||
return this._element;
|
return this._element;
|
||||||
}
|
}
|
||||||
|
|
||||||
public isActive(tab: ITab): boolean {
|
public isActive(tab: Tab): boolean {
|
||||||
return (
|
return (
|
||||||
this.selectedIndex > -1 &&
|
this.selectedIndex > -1 &&
|
||||||
this.tabs[this.selectedIndex].value === tab
|
this.tabs[this.selectedIndex].value === tab
|
||||||
@ -167,12 +182,6 @@ export class TabsContainer
|
|||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.addDisposables(
|
|
||||||
this._onDrop,
|
|
||||||
this._onTabDragStart,
|
|
||||||
this._onGroupDragStart
|
|
||||||
);
|
|
||||||
|
|
||||||
this._element = document.createElement('div');
|
this._element = document.createElement('div');
|
||||||
this._element.className = 'tabs-and-actions-container';
|
this._element.className = 'tabs-and-actions-container';
|
||||||
|
|
||||||
@ -182,27 +191,6 @@ export class TabsContainer
|
|||||||
this.accessor.options.singleTabMode === 'fullwidth'
|
this.accessor.options.singleTabMode === 'fullwidth'
|
||||||
);
|
);
|
||||||
|
|
||||||
this.addDisposables(
|
|
||||||
this.accessor.onDidAddPanel((e) => {
|
|
||||||
if (e.api.group === this.group) {
|
|
||||||
toggleClass(
|
|
||||||
this._element,
|
|
||||||
'dv-single-tab',
|
|
||||||
this.size === 1
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
this.accessor.onDidRemovePanel((e) => {
|
|
||||||
if (e.api.group === this.group) {
|
|
||||||
toggleClass(
|
|
||||||
this._element,
|
|
||||||
'dv-single-tab',
|
|
||||||
this.size === 1
|
|
||||||
);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
this.rightActionsContainer = document.createElement('div');
|
this.rightActionsContainer = document.createElement('div');
|
||||||
this.rightActionsContainer.className = 'right-actions-container';
|
this.rightActionsContainer.className = 'right-actions-container';
|
||||||
|
|
||||||
@ -224,6 +212,28 @@ export class TabsContainer
|
|||||||
this._element.appendChild(this.rightActionsContainer);
|
this._element.appendChild(this.rightActionsContainer);
|
||||||
|
|
||||||
this.addDisposables(
|
this.addDisposables(
|
||||||
|
this.accessor.onDidAddPanel((e) => {
|
||||||
|
if (e.api.group === this.group) {
|
||||||
|
toggleClass(
|
||||||
|
this._element,
|
||||||
|
'dv-single-tab',
|
||||||
|
this.size === 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
this.accessor.onDidRemovePanel((e) => {
|
||||||
|
if (e.api.group === this.group) {
|
||||||
|
toggleClass(
|
||||||
|
this._element,
|
||||||
|
'dv-single-tab',
|
||||||
|
this.size === 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
this._onWillShowOverlay,
|
||||||
|
this._onDrop,
|
||||||
|
this._onTabDragStart,
|
||||||
|
this._onGroupDragStart,
|
||||||
this.voidContainer,
|
this.voidContainer,
|
||||||
this.voidContainer.onDragStart((event) => {
|
this.voidContainer.onDragStart((event) => {
|
||||||
this._onGroupDragStart.fire({
|
this._onGroupDragStart.fire({
|
||||||
@ -237,6 +247,9 @@ export class TabsContainer
|
|||||||
index: this.tabs.length,
|
index: this.tabs.length,
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
|
this.voidContainer.onWillShowOverlay((event) => {
|
||||||
|
this._onWillShowOverlay.fire({ event, kind: 'header_space' });
|
||||||
|
}),
|
||||||
addDisposableListener(
|
addDisposableListener(
|
||||||
this.voidContainer.element,
|
this.voidContainer.element,
|
||||||
'mousedown',
|
'mousedown',
|
||||||
@ -247,7 +260,7 @@ export class TabsContainer
|
|||||||
if (
|
if (
|
||||||
isFloatingGroupsEnabled &&
|
isFloatingGroupsEnabled &&
|
||||||
event.shiftKey &&
|
event.shiftKey &&
|
||||||
this.group.api.location !== 'floating'
|
this.group.api.location.type !== 'floating'
|
||||||
) {
|
) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
@ -286,7 +299,7 @@ export class TabsContainer
|
|||||||
}
|
}
|
||||||
|
|
||||||
private addTab(
|
private addTab(
|
||||||
tab: IValueDisposable<ITab>,
|
tab: IValueDisposable<Tab>,
|
||||||
index: number = this.tabs.length
|
index: number = this.tabs.length
|
||||||
): void {
|
): void {
|
||||||
if (index < 0 || index > this.tabs.length) {
|
if (index < 0 || index > this.tabs.length) {
|
||||||
@ -350,7 +363,8 @@ export class TabsContainer
|
|||||||
!this.accessor.options.disableFloatingGroups;
|
!this.accessor.options.disableFloatingGroups;
|
||||||
|
|
||||||
const isFloatingWithOnePanel =
|
const isFloatingWithOnePanel =
|
||||||
this.group.api.location === 'floating' && this.size === 1;
|
this.group.api.location.type === 'floating' &&
|
||||||
|
this.size === 1;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
isFloatingGroupsEnabled &&
|
isFloatingGroupsEnabled &&
|
||||||
@ -393,10 +407,13 @@ export class TabsContainer
|
|||||||
event: event.nativeEvent,
|
event: event.nativeEvent,
|
||||||
index: this.tabs.findIndex((x) => x.value === tab),
|
index: this.tabs.findIndex((x) => x.value === tab),
|
||||||
});
|
});
|
||||||
|
}),
|
||||||
|
tab.onWillShowOverlay((event) => {
|
||||||
|
this._onWillShowOverlay.fire({ event, kind: 'tab' });
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const value: IValueDisposable<ITab> = { value: tab, disposable };
|
const value: IValueDisposable<Tab> = { value: tab, disposable };
|
||||||
|
|
||||||
this.addTab(value, index);
|
this.addTab(value, index);
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
import { last } from '../../../array';
|
import { last } from '../../../array';
|
||||||
import { getPanelData } from '../../../dnd/dataTransfer';
|
import { getPanelData } from '../../../dnd/dataTransfer';
|
||||||
import { Droptarget, DroptargetEvent } from '../../../dnd/droptarget';
|
import {
|
||||||
|
Droptarget,
|
||||||
|
DroptargetEvent,
|
||||||
|
WillShowOverlayEvent,
|
||||||
|
} from '../../../dnd/droptarget';
|
||||||
import { GroupDragHandler } from '../../../dnd/groupDragHandler';
|
import { GroupDragHandler } from '../../../dnd/groupDragHandler';
|
||||||
import { DockviewComponent } from '../../dockviewComponent';
|
import { DockviewComponent } from '../../dockviewComponent';
|
||||||
import { addDisposableListener, Emitter, Event } from '../../../events';
|
import { addDisposableListener, Emitter, Event } from '../../../events';
|
||||||
import { CompositeDisposable } from '../../../lifecycle';
|
import { CompositeDisposable } from '../../../lifecycle';
|
||||||
import { DockviewGroupPanel } from '../../dockviewGroupPanel';
|
import { DockviewGroupPanel } from '../../dockviewGroupPanel';
|
||||||
import { DockviewDropTargets } from '../../types';
|
|
||||||
|
|
||||||
export class VoidContainer extends CompositeDisposable {
|
export class VoidContainer extends CompositeDisposable {
|
||||||
private readonly _element: HTMLElement;
|
private readonly _element: HTMLElement;
|
||||||
private readonly voidDropTarget: Droptarget;
|
private readonly dropTraget: Droptarget;
|
||||||
|
|
||||||
private readonly _onDrop = new Emitter<DroptargetEvent>();
|
private readonly _onDrop = new Emitter<DroptargetEvent>();
|
||||||
readonly onDrop: Event<DroptargetEvent> = this._onDrop.event;
|
readonly onDrop: Event<DroptargetEvent> = this._onDrop.event;
|
||||||
@ -18,6 +21,8 @@ export class VoidContainer extends CompositeDisposable {
|
|||||||
private readonly _onDragStart = new Emitter<DragEvent>();
|
private readonly _onDragStart = new Emitter<DragEvent>();
|
||||||
readonly onDragStart = this._onDragStart.event;
|
readonly onDragStart = this._onDragStart.event;
|
||||||
|
|
||||||
|
readonly onWillShowOverlay: Event<WillShowOverlayEvent>;
|
||||||
|
|
||||||
get element(): HTMLElement {
|
get element(): HTMLElement {
|
||||||
return this._element;
|
return this._element;
|
||||||
}
|
}
|
||||||
@ -44,7 +49,7 @@ export class VoidContainer extends CompositeDisposable {
|
|||||||
|
|
||||||
const handler = new GroupDragHandler(this._element, accessor, group);
|
const handler = new GroupDragHandler(this._element, accessor, group);
|
||||||
|
|
||||||
this.voidDropTarget = new Droptarget(this._element, {
|
this.dropTraget = new Droptarget(this._element, {
|
||||||
acceptedTargetZones: ['center'],
|
acceptedTargetZones: ['center'],
|
||||||
canDisplayOverlay: (event, position) => {
|
canDisplayOverlay: (event, position) => {
|
||||||
const data = getPanelData();
|
const data = getPanelData();
|
||||||
@ -62,23 +67,21 @@ export class VoidContainer extends CompositeDisposable {
|
|||||||
return last(this.group.panels)?.id !== data.panelId;
|
return last(this.group.panels)?.id !== data.panelId;
|
||||||
}
|
}
|
||||||
|
|
||||||
return group.model.canDisplayOverlay(
|
return group.model.canDisplayOverlay(event, position, 'panel');
|
||||||
event,
|
|
||||||
position,
|
|
||||||
DockviewDropTargets.Panel
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.onWillShowOverlay = this.dropTraget.onWillShowOverlay;
|
||||||
|
|
||||||
this.addDisposables(
|
this.addDisposables(
|
||||||
handler,
|
handler,
|
||||||
handler.onDragStart((event) => {
|
handler.onDragStart((event) => {
|
||||||
this._onDragStart.fire(event);
|
this._onDragStart.fire(event);
|
||||||
}),
|
}),
|
||||||
this.voidDropTarget.onDrop((event) => {
|
this.dropTraget.onDrop((event) => {
|
||||||
this._onDrop.fire(event);
|
this._onDrop.fire(event);
|
||||||
}),
|
}),
|
||||||
this.voidDropTarget
|
this.dropTraget
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,32 @@
|
|||||||
.dv-overlay-render-container {
|
.dv-overlay-render-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.split-view-container {
|
||||||
|
&.horizontal {
|
||||||
|
> .view-container > .view {
|
||||||
|
&:not(:last-child) {
|
||||||
|
border-right: var(--dv-group-gap-size) solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:first-child) {
|
||||||
|
border-left: var(--dv-group-gap-size) solid transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.vertical {
|
||||||
|
> .view-container > .view {
|
||||||
|
&:not(:last-child) {
|
||||||
|
border-bottom: var(--dv-group-gap-size) solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:first-child) {
|
||||||
|
border-top: var(--dv-group-gap-size) solid transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.groupview {
|
.groupview {
|
||||||
|
@ -12,14 +12,10 @@ import {
|
|||||||
} from '../dnd/droptarget';
|
} 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, Disposable } from '../lifecycle';
|
import { CompositeDisposable, Disposable, IDisposable } from '../lifecycle';
|
||||||
import { Event, Emitter } from '../events';
|
import { Event, Emitter, addDisposableWindowListener } from '../events';
|
||||||
import { Watermark } from './components/watermark/watermark';
|
import { Watermark } from './components/watermark/watermark';
|
||||||
import {
|
import { IWatermarkRenderer, GroupviewPanelState } from './types';
|
||||||
IWatermarkRenderer,
|
|
||||||
GroupviewPanelState,
|
|
||||||
DockviewDropTargets,
|
|
||||||
} from './types';
|
|
||||||
import { sequentialNumberGenerator } from '../math';
|
import { sequentialNumberGenerator } from '../math';
|
||||||
import { DefaultDockviewDeserialzier } from './deserializer';
|
import { DefaultDockviewDeserialzier } from './deserializer';
|
||||||
import { createComponent } from '../panel/componentFactory';
|
import { createComponent } from '../panel/componentFactory';
|
||||||
@ -44,7 +40,9 @@ import { Orientation, Sizing } from '../splitview/splitview';
|
|||||||
import {
|
import {
|
||||||
GroupOptions,
|
GroupOptions,
|
||||||
GroupPanelViewState,
|
GroupPanelViewState,
|
||||||
GroupviewDropEvent,
|
DockviewDidDropEvent,
|
||||||
|
DockviewWillDropEvent,
|
||||||
|
WillShowOverlayLocationEvent,
|
||||||
} from './dockviewGroupPanelModel';
|
} from './dockviewGroupPanelModel';
|
||||||
import { DockviewGroupPanel } from './dockviewGroupPanel';
|
import { DockviewGroupPanel } from './dockviewGroupPanel';
|
||||||
import { DockviewPanelModel } from './dockviewPanelModel';
|
import { DockviewPanelModel } from './dockviewPanelModel';
|
||||||
@ -58,7 +56,6 @@ import {
|
|||||||
TabDragEvent,
|
TabDragEvent,
|
||||||
} from './components/titlebar/tabsContainer';
|
} from './components/titlebar/tabsContainer';
|
||||||
import { Box } from '../types';
|
import { Box } from '../types';
|
||||||
import { DockviewPopoutGroupPanel } from './dockviewPopoutGroupPanel';
|
|
||||||
import {
|
import {
|
||||||
DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE,
|
DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE,
|
||||||
DEFAULT_FLOATING_GROUP_POSITION,
|
DEFAULT_FLOATING_GROUP_POSITION,
|
||||||
@ -67,13 +64,14 @@ import {
|
|||||||
DockviewPanelRenderer,
|
DockviewPanelRenderer,
|
||||||
OverlayRenderContainer,
|
OverlayRenderContainer,
|
||||||
} from '../overlayRenderContainer';
|
} from '../overlayRenderContainer';
|
||||||
|
import { PopoutWindow } from '../popoutWindow';
|
||||||
|
|
||||||
const DEFAULT_ROOT_OVERLAY_MODEL: DroptargetOverlayModel = {
|
const DEFAULT_ROOT_OVERLAY_MODEL: DroptargetOverlayModel = {
|
||||||
activationSize: { type: 'pixels', value: 10 },
|
activationSize: { type: 'pixels', value: 10 },
|
||||||
size: { type: 'pixels', value: 20 },
|
size: { type: 'pixels', value: 20 },
|
||||||
};
|
};
|
||||||
|
|
||||||
function getTheme(element: HTMLElement): string | undefined {
|
function getDockviewTheme(element: HTMLElement): string | undefined {
|
||||||
function toClassList(element: HTMLElement) {
|
function toClassList(element: HTMLElement) {
|
||||||
const list: string[] = [];
|
const list: string[] = [];
|
||||||
|
|
||||||
@ -112,6 +110,7 @@ export interface SerializedFloatingGroup {
|
|||||||
|
|
||||||
export interface SerializedPopoutGroup {
|
export interface SerializedPopoutGroup {
|
||||||
data: GroupPanelViewState;
|
data: GroupPanelViewState;
|
||||||
|
gridReferenceGroup?: string;
|
||||||
position: Box | null;
|
position: Box | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,18 +229,16 @@ export type DockviewComponentUpdateOptions = Pick<
|
|||||||
| 'disableFloatingGroups'
|
| 'disableFloatingGroups'
|
||||||
| 'floatingGroupBounds'
|
| 'floatingGroupBounds'
|
||||||
| 'rootOverlayModel'
|
| 'rootOverlayModel'
|
||||||
|
| 'disableDnd'
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export interface DockviewDropEvent extends GroupviewDropEvent {
|
|
||||||
api: DockviewApi;
|
|
||||||
group: DockviewGroupPanel | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IDockviewComponent extends IBaseGrid<DockviewGroupPanel> {
|
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 onDidDrop: Event<DockviewDropEvent>;
|
readonly onDidDrop: Event<DockviewDidDropEvent>;
|
||||||
|
readonly onWillDrop: Event<DockviewWillDropEvent>;
|
||||||
|
readonly onWillShowOverlay: Event<WillShowOverlayLocationEvent>;
|
||||||
readonly orientation: Orientation;
|
readonly orientation: Orientation;
|
||||||
updateOptions(options: DockviewComponentUpdateOptions): void;
|
updateOptions(options: DockviewComponentUpdateOptions): void;
|
||||||
moveGroupOrPanel(
|
moveGroupOrPanel(
|
||||||
@ -286,8 +283,10 @@ export interface IDockviewComponent extends IBaseGrid<DockviewGroupPanel> {
|
|||||||
options?: {
|
options?: {
|
||||||
position?: Box;
|
position?: Box;
|
||||||
popoutUrl?: string;
|
popoutUrl?: string;
|
||||||
|
onDidOpen?: (event: { id: string; window: Window }) => void;
|
||||||
|
onWillClose?: (event: { id: string; window: Window }) => void;
|
||||||
}
|
}
|
||||||
): void;
|
): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DockviewComponent
|
export class DockviewComponent
|
||||||
@ -309,8 +308,16 @@ export class DockviewComponent
|
|||||||
readonly onWillDragGroup: Event<GroupDragEvent> =
|
readonly onWillDragGroup: Event<GroupDragEvent> =
|
||||||
this._onWillDragGroup.event;
|
this._onWillDragGroup.event;
|
||||||
|
|
||||||
private readonly _onDidDrop = new Emitter<DockviewDropEvent>();
|
private readonly _onDidDrop = new Emitter<DockviewDidDropEvent>();
|
||||||
readonly onDidDrop: Event<DockviewDropEvent> = this._onDidDrop.event;
|
readonly onDidDrop: Event<DockviewDidDropEvent> = this._onDidDrop.event;
|
||||||
|
|
||||||
|
private readonly _onWillDrop = new Emitter<DockviewWillDropEvent>();
|
||||||
|
readonly onWillDrop: Event<DockviewWillDropEvent> = this._onWillDrop.event;
|
||||||
|
|
||||||
|
private readonly _onWillShowOverlay =
|
||||||
|
new Emitter<WillShowOverlayLocationEvent>();
|
||||||
|
readonly onWillShowOverlay: Event<WillShowOverlayLocationEvent> =
|
||||||
|
this._onWillShowOverlay.event;
|
||||||
|
|
||||||
private readonly _onDidRemovePanel = new Emitter<IDockviewPanel>();
|
private readonly _onDidRemovePanel = new Emitter<IDockviewPanel>();
|
||||||
readonly onDidRemovePanel: Event<IDockviewPanel> =
|
readonly onDidRemovePanel: Event<IDockviewPanel> =
|
||||||
@ -329,7 +336,12 @@ export class DockviewComponent
|
|||||||
this._onDidActivePanelChange.event;
|
this._onDidActivePanelChange.event;
|
||||||
|
|
||||||
private readonly _floatingGroups: DockviewFloatingGroupPanel[] = [];
|
private readonly _floatingGroups: DockviewFloatingGroupPanel[] = [];
|
||||||
private readonly _popoutGroups: DockviewPopoutGroupPanel[] = [];
|
private readonly _popoutGroups: {
|
||||||
|
window: PopoutWindow;
|
||||||
|
popoutGroup: DockviewGroupPanel;
|
||||||
|
referenceGroup: string;
|
||||||
|
disposable: IDisposable;
|
||||||
|
}[] = [];
|
||||||
private readonly _rootDropTarget: Droptarget;
|
private readonly _rootDropTarget: Droptarget;
|
||||||
|
|
||||||
get orientation(): Orientation {
|
get orientation(): Orientation {
|
||||||
@ -369,6 +381,7 @@ export class DockviewComponent
|
|||||||
styles: options.styles,
|
styles: options.styles,
|
||||||
parentElement: options.parentElement,
|
parentElement: options.parentElement,
|
||||||
disableAutoResizing: options.disableAutoResizing,
|
disableAutoResizing: options.disableAutoResizing,
|
||||||
|
locked: options.locked,
|
||||||
});
|
});
|
||||||
|
|
||||||
const gready = document.createElement('div');
|
const gready = document.createElement('div');
|
||||||
@ -384,11 +397,13 @@ export class DockviewComponent
|
|||||||
this.overlayRenderContainer,
|
this.overlayRenderContainer,
|
||||||
this._onWillDragPanel,
|
this._onWillDragPanel,
|
||||||
this._onWillDragGroup,
|
this._onWillDragGroup,
|
||||||
|
this._onWillShowOverlay,
|
||||||
this._onDidActivePanelChange,
|
this._onDidActivePanelChange,
|
||||||
this._onDidAddPanel,
|
this._onDidAddPanel,
|
||||||
this._onDidRemovePanel,
|
this._onDidRemovePanel,
|
||||||
this._onDidLayoutFromJSON,
|
this._onDidLayoutFromJSON,
|
||||||
this._onDidDrop,
|
this._onDidDrop,
|
||||||
|
this._onWillDrop,
|
||||||
Event.any(
|
Event.any(
|
||||||
this.onDidAddGroup,
|
this.onDidAddGroup,
|
||||||
this.onDidRemoveGroup
|
this.onDidRemoveGroup
|
||||||
@ -410,7 +425,7 @@ export class DockviewComponent
|
|||||||
|
|
||||||
// iterate over a copy of the array since .dispose() mutates the original array
|
// iterate over a copy of the array since .dispose() mutates the original array
|
||||||
for (const group of [...this._popoutGroups]) {
|
for (const group of [...this._popoutGroups]) {
|
||||||
group.dispose();
|
group.disposable.dispose();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@ -467,7 +482,7 @@ export class DockviewComponent
|
|||||||
return this.options.showDndOverlay({
|
return this.options.showDndOverlay({
|
||||||
nativeEvent: event,
|
nativeEvent: event,
|
||||||
position: position,
|
position: position,
|
||||||
target: DockviewDropTargets.Edge,
|
target: 'edge',
|
||||||
getData: getPanelData,
|
getData: getPanelData,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -481,6 +496,22 @@ export class DockviewComponent
|
|||||||
|
|
||||||
this.addDisposables(
|
this.addDisposables(
|
||||||
this._rootDropTarget.onDrop((event) => {
|
this._rootDropTarget.onDrop((event) => {
|
||||||
|
const willDropEvent = new DockviewWillDropEvent({
|
||||||
|
nativeEvent: event.nativeEvent,
|
||||||
|
position: event.position,
|
||||||
|
panel: undefined,
|
||||||
|
api: this._api,
|
||||||
|
group: undefined,
|
||||||
|
getData: getPanelData,
|
||||||
|
kind: 'content',
|
||||||
|
});
|
||||||
|
|
||||||
|
this._onWillDrop.fire(willDropEvent);
|
||||||
|
|
||||||
|
if (willDropEvent.defaultPrevented) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const data = getPanelData();
|
const data = getPanelData();
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
@ -491,12 +522,16 @@ export class DockviewComponent
|
|||||||
'center'
|
'center'
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this._onDidDrop.fire({
|
this._onDidDrop.fire(
|
||||||
...event,
|
new DockviewDidDropEvent({
|
||||||
api: this._api,
|
nativeEvent: event.nativeEvent,
|
||||||
group: null,
|
position: event.position,
|
||||||
getData: getPanelData,
|
panel: undefined,
|
||||||
});
|
api: this._api,
|
||||||
|
group: undefined,
|
||||||
|
getData: getPanelData,
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
this._rootDropTarget
|
this._rootDropTarget
|
||||||
@ -508,76 +543,191 @@ export class DockviewComponent
|
|||||||
}
|
}
|
||||||
|
|
||||||
addPopoutGroup(
|
addPopoutGroup(
|
||||||
item: DockviewPanel | DockviewGroupPanel,
|
itemToPopout: DockviewPanel | DockviewGroupPanel,
|
||||||
options?: {
|
options?: {
|
||||||
skipRemoveGroup?: boolean;
|
skipRemoveGroup?: boolean;
|
||||||
position?: Box;
|
position?: Box;
|
||||||
popoutUrl?: string;
|
popoutUrl?: string;
|
||||||
|
onDidOpen?: (event: { id: string; window: Window }) => void;
|
||||||
|
onWillClose?: (event: { id: string; window: Window }) => void;
|
||||||
|
overridePopoutGroup?: DockviewGroupPanel;
|
||||||
|
}
|
||||||
|
): Promise<void> {
|
||||||
|
if (
|
||||||
|
itemToPopout instanceof DockviewPanel &&
|
||||||
|
itemToPopout.group.size === 1
|
||||||
|
) {
|
||||||
|
return this.addPopoutGroup(itemToPopout.group);
|
||||||
}
|
}
|
||||||
): void {
|
|
||||||
let group: DockviewGroupPanel;
|
|
||||||
let box: Box | undefined = options?.position;
|
|
||||||
|
|
||||||
if (item instanceof DockviewPanel) {
|
const theme = getDockviewTheme(this.gridview.element);
|
||||||
group = this.createGroup();
|
const element = this.element;
|
||||||
|
|
||||||
this.removePanel(item, {
|
function moveGroupWithoutDestroying(options: {
|
||||||
removeEmptyGroup: true,
|
from: DockviewGroupPanel;
|
||||||
skipDispose: true,
|
to: DockviewGroupPanel;
|
||||||
|
}) {
|
||||||
|
const activePanel = options.from.activePanel;
|
||||||
|
const panels = [...options.from.panels].map((panel) =>
|
||||||
|
options.from.model.removePanel(panel)
|
||||||
|
);
|
||||||
|
|
||||||
|
panels.forEach((panel) => {
|
||||||
|
options.to.model.openPanel(panel, {
|
||||||
|
skipSetPanelActive: activePanel !== panel,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
group.model.openPanel(item);
|
|
||||||
|
|
||||||
if (!box) {
|
|
||||||
box = this.element.getBoundingClientRect();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
group = item;
|
|
||||||
|
|
||||||
if (!box) {
|
|
||||||
box = group.element.getBoundingClientRect();
|
|
||||||
}
|
|
||||||
|
|
||||||
const skip =
|
|
||||||
typeof options?.skipRemoveGroup === 'boolean' &&
|
|
||||||
options.skipRemoveGroup;
|
|
||||||
|
|
||||||
if (!skip) {
|
|
||||||
this.doRemoveGroup(item, { skipDispose: true });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const theme = getTheme(this.gridview.element);
|
function getBox(): Box {
|
||||||
|
if (options?.position) {
|
||||||
|
return options.position;
|
||||||
|
}
|
||||||
|
|
||||||
const popoutWindow = new DockviewPopoutGroupPanel(
|
if (itemToPopout instanceof DockviewGroupPanel) {
|
||||||
`${this.id}-${group.id}`, // globally unique within dockview
|
return itemToPopout.element.getBoundingClientRect();
|
||||||
group,
|
}
|
||||||
|
|
||||||
|
if (itemToPopout.group) {
|
||||||
|
return itemToPopout.group.element.getBoundingClientRect();
|
||||||
|
}
|
||||||
|
return element.getBoundingClientRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
const box: Box = getBox();
|
||||||
|
|
||||||
|
const groupId =
|
||||||
|
options?.overridePopoutGroup?.id ?? this.getNextGroupId(); //item.id;
|
||||||
|
|
||||||
|
itemToPopout.api.setHidden(true);
|
||||||
|
|
||||||
|
const _window = new PopoutWindow(
|
||||||
|
`${this.id}-${groupId}`, // unique id
|
||||||
|
theme ?? '',
|
||||||
{
|
{
|
||||||
className: theme ?? '',
|
url: options?.popoutUrl ?? '/popout.html',
|
||||||
popoutUrl: options?.popoutUrl ?? '/popout.html',
|
left: window.screenX + box.left,
|
||||||
box: {
|
top: window.screenY + box.top,
|
||||||
left: window.screenX + box.left,
|
width: box.width,
|
||||||
top: window.screenY + box.top,
|
height: box.height,
|
||||||
width: box.width,
|
onDidOpen: options?.onDidOpen,
|
||||||
height: box.height,
|
onWillClose: options?.onWillClose,
|
||||||
},
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
popoutWindow.addDisposables(
|
const popoutWindowDisposable = new CompositeDisposable(
|
||||||
{
|
_window,
|
||||||
dispose: () => {
|
_window.onDidClose(() => {
|
||||||
remove(this._popoutGroups, popoutWindow);
|
popoutWindowDisposable.dispose();
|
||||||
this.updateWatermark();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
popoutWindow.window.onDidClose(() => {
|
|
||||||
this.doAddGroup(group, [0]);
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
this._popoutGroups.push(popoutWindow);
|
return _window
|
||||||
this.updateWatermark();
|
.open()
|
||||||
|
.then((popoutContainer) => {
|
||||||
|
if (_window.isDisposed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (popoutContainer === null) {
|
||||||
|
popoutWindowDisposable.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const gready = document.createElement('div');
|
||||||
|
gready.className = 'dv-overlay-render-container';
|
||||||
|
|
||||||
|
const overlayRenderContainer = new OverlayRenderContainer(
|
||||||
|
gready
|
||||||
|
);
|
||||||
|
|
||||||
|
const referenceGroup =
|
||||||
|
itemToPopout instanceof DockviewPanel
|
||||||
|
? itemToPopout.group
|
||||||
|
: itemToPopout;
|
||||||
|
|
||||||
|
const group =
|
||||||
|
options?.overridePopoutGroup ??
|
||||||
|
this.createGroup({ id: groupId });
|
||||||
|
group.model.renderContainer = overlayRenderContainer;
|
||||||
|
|
||||||
|
if (itemToPopout instanceof DockviewPanel) {
|
||||||
|
const panel =
|
||||||
|
referenceGroup.model.removePanel(itemToPopout);
|
||||||
|
group.model.openPanel(panel);
|
||||||
|
} else {
|
||||||
|
moveGroupWithoutDestroying({
|
||||||
|
from: referenceGroup,
|
||||||
|
to: group,
|
||||||
|
});
|
||||||
|
referenceGroup.api.setHidden(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
popoutContainer.classList.add('dv-dockview');
|
||||||
|
popoutContainer.style.overflow = 'hidden';
|
||||||
|
popoutContainer.appendChild(gready);
|
||||||
|
|
||||||
|
popoutContainer.appendChild(group.element);
|
||||||
|
|
||||||
|
group.model.location = {
|
||||||
|
type: 'popout',
|
||||||
|
getWindow: () => _window.window!,
|
||||||
|
};
|
||||||
|
|
||||||
|
const value = {
|
||||||
|
window: _window,
|
||||||
|
popoutGroup: group,
|
||||||
|
referenceGroup: referenceGroup.id,
|
||||||
|
disposable: popoutWindowDisposable,
|
||||||
|
};
|
||||||
|
|
||||||
|
popoutWindowDisposable.addDisposables(
|
||||||
|
/**
|
||||||
|
* ResizeObserver seems slow here, I do not know why but we don't need it
|
||||||
|
* since we can reply on the window resize event as we will occupy the full
|
||||||
|
* window dimensions
|
||||||
|
*/
|
||||||
|
addDisposableWindowListener(
|
||||||
|
_window.window!,
|
||||||
|
'resize',
|
||||||
|
() => {
|
||||||
|
group.layout(window.innerWidth, window.innerHeight);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
overlayRenderContainer,
|
||||||
|
Disposable.from(() => {
|
||||||
|
if (this.getPanel(referenceGroup.id)) {
|
||||||
|
moveGroupWithoutDestroying({
|
||||||
|
from: group,
|
||||||
|
to: referenceGroup,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (referenceGroup.api.isHidden) {
|
||||||
|
referenceGroup.api.setHidden(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.doRemoveGroup(group, {
|
||||||
|
skipPopoutAssociated: true,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const removedGroup = this.doRemoveGroup(group, {
|
||||||
|
skipDispose: true,
|
||||||
|
skipActive: true,
|
||||||
|
});
|
||||||
|
removedGroup.model.renderContainer =
|
||||||
|
this.overlayRenderContainer;
|
||||||
|
removedGroup.model.location = { type: 'grid' };
|
||||||
|
this.doAddGroup(removedGroup, [0]);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
this._popoutGroups.push(value);
|
||||||
|
this.updateWatermark();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
addFloatingGroup(
|
addFloatingGroup(
|
||||||
@ -608,7 +758,7 @@ export class DockviewComponent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
group.model.location = 'floating';
|
group.model.location = { type: 'floating' };
|
||||||
|
|
||||||
const overlayLeft =
|
const overlayLeft =
|
||||||
typeof coord?.x === 'number'
|
typeof coord?.x === 'number'
|
||||||
@ -683,7 +833,7 @@ export class DockviewComponent
|
|||||||
dispose: () => {
|
dispose: () => {
|
||||||
disposable.dispose();
|
disposable.dispose();
|
||||||
|
|
||||||
group.model.location = 'grid';
|
group.model.location = { type: 'grid' };
|
||||||
remove(this._floatingGroups, floatingGroupPanel);
|
remove(this._floatingGroups, floatingGroupPanel);
|
||||||
this.updateWatermark();
|
this.updateWatermark();
|
||||||
},
|
},
|
||||||
@ -876,7 +1026,8 @@ export class DockviewComponent
|
|||||||
const popoutGroups: SerializedPopoutGroup[] = this._popoutGroups.map(
|
const popoutGroups: SerializedPopoutGroup[] = this._popoutGroups.map(
|
||||||
(group) => {
|
(group) => {
|
||||||
return {
|
return {
|
||||||
data: group.group.toJSON() as GroupPanelViewState,
|
data: group.popoutGroup.toJSON() as GroupPanelViewState,
|
||||||
|
gridReferenceGroup: group.referenceGroup,
|
||||||
position: group.window.dimensions(),
|
position: group.window.dimensions(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -1004,14 +1155,23 @@ export class DockviewComponent
|
|||||||
const serializedPopoutGroups = data.popoutGroups ?? [];
|
const serializedPopoutGroups = data.popoutGroups ?? [];
|
||||||
|
|
||||||
for (const serializedPopoutGroup of serializedPopoutGroups) {
|
for (const serializedPopoutGroup of serializedPopoutGroups) {
|
||||||
const { data, position } = serializedPopoutGroup;
|
const { data, position, gridReferenceGroup } =
|
||||||
|
serializedPopoutGroup;
|
||||||
|
|
||||||
const group = createGroupFromSerializedState(data);
|
const group = createGroupFromSerializedState(data);
|
||||||
|
|
||||||
this.addPopoutGroup(group, {
|
this.addPopoutGroup(
|
||||||
skipRemoveGroup: true,
|
(gridReferenceGroup
|
||||||
position: position ?? undefined,
|
? this.getPanel(gridReferenceGroup)
|
||||||
});
|
: undefined) ?? group,
|
||||||
|
{
|
||||||
|
skipRemoveGroup: true,
|
||||||
|
position: position ?? undefined,
|
||||||
|
overridePopoutGroup: gridReferenceGroup
|
||||||
|
? group
|
||||||
|
: undefined,
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const floatingGroup of this._floatingGroups) {
|
for (const floatingGroup of this._floatingGroups) {
|
||||||
@ -1173,7 +1333,7 @@ export class DockviewComponent
|
|||||||
group.model.openPanel(panel);
|
group.model.openPanel(panel);
|
||||||
this.doSetGroupAndPanelActive(group);
|
this.doSetGroupAndPanelActive(group);
|
||||||
} else if (
|
} else if (
|
||||||
referenceGroup.api.location === 'floating' ||
|
referenceGroup.api.location.type === 'floating' ||
|
||||||
target === 'center'
|
target === 'center'
|
||||||
) {
|
) {
|
||||||
panel = this.createPanel(options, referenceGroup);
|
panel = this.createPanel(options, referenceGroup);
|
||||||
@ -1259,7 +1419,11 @@ export class DockviewComponent
|
|||||||
}
|
}
|
||||||
|
|
||||||
private updateWatermark(): void {
|
private updateWatermark(): void {
|
||||||
if (this.groups.filter((x) => x.api.location === 'grid').length === 0) {
|
if (
|
||||||
|
this.groups.filter(
|
||||||
|
(x) => x.api.location.type === 'grid' && !x.api.isHidden
|
||||||
|
).length === 0
|
||||||
|
) {
|
||||||
if (!this.watermark) {
|
if (!this.watermark) {
|
||||||
this.watermark = this.createWatermarkComponent();
|
this.watermark = this.createWatermarkComponent();
|
||||||
|
|
||||||
@ -1374,10 +1538,11 @@ export class DockviewComponent
|
|||||||
| {
|
| {
|
||||||
skipActive?: boolean;
|
skipActive?: boolean;
|
||||||
skipDispose?: boolean;
|
skipDispose?: boolean;
|
||||||
|
skipPopoutAssociated?: boolean;
|
||||||
}
|
}
|
||||||
| undefined
|
| undefined
|
||||||
): DockviewGroupPanel {
|
): DockviewGroupPanel {
|
||||||
if (group.api.location === 'floating') {
|
if (group.api.location.type === 'floating') {
|
||||||
const floatingGroup = this._floatingGroups.find(
|
const floatingGroup = this._floatingGroups.find(
|
||||||
(_) => _.group === group
|
(_) => _.group === group
|
||||||
);
|
);
|
||||||
@ -1406,19 +1571,28 @@ export class DockviewComponent
|
|||||||
throw new Error('failed to find floating group');
|
throw new Error('failed to find floating group');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (group.api.location === 'popout') {
|
if (group.api.location.type === 'popout') {
|
||||||
const selectedGroup = this._popoutGroups.find(
|
const selectedGroup = this._popoutGroups.find(
|
||||||
(_) => _.group === group
|
(_) => _.popoutGroup === group
|
||||||
);
|
);
|
||||||
|
|
||||||
if (selectedGroup) {
|
if (selectedGroup) {
|
||||||
if (!options?.skipDispose) {
|
if (!options?.skipDispose) {
|
||||||
selectedGroup.group.dispose();
|
if (!options?.skipPopoutAssociated) {
|
||||||
|
const refGroup = this.getPanel(
|
||||||
|
selectedGroup.referenceGroup
|
||||||
|
);
|
||||||
|
if (refGroup) {
|
||||||
|
this.removeGroup(refGroup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedGroup.popoutGroup.dispose();
|
||||||
this._groups.delete(group.id);
|
this._groups.delete(group.id);
|
||||||
this._onDidRemoveGroup.fire(group);
|
this._onDidRemoveGroup.fire(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
selectedGroup.dispose();
|
selectedGroup.disposable.dispose();
|
||||||
|
|
||||||
if (!options?.skipActive && this._activeGroup === group) {
|
if (!options?.skipActive && this._activeGroup === group) {
|
||||||
const groups = Array.from(this._groups.values());
|
const groups = Array.from(this._groups.values());
|
||||||
@ -1428,7 +1602,8 @@ export class DockviewComponent
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return selectedGroup.group;
|
this.updateWatermark();
|
||||||
|
return selectedGroup.popoutGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error('failed to find popout group');
|
throw new Error('failed to find popout group');
|
||||||
@ -1486,7 +1661,7 @@ export class DockviewComponent
|
|||||||
if (sourceGroup && sourceGroup.size < 2) {
|
if (sourceGroup && sourceGroup.size < 2) {
|
||||||
const [targetParentLocation, to] = tail(targetLocation);
|
const [targetParentLocation, to] = tail(targetLocation);
|
||||||
|
|
||||||
if (sourceGroup.api.location === 'grid') {
|
if (sourceGroup.api.location.type === 'grid') {
|
||||||
const sourceLocation = getGridLocation(sourceGroup.element);
|
const sourceLocation = getGridLocation(sourceGroup.element);
|
||||||
const [sourceParentLocation, from] = tail(sourceLocation);
|
const [sourceParentLocation, from] = tail(sourceLocation);
|
||||||
|
|
||||||
@ -1562,7 +1737,7 @@ export class DockviewComponent
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (sourceGroup.api.location) {
|
switch (sourceGroup.api.location.type) {
|
||||||
case 'grid':
|
case 'grid':
|
||||||
this.gridview.removeView(
|
this.gridview.removeView(
|
||||||
getGridLocation(sourceGroup.element)
|
getGridLocation(sourceGroup.element)
|
||||||
@ -1580,12 +1755,12 @@ export class DockviewComponent
|
|||||||
}
|
}
|
||||||
case 'popout': {
|
case 'popout': {
|
||||||
const selectedPopoutGroup = this._popoutGroups.find(
|
const selectedPopoutGroup = this._popoutGroups.find(
|
||||||
(x) => x.group === sourceGroup
|
(x) => x.popoutGroup === sourceGroup
|
||||||
);
|
);
|
||||||
if (!selectedPopoutGroup) {
|
if (!selectedPopoutGroup) {
|
||||||
throw new Error('failed to find popout group');
|
throw new Error('failed to find popout group');
|
||||||
}
|
}
|
||||||
selectedPopoutGroup.dispose();
|
selectedPopoutGroup.disposable.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1618,6 +1793,15 @@ export class DockviewComponent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getNextGroupId(): string {
|
||||||
|
let id = this.nextGroupId.next();
|
||||||
|
while (this._groups.has(id)) {
|
||||||
|
id = this.nextGroupId.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
createGroup(options?: GroupOptions): DockviewGroupPanel {
|
createGroup(options?: GroupOptions): DockviewGroupPanel {
|
||||||
if (!options) {
|
if (!options) {
|
||||||
options = {};
|
options = {};
|
||||||
@ -1640,7 +1824,7 @@ export class DockviewComponent
|
|||||||
}
|
}
|
||||||
|
|
||||||
const view = new DockviewGroupPanel(this, id, options);
|
const view = new DockviewGroupPanel(this, id, options);
|
||||||
view.init({ params: {}, accessor: <any>null }); // required to initialized .part and allow for correct disposal of group
|
view.init({ params: {}, accessor: this });
|
||||||
|
|
||||||
if (!this._groups.has(view.id)) {
|
if (!this._groups.has(view.id)) {
|
||||||
const disposable = new CompositeDisposable(
|
const disposable = new CompositeDisposable(
|
||||||
@ -1655,11 +1839,18 @@ export class DockviewComponent
|
|||||||
this.moveGroupOrPanel(view, groupId, itemId, target, index);
|
this.moveGroupOrPanel(view, groupId, itemId, target, index);
|
||||||
}),
|
}),
|
||||||
view.model.onDidDrop((event) => {
|
view.model.onDidDrop((event) => {
|
||||||
this._onDidDrop.fire({
|
this._onDidDrop.fire(event);
|
||||||
...event,
|
}),
|
||||||
api: this._api,
|
view.model.onWillDrop((event) => {
|
||||||
group: view,
|
this._onWillDrop.fire(event);
|
||||||
});
|
}),
|
||||||
|
view.model.onWillShowOverlay((event) => {
|
||||||
|
if (this.options.disableDnd) {
|
||||||
|
event.event.preventDefault();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._onWillShowOverlay.fire(event);
|
||||||
}),
|
}),
|
||||||
view.model.onDidAddPanel((event) => {
|
view.model.onDidAddPanel((event) => {
|
||||||
this._onDidAddPanel.fire(event.panel);
|
this._onDidAddPanel.fire(event.panel);
|
||||||
@ -1675,8 +1866,7 @@ export class DockviewComponent
|
|||||||
this._groups.set(view.id, { value: view, disposable });
|
this._groups.set(view.id, { value: view, disposable });
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: must be called after the above listeners have been setup,
|
// TODO: must be called after the above listeners have been setup, not an ideal pattern
|
||||||
// not an ideal pattern
|
|
||||||
view.initialize();
|
view.initialize();
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
import { DockviewApi } from '../api/component.api';
|
import { DockviewApi } from '../api/component.api';
|
||||||
import { getPanelData, PanelTransfer } from '../dnd/dataTransfer';
|
import { getPanelData, PanelTransfer } from '../dnd/dataTransfer';
|
||||||
import { Position } from '../dnd/droptarget';
|
import { Position, WillShowOverlayEvent } from '../dnd/droptarget';
|
||||||
import { DockviewComponent } from './dockviewComponent';
|
import { DockviewComponent } from './dockviewComponent';
|
||||||
import { isAncestor, toggleClass } from '../dom';
|
import { isAncestor, toggleClass } from '../dom';
|
||||||
import { addDisposableListener, Emitter, Event } from '../events';
|
import {
|
||||||
|
addDisposableListener,
|
||||||
|
DockviewEvent,
|
||||||
|
Emitter,
|
||||||
|
Event,
|
||||||
|
} from '../events';
|
||||||
import { IViewSize } from '../gridview/gridview';
|
import { IViewSize } from '../gridview/gridview';
|
||||||
import { CompositeDisposable } from '../lifecycle';
|
import { CompositeDisposable } from '../lifecycle';
|
||||||
import { IPanel, PanelInitParameters, PanelUpdateEvent } from '../panel/types';
|
import { IPanel, PanelInitParameters, PanelUpdateEvent } from '../panel/types';
|
||||||
@ -21,26 +26,7 @@ import { DockviewDropTargets, IWatermarkRenderer } from './types';
|
|||||||
import { DockviewGroupPanel } from './dockviewGroupPanel';
|
import { DockviewGroupPanel } from './dockviewGroupPanel';
|
||||||
import { IDockviewPanel } from './dockviewPanel';
|
import { IDockviewPanel } from './dockviewPanel';
|
||||||
import { IHeaderActionsRenderer } from './options';
|
import { IHeaderActionsRenderer } from './options';
|
||||||
|
import { OverlayRenderContainer } from '../overlayRenderContainer';
|
||||||
export interface DndService {
|
|
||||||
canDisplayOverlay(
|
|
||||||
group: IDockviewGroupPanelModel,
|
|
||||||
event: DragEvent,
|
|
||||||
target: DockviewDropTargets
|
|
||||||
): boolean;
|
|
||||||
onDrop(
|
|
||||||
group: IDockviewGroupPanelModel,
|
|
||||||
event: DragEvent,
|
|
||||||
position: Position,
|
|
||||||
index?: number
|
|
||||||
): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IGroupItem {
|
|
||||||
id: string;
|
|
||||||
header: { element: HTMLElement };
|
|
||||||
body: { element: HTMLElement };
|
|
||||||
}
|
|
||||||
|
|
||||||
interface GroupMoveEvent {
|
interface GroupMoveEvent {
|
||||||
groupId: string;
|
groupId: string;
|
||||||
@ -66,15 +52,69 @@ export interface GroupPanelViewState extends CoreGroupOptions {
|
|||||||
id: string;
|
id: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GroupviewChangeEvent {
|
export interface DockviewGroupChangeEvent {
|
||||||
readonly panel: IDockviewPanel;
|
readonly panel: IDockviewPanel;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GroupviewDropEvent {
|
export class DockviewDidDropEvent extends DockviewEvent {
|
||||||
readonly nativeEvent: DragEvent;
|
get nativeEvent(): DragEvent {
|
||||||
readonly position: Position;
|
return this.options.nativeEvent;
|
||||||
readonly index?: number;
|
}
|
||||||
getData(): PanelTransfer | undefined;
|
|
||||||
|
get position(): Position {
|
||||||
|
return this.options.position;
|
||||||
|
}
|
||||||
|
|
||||||
|
get panel(): IDockviewPanel | undefined {
|
||||||
|
return this.options.panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
get group(): DockviewGroupPanel | undefined {
|
||||||
|
return this.options.group;
|
||||||
|
}
|
||||||
|
|
||||||
|
get api(): DockviewApi {
|
||||||
|
return this.options.api;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private readonly options: {
|
||||||
|
readonly nativeEvent: DragEvent;
|
||||||
|
readonly position: Position;
|
||||||
|
readonly panel?: IDockviewPanel;
|
||||||
|
getData(): PanelTransfer | undefined;
|
||||||
|
group?: DockviewGroupPanel;
|
||||||
|
api: DockviewApi;
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
getData(): PanelTransfer | undefined {
|
||||||
|
return this.options.getData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DockviewWillDropEvent extends DockviewDidDropEvent {
|
||||||
|
private readonly _kind: DockviewGroupDropLocation;
|
||||||
|
|
||||||
|
get kind(): DockviewGroupDropLocation {
|
||||||
|
return this._kind;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(options: {
|
||||||
|
readonly nativeEvent: DragEvent;
|
||||||
|
readonly position: Position;
|
||||||
|
readonly panel?: IDockviewPanel;
|
||||||
|
getData(): PanelTransfer | undefined;
|
||||||
|
kind: DockviewGroupDropLocation;
|
||||||
|
group?: DockviewGroupPanel;
|
||||||
|
api: DockviewApi;
|
||||||
|
}) {
|
||||||
|
super(options);
|
||||||
|
|
||||||
|
this._kind = options.kind;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IHeader {
|
export interface IHeader {
|
||||||
@ -83,6 +123,8 @@ export interface IHeader {
|
|||||||
|
|
||||||
export type DockviewGroupPanelLocked = boolean | 'no-drop-target';
|
export type DockviewGroupPanelLocked = boolean | 'no-drop-target';
|
||||||
|
|
||||||
|
export type DockviewGroupDropLocation = 'tab' | 'header_space' | 'content';
|
||||||
|
|
||||||
export interface IDockviewGroupPanelModel extends IPanel {
|
export interface IDockviewGroupPanelModel extends IPanel {
|
||||||
readonly isActive: boolean;
|
readonly isActive: boolean;
|
||||||
readonly size: number;
|
readonly size: number;
|
||||||
@ -90,10 +132,11 @@ export interface IDockviewGroupPanelModel extends IPanel {
|
|||||||
readonly activePanel: IDockviewPanel | undefined;
|
readonly activePanel: IDockviewPanel | undefined;
|
||||||
readonly header: IHeader;
|
readonly header: IHeader;
|
||||||
readonly isContentFocused: boolean;
|
readonly isContentFocused: boolean;
|
||||||
readonly onDidDrop: Event<GroupviewDropEvent>;
|
readonly onDidDrop: Event<DockviewDidDropEvent>;
|
||||||
readonly onDidAddPanel: Event<GroupviewChangeEvent>;
|
readonly onWillDrop: Event<DockviewWillDropEvent>;
|
||||||
readonly onDidRemovePanel: Event<GroupviewChangeEvent>;
|
readonly onDidAddPanel: Event<DockviewGroupChangeEvent>;
|
||||||
readonly onDidActivePanelChange: Event<GroupviewChangeEvent>;
|
readonly onDidRemovePanel: Event<DockviewGroupChangeEvent>;
|
||||||
|
readonly onDidActivePanelChange: Event<DockviewGroupChangeEvent>;
|
||||||
readonly onMove: Event<GroupMoveEvent>;
|
readonly onMove: Event<GroupMoveEvent>;
|
||||||
locked: DockviewGroupPanelLocked;
|
locked: DockviewGroupPanelLocked;
|
||||||
setActive(isActive: boolean): void;
|
setActive(isActive: boolean): void;
|
||||||
@ -130,7 +173,15 @@ export interface IDockviewGroupPanelModel extends IPanel {
|
|||||||
): boolean;
|
): boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type DockviewGroupLocation = 'grid' | 'floating' | 'popout';
|
export type DockviewGroupLocation =
|
||||||
|
| { type: 'grid' }
|
||||||
|
| { type: 'floating' }
|
||||||
|
| { type: 'popout'; getWindow: () => Window };
|
||||||
|
|
||||||
|
export interface WillShowOverlayLocationEvent {
|
||||||
|
event: WillShowOverlayEvent;
|
||||||
|
kind: DockviewGroupDropLocation;
|
||||||
|
}
|
||||||
|
|
||||||
export class DockviewGroupPanelModel
|
export class DockviewGroupPanelModel
|
||||||
extends CompositeDisposable
|
extends CompositeDisposable
|
||||||
@ -146,7 +197,7 @@ export class DockviewGroupPanelModel
|
|||||||
private _leftHeaderActions: IHeaderActionsRenderer | undefined;
|
private _leftHeaderActions: IHeaderActionsRenderer | undefined;
|
||||||
private _prefixHeaderActions: IHeaderActionsRenderer | undefined;
|
private _prefixHeaderActions: IHeaderActionsRenderer | undefined;
|
||||||
|
|
||||||
private _location: DockviewGroupLocation = 'grid';
|
private _location: DockviewGroupLocation = { type: 'grid' };
|
||||||
|
|
||||||
private mostRecentlyUsed: IDockviewPanel[] = [];
|
private mostRecentlyUsed: IDockviewPanel[] = [];
|
||||||
|
|
||||||
@ -162,8 +213,16 @@ export class DockviewGroupPanelModel
|
|||||||
private readonly _onMove = new Emitter<GroupMoveEvent>();
|
private readonly _onMove = new Emitter<GroupMoveEvent>();
|
||||||
readonly onMove: Event<GroupMoveEvent> = this._onMove.event;
|
readonly onMove: Event<GroupMoveEvent> = this._onMove.event;
|
||||||
|
|
||||||
private readonly _onDidDrop = new Emitter<GroupviewDropEvent>();
|
private readonly _onDidDrop = new Emitter<DockviewDidDropEvent>();
|
||||||
readonly onDidDrop: Event<GroupviewDropEvent> = this._onDidDrop.event;
|
readonly onDidDrop: Event<DockviewDidDropEvent> = this._onDidDrop.event;
|
||||||
|
|
||||||
|
private readonly _onWillDrop = new Emitter<DockviewWillDropEvent>();
|
||||||
|
readonly onWillDrop: Event<DockviewWillDropEvent> = this._onWillDrop.event;
|
||||||
|
|
||||||
|
private readonly _onWillShowOverlay =
|
||||||
|
new Emitter<WillShowOverlayLocationEvent>();
|
||||||
|
readonly onWillShowOverlay: Event<WillShowOverlayLocationEvent> =
|
||||||
|
this._onWillShowOverlay.event;
|
||||||
|
|
||||||
private readonly _onTabDragStart = new Emitter<TabDragEvent>();
|
private readonly _onTabDragStart = new Emitter<TabDragEvent>();
|
||||||
readonly onTabDragStart: Event<TabDragEvent> = this._onTabDragStart.event;
|
readonly onTabDragStart: Event<TabDragEvent> = this._onTabDragStart.event;
|
||||||
@ -172,19 +231,22 @@ export class DockviewGroupPanelModel
|
|||||||
readonly onGroupDragStart: Event<GroupDragEvent> =
|
readonly onGroupDragStart: Event<GroupDragEvent> =
|
||||||
this._onGroupDragStart.event;
|
this._onGroupDragStart.event;
|
||||||
|
|
||||||
private readonly _onDidAddPanel = new Emitter<GroupviewChangeEvent>();
|
private readonly _onDidAddPanel = new Emitter<DockviewGroupChangeEvent>();
|
||||||
readonly onDidAddPanel: Event<GroupviewChangeEvent> =
|
readonly onDidAddPanel: Event<DockviewGroupChangeEvent> =
|
||||||
this._onDidAddPanel.event;
|
this._onDidAddPanel.event;
|
||||||
|
|
||||||
private readonly _onDidRemovePanel = new Emitter<GroupviewChangeEvent>();
|
private readonly _onDidRemovePanel =
|
||||||
readonly onDidRemovePanel: Event<GroupviewChangeEvent> =
|
new Emitter<DockviewGroupChangeEvent>();
|
||||||
|
readonly onDidRemovePanel: Event<DockviewGroupChangeEvent> =
|
||||||
this._onDidRemovePanel.event;
|
this._onDidRemovePanel.event;
|
||||||
|
|
||||||
private readonly _onDidActivePanelChange =
|
private readonly _onDidActivePanelChange =
|
||||||
new Emitter<GroupviewChangeEvent>();
|
new Emitter<DockviewGroupChangeEvent>();
|
||||||
readonly onDidActivePanelChange: Event<GroupviewChangeEvent> =
|
readonly onDidActivePanelChange: Event<DockviewGroupChangeEvent> =
|
||||||
this._onDidActivePanelChange.event;
|
this._onDidActivePanelChange.event;
|
||||||
|
|
||||||
|
private readonly _api: DockviewApi;
|
||||||
|
|
||||||
get element(): HTMLElement {
|
get element(): HTMLElement {
|
||||||
throw new Error('not supported');
|
throw new Error('not supported');
|
||||||
}
|
}
|
||||||
@ -253,7 +315,7 @@ export class DockviewGroupPanelModel
|
|||||||
toggleClass(this.container, 'dv-groupview-floating', false);
|
toggleClass(this.container, 'dv-groupview-floating', false);
|
||||||
toggleClass(this.container, 'dv-groupview-popout', false);
|
toggleClass(this.container, 'dv-groupview-popout', false);
|
||||||
|
|
||||||
switch (value) {
|
switch (value.type) {
|
||||||
case 'grid':
|
case 'grid':
|
||||||
this.contentContainer.dropTarget.setTargetZones([
|
this.contentContainer.dropTarget.setTargetZones([
|
||||||
'top',
|
'top',
|
||||||
@ -298,6 +360,8 @@ export class DockviewGroupPanelModel
|
|||||||
|
|
||||||
toggleClass(this.container, 'groupview', true);
|
toggleClass(this.container, 'groupview', true);
|
||||||
|
|
||||||
|
this._api = new DockviewApi(this.accessor);
|
||||||
|
|
||||||
this.tabsContainer = new TabsContainer(this.accessor, this.groupPanel);
|
this.tabsContainer = new TabsContainer(this.accessor, this.groupPanel);
|
||||||
|
|
||||||
this.contentContainer = new ContentContainer(this.accessor, this);
|
this.contentContainer = new ContentContainer(this.accessor, this);
|
||||||
@ -313,6 +377,7 @@ export class DockviewGroupPanelModel
|
|||||||
this.addDisposables(
|
this.addDisposables(
|
||||||
this._onTabDragStart,
|
this._onTabDragStart,
|
||||||
this._onGroupDragStart,
|
this._onGroupDragStart,
|
||||||
|
this._onWillShowOverlay,
|
||||||
this.tabsContainer.onTabDragStart((event) => {
|
this.tabsContainer.onTabDragStart((event) => {
|
||||||
this._onTabDragStart.fire(event);
|
this._onTabDragStart.fire(event);
|
||||||
}),
|
}),
|
||||||
@ -320,8 +385,14 @@ export class DockviewGroupPanelModel
|
|||||||
this._onGroupDragStart.fire(event);
|
this._onGroupDragStart.fire(event);
|
||||||
}),
|
}),
|
||||||
this.tabsContainer.onDrop((event) => {
|
this.tabsContainer.onDrop((event) => {
|
||||||
this.handleDropEvent(event.event, 'center', event.index);
|
this.handleDropEvent(
|
||||||
|
'header',
|
||||||
|
event.event,
|
||||||
|
'center',
|
||||||
|
event.index
|
||||||
|
);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
this.contentContainer.onDidFocus(() => {
|
this.contentContainer.onDidFocus(() => {
|
||||||
this.accessor.doSetGroupActive(this.groupPanel);
|
this.accessor.doSetGroupActive(this.groupPanel);
|
||||||
}),
|
}),
|
||||||
@ -329,11 +400,22 @@ export class DockviewGroupPanelModel
|
|||||||
// noop
|
// noop
|
||||||
}),
|
}),
|
||||||
this.contentContainer.dropTarget.onDrop((event) => {
|
this.contentContainer.dropTarget.onDrop((event) => {
|
||||||
this.handleDropEvent(event.nativeEvent, event.position);
|
this.handleDropEvent(
|
||||||
|
'content',
|
||||||
|
event.nativeEvent,
|
||||||
|
event.position
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
this.tabsContainer.onWillShowOverlay((event) => {
|
||||||
|
this._onWillShowOverlay.fire(event);
|
||||||
|
}),
|
||||||
|
this.contentContainer.dropTarget.onWillShowOverlay((event) => {
|
||||||
|
this._onWillShowOverlay.fire({ event, kind: 'content' });
|
||||||
}),
|
}),
|
||||||
this._onMove,
|
this._onMove,
|
||||||
this._onDidChange,
|
this._onDidChange,
|
||||||
this._onDidDrop,
|
this._onDidDrop,
|
||||||
|
this._onWillDrop,
|
||||||
this._onDidAddPanel,
|
this._onDidAddPanel,
|
||||||
this._onDidRemovePanel,
|
this._onDidRemovePanel,
|
||||||
this._onDidActivePanelChange
|
this._onDidActivePanelChange
|
||||||
@ -344,14 +426,35 @@ export class DockviewGroupPanelModel
|
|||||||
this.contentContainer.element.focus();
|
this.contentContainer.element.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _overwriteRenderContainer: OverlayRenderContainer | null = null;
|
||||||
|
|
||||||
|
set renderContainer(value: OverlayRenderContainer | null) {
|
||||||
|
this.panels.forEach((panel) => {
|
||||||
|
this.renderContainer.detatch(panel);
|
||||||
|
});
|
||||||
|
|
||||||
|
this._overwriteRenderContainer = value;
|
||||||
|
|
||||||
|
this.panels.forEach((panel) => {
|
||||||
|
this.rerender(panel);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get renderContainer(): OverlayRenderContainer {
|
||||||
|
return (
|
||||||
|
this._overwriteRenderContainer ??
|
||||||
|
this.accessor.overlayRenderContainer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
initialize(): void {
|
initialize(): void {
|
||||||
if (this.options?.panels) {
|
if (this.options.panels) {
|
||||||
this.options.panels.forEach((panel) => {
|
this.options.panels.forEach((panel) => {
|
||||||
this.doAddPanel(panel);
|
this.doAddPanel(panel);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.options?.activePanel) {
|
if (this.options.activePanel) {
|
||||||
this.openPanel(this.options.activePanel);
|
this.openPanel(this.options.activePanel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,7 +470,7 @@ export class DockviewGroupPanelModel
|
|||||||
);
|
);
|
||||||
this.addDisposables(this._rightHeaderActions);
|
this.addDisposables(this._rightHeaderActions);
|
||||||
this._rightHeaderActions.init({
|
this._rightHeaderActions.init({
|
||||||
containerApi: new DockviewApi(this.accessor),
|
containerApi: this._api,
|
||||||
api: this.groupPanel.api,
|
api: this.groupPanel.api,
|
||||||
});
|
});
|
||||||
this.tabsContainer.setRightActionsElement(
|
this.tabsContainer.setRightActionsElement(
|
||||||
@ -382,7 +485,7 @@ export class DockviewGroupPanelModel
|
|||||||
);
|
);
|
||||||
this.addDisposables(this._leftHeaderActions);
|
this.addDisposables(this._leftHeaderActions);
|
||||||
this._leftHeaderActions.init({
|
this._leftHeaderActions.init({
|
||||||
containerApi: new DockviewApi(this.accessor),
|
containerApi: this._api,
|
||||||
api: this.groupPanel.api,
|
api: this.groupPanel.api,
|
||||||
});
|
});
|
||||||
this.tabsContainer.setLeftActionsElement(
|
this.tabsContainer.setLeftActionsElement(
|
||||||
@ -397,7 +500,7 @@ export class DockviewGroupPanelModel
|
|||||||
);
|
);
|
||||||
this.addDisposables(this._prefixHeaderActions);
|
this.addDisposables(this._prefixHeaderActions);
|
||||||
this._prefixHeaderActions.init({
|
this._prefixHeaderActions.init({
|
||||||
containerApi: new DockviewApi(this.accessor),
|
containerApi: this._api,
|
||||||
api: this.groupPanel.api,
|
api: this.groupPanel.api,
|
||||||
});
|
});
|
||||||
this.tabsContainer.setPrefixActionsElement(
|
this.tabsContainer.setPrefixActionsElement(
|
||||||
@ -732,7 +835,7 @@ export class DockviewGroupPanelModel
|
|||||||
if (this.isEmpty && !this.watermark) {
|
if (this.isEmpty && !this.watermark) {
|
||||||
const watermark = this.accessor.createWatermarkComponent();
|
const watermark = this.accessor.createWatermarkComponent();
|
||||||
watermark.init({
|
watermark.init({
|
||||||
containerApi: new DockviewApi(this.accessor),
|
containerApi: this._api,
|
||||||
group: this.groupPanel,
|
group: this.groupPanel,
|
||||||
});
|
});
|
||||||
this.watermark = watermark;
|
this.watermark = watermark;
|
||||||
@ -775,6 +878,7 @@ export class DockviewGroupPanelModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
private handleDropEvent(
|
private handleDropEvent(
|
||||||
|
type: 'header' | 'content',
|
||||||
event: DragEvent,
|
event: DragEvent,
|
||||||
position: Position,
|
position: Position,
|
||||||
index?: number
|
index?: number
|
||||||
@ -783,6 +887,34 @@ export class DockviewGroupPanelModel
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getKind(): DockviewGroupDropLocation {
|
||||||
|
switch (type) {
|
||||||
|
case 'header':
|
||||||
|
return typeof index === 'number' ? 'tab' : 'header_space';
|
||||||
|
case 'content':
|
||||||
|
return 'content';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const panel =
|
||||||
|
typeof index === 'number' ? this.panels[index] : undefined;
|
||||||
|
|
||||||
|
const willDropEvent = new DockviewWillDropEvent({
|
||||||
|
nativeEvent: event,
|
||||||
|
position,
|
||||||
|
panel,
|
||||||
|
getData: () => getPanelData(),
|
||||||
|
kind: getKind(),
|
||||||
|
group: this.groupPanel,
|
||||||
|
api: this._api,
|
||||||
|
});
|
||||||
|
|
||||||
|
this._onWillDrop.fire(willDropEvent);
|
||||||
|
|
||||||
|
if (willDropEvent.defaultPrevented) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const data = getPanelData();
|
const data = getPanelData();
|
||||||
|
|
||||||
if (data && data.viewId === this.accessor.id) {
|
if (data && data.viewId === this.accessor.id) {
|
||||||
@ -821,12 +953,16 @@ export class DockviewGroupPanelModel
|
|||||||
index,
|
index,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this._onDidDrop.fire({
|
this._onDidDrop.fire(
|
||||||
nativeEvent: event,
|
new DockviewDidDropEvent({
|
||||||
position,
|
nativeEvent: event,
|
||||||
index,
|
position,
|
||||||
getData: () => getPanelData(),
|
panel,
|
||||||
});
|
getData: () => getPanelData(),
|
||||||
|
group: this.groupPanel,
|
||||||
|
api: this._api,
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -835,6 +971,7 @@ export class DockviewGroupPanelModel
|
|||||||
|
|
||||||
this.watermark?.element.remove();
|
this.watermark?.element.remove();
|
||||||
this.watermark?.dispose?.();
|
this.watermark?.dispose?.();
|
||||||
|
this.watermark = undefined;
|
||||||
|
|
||||||
for (const panel of this.panels) {
|
for (const panel of this.panels) {
|
||||||
panel.dispose();
|
panel.dispose();
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
import { CompositeDisposable } from '../lifecycle';
|
|
||||||
import { PopoutWindow } from '../popoutWindow';
|
|
||||||
import { Box } from '../types';
|
|
||||||
import { DockviewGroupPanel } from './dockviewGroupPanel';
|
|
||||||
|
|
||||||
export class DockviewPopoutGroupPanel extends CompositeDisposable {
|
|
||||||
readonly window: PopoutWindow;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
readonly id: string,
|
|
||||||
readonly group: DockviewGroupPanel,
|
|
||||||
private readonly options: {
|
|
||||||
className: string;
|
|
||||||
popoutUrl: string;
|
|
||||||
box: Box;
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
super();
|
|
||||||
|
|
||||||
this.window = new PopoutWindow(id, options.className ?? '', {
|
|
||||||
url: this.options.popoutUrl,
|
|
||||||
left: this.options.box.left,
|
|
||||||
top: this.options.box.top,
|
|
||||||
width: this.options.box.width,
|
|
||||||
height: this.options.box.height,
|
|
||||||
});
|
|
||||||
|
|
||||||
group.model.location = 'popout';
|
|
||||||
|
|
||||||
this.addDisposables(
|
|
||||||
this.window,
|
|
||||||
{
|
|
||||||
dispose: () => {
|
|
||||||
group.model.location = 'grid';
|
|
||||||
},
|
|
||||||
},
|
|
||||||
this.window.onDidClose(() => {
|
|
||||||
this.dispose();
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
this.window.open(group.element);
|
|
||||||
}
|
|
||||||
}
|
|
@ -90,7 +90,7 @@ export interface DockviewComponentOptions extends DockviewRenderFunctions {
|
|||||||
group: DockviewGroupPanel
|
group: DockviewGroupPanel
|
||||||
) => IHeaderActionsRenderer;
|
) => IHeaderActionsRenderer;
|
||||||
singleTabMode?: 'fullwidth' | 'default';
|
singleTabMode?: 'fullwidth' | 'default';
|
||||||
parentElement?: HTMLElement;
|
parentElement: HTMLElement;
|
||||||
disableFloatingGroups?: boolean;
|
disableFloatingGroups?: boolean;
|
||||||
floatingGroupBounds?:
|
floatingGroupBounds?:
|
||||||
| 'boundedWithinViewport'
|
| 'boundedWithinViewport'
|
||||||
@ -102,6 +102,8 @@ export interface DockviewComponentOptions extends DockviewRenderFunctions {
|
|||||||
defaultRenderer?: DockviewPanelRenderer;
|
defaultRenderer?: DockviewPanelRenderer;
|
||||||
debug?: boolean;
|
debug?: boolean;
|
||||||
rootOverlayModel?: DroptargetOverlayModel;
|
rootOverlayModel?: DroptargetOverlayModel;
|
||||||
|
locked?: boolean;
|
||||||
|
disableDnd?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PanelOptions<P extends object = Parameters> {
|
export interface PanelOptions<P extends object = Parameters> {
|
||||||
|
@ -7,12 +7,7 @@ import { Optional } from '../types';
|
|||||||
import { DockviewGroupPanel, IDockviewGroupPanel } from './dockviewGroupPanel';
|
import { DockviewGroupPanel, IDockviewGroupPanel } from './dockviewGroupPanel';
|
||||||
import { DockviewPanelRenderer } from '../overlayRenderContainer';
|
import { DockviewPanelRenderer } from '../overlayRenderContainer';
|
||||||
|
|
||||||
export enum DockviewDropTargets {
|
export type DockviewDropTargets = 'tab' | 'panel' | 'tabContainer' | 'edge';
|
||||||
Tab,
|
|
||||||
Panel,
|
|
||||||
TabContainer,
|
|
||||||
Edge,
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface HeaderPartInitParameters {
|
export interface HeaderPartInitParameters {
|
||||||
title: string;
|
title: string;
|
||||||
|
@ -23,6 +23,7 @@ export namespace Event {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DockviewEvent {
|
export class DockviewEvent {
|
||||||
private _defaultPrevented = false;
|
private _defaultPrevented = false;
|
||||||
|
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
.dv-root-wrapper {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
import { Emitter, Event, TickDelayedEvent } from '../events';
|
import { Emitter, Event, TickDelayedEvent } from '../events';
|
||||||
import { getGridLocation, Gridview, IGridView } from './gridview';
|
import { getGridLocation, Gridview, IGridView } from './gridview';
|
||||||
import { Position } from '../dnd/droptarget';
|
import { Position } from '../dnd/droptarget';
|
||||||
import { IValueDisposable } from '../lifecycle';
|
import { Disposable, IValueDisposable } from '../lifecycle';
|
||||||
import { sequentialNumberGenerator } from '../math';
|
import { sequentialNumberGenerator } from '../math';
|
||||||
import { ISplitviewStyles, Orientation, Sizing } from '../splitview/splitview';
|
import { ISplitviewStyles, Orientation, Sizing } from '../splitview/splitview';
|
||||||
import { IPanel } from '../panel/types';
|
import { IPanel } from '../panel/types';
|
||||||
@ -32,8 +32,9 @@ export interface BaseGridOptions {
|
|||||||
readonly proportionalLayout: boolean;
|
readonly proportionalLayout: boolean;
|
||||||
readonly orientation: Orientation;
|
readonly orientation: Orientation;
|
||||||
readonly styles?: ISplitviewStyles;
|
readonly styles?: ISplitviewStyles;
|
||||||
readonly parentElement?: HTMLElement;
|
readonly parentElement: HTMLElement;
|
||||||
readonly disableAutoResizing?: boolean;
|
readonly disableAutoResizing?: boolean;
|
||||||
|
readonly locked?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IGridPanelView extends IGridView, IPanel {
|
export interface IGridPanelView extends IGridView, IPanel {
|
||||||
@ -133,8 +134,18 @@ export abstract class BaseGrid<T extends IGridPanelView>
|
|||||||
return this._activeGroup;
|
return this._activeGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get locked(): boolean {
|
||||||
|
return this.gridview.locked;
|
||||||
|
}
|
||||||
|
|
||||||
|
set locked(value: boolean) {
|
||||||
|
this.gridview.locked = value;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(options: BaseGridOptions) {
|
constructor(options: BaseGridOptions) {
|
||||||
super(options.parentElement, options.disableAutoResizing);
|
super(document.createElement('div'), options.disableAutoResizing);
|
||||||
|
|
||||||
|
options.parentElement.appendChild(this.element);
|
||||||
|
|
||||||
this.gridview = new Gridview(
|
this.gridview = new Gridview(
|
||||||
!!options.proportionalLayout,
|
!!options.proportionalLayout,
|
||||||
@ -142,11 +153,16 @@ export abstract class BaseGrid<T extends IGridPanelView>
|
|||||||
options.orientation
|
options.orientation
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.gridview.locked = !!options.locked;
|
||||||
|
|
||||||
this.element.appendChild(this.gridview.element);
|
this.element.appendChild(this.gridview.element);
|
||||||
|
|
||||||
this.layout(0, 0, true); // set some elements height/widths
|
this.layout(0, 0, true); // set some elements height/widths
|
||||||
|
|
||||||
this.addDisposables(
|
this.addDisposables(
|
||||||
|
Disposable.from(() => {
|
||||||
|
this.element.parentElement?.removeChild(this.element);
|
||||||
|
}),
|
||||||
this.gridview.onDidChange(() => {
|
this.gridview.onDidChange(() => {
|
||||||
this._bufferOnDidLayoutChange.fire();
|
this._bufferOnDidLayoutChange.fire();
|
||||||
}),
|
}),
|
||||||
|
@ -131,17 +131,27 @@ export class BranchNode extends CompositeDisposable implements IView {
|
|||||||
return LayoutPriority.Normal;
|
return LayoutPriority.Normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get disabled(): boolean {
|
||||||
|
return this.splitview.disabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
set disabled(value: boolean) {
|
||||||
|
this.splitview.disabled = value;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
readonly orientation: Orientation,
|
readonly orientation: Orientation,
|
||||||
readonly proportionalLayout: boolean,
|
readonly proportionalLayout: boolean,
|
||||||
readonly styles: ISplitviewStyles | undefined,
|
readonly styles: ISplitviewStyles | undefined,
|
||||||
size: number,
|
size: number,
|
||||||
orthogonalSize: number,
|
orthogonalSize: number,
|
||||||
|
disabled: boolean,
|
||||||
childDescriptors?: INodeDescriptor[]
|
childDescriptors?: INodeDescriptor[]
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this._orthogonalSize = orthogonalSize;
|
this._orthogonalSize = orthogonalSize;
|
||||||
this._size = size;
|
this._size = size;
|
||||||
|
|
||||||
this.element = document.createElement('div');
|
this.element = document.createElement('div');
|
||||||
this.element.className = 'branch-node';
|
this.element.className = 'branch-node';
|
||||||
|
|
||||||
@ -177,6 +187,8 @@ export class BranchNode extends CompositeDisposable implements IView {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.disabled = disabled;
|
||||||
|
|
||||||
this.addDisposables(
|
this.addDisposables(
|
||||||
this._onDidChange,
|
this._onDidChange,
|
||||||
this._onDidVisibilityChange,
|
this._onDidVisibilityChange,
|
||||||
@ -202,7 +214,7 @@ export class BranchNode extends CompositeDisposable implements IView {
|
|||||||
return this.splitview.isViewVisible(index);
|
return this.splitview.isViewVisible(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
setChildVisible(index: number, visible: boolean): void {
|
setChildVisible(index: number, visible: boolean): void {
|
||||||
if (index < 0 || index >= this.children.length) {
|
if (index < 0 || index >= this.children.length) {
|
||||||
throw new Error('Invalid index');
|
throw new Error('Invalid index');
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,8 @@ function flipNode<T extends Node>(
|
|||||||
node.proportionalLayout,
|
node.proportionalLayout,
|
||||||
node.styles,
|
node.styles,
|
||||||
size,
|
size,
|
||||||
orthogonalSize
|
orthogonalSize,
|
||||||
|
node.disabled
|
||||||
);
|
);
|
||||||
|
|
||||||
let totalSize = 0;
|
let totalSize = 0;
|
||||||
@ -273,7 +274,10 @@ export class Gridview implements IDisposable {
|
|||||||
readonly element: HTMLElement;
|
readonly element: HTMLElement;
|
||||||
|
|
||||||
private _root: BranchNode | undefined;
|
private _root: BranchNode | undefined;
|
||||||
private _maximizedNode: LeafNode | undefined = undefined;
|
private _locked = false;
|
||||||
|
private _maximizedNode:
|
||||||
|
| { leaf: LeafNode; hiddenOnMaximize: LeafNode[] }
|
||||||
|
| undefined = undefined;
|
||||||
private readonly disposable: MutableDisposable = new MutableDisposable();
|
private readonly disposable: MutableDisposable = new MutableDisposable();
|
||||||
|
|
||||||
private readonly _onDidChange = new Emitter<{
|
private readonly _onDidChange = new Emitter<{
|
||||||
@ -328,8 +332,32 @@ export class Gridview implements IDisposable {
|
|||||||
return this.root.maximumHeight;
|
return this.root.maximumHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get locked(): boolean {
|
||||||
|
return this._locked;
|
||||||
|
}
|
||||||
|
|
||||||
|
set locked(value: boolean) {
|
||||||
|
this._locked = value;
|
||||||
|
|
||||||
|
const branch: Node[] = [this.root];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* simple depth-first-search to cover all nodes
|
||||||
|
*
|
||||||
|
* @see https://en.wikipedia.org/wiki/Depth-first_search
|
||||||
|
*/
|
||||||
|
while (branch.length > 0) {
|
||||||
|
const node = branch.pop();
|
||||||
|
|
||||||
|
if (node instanceof BranchNode) {
|
||||||
|
node.disabled = value;
|
||||||
|
branch.push(...node.children);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
maximizedView(): IGridView | undefined {
|
maximizedView(): IGridView | undefined {
|
||||||
return this._maximizedNode?.view;
|
return this._maximizedNode?.leaf.view;
|
||||||
}
|
}
|
||||||
|
|
||||||
hasMaximizedView(): boolean {
|
hasMaximizedView(): boolean {
|
||||||
@ -344,7 +372,7 @@ export class Gridview implements IDisposable {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._maximizedNode === node) {
|
if (this._maximizedNode?.leaf === node) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,12 +380,18 @@ export class Gridview implements IDisposable {
|
|||||||
this.exitMaximizedView();
|
this.exitMaximizedView();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const hiddenOnMaximize: LeafNode[] = [];
|
||||||
|
|
||||||
function hideAllViewsBut(parent: BranchNode, exclude: LeafNode): void {
|
function hideAllViewsBut(parent: BranchNode, exclude: LeafNode): void {
|
||||||
for (let i = 0; i < parent.children.length; i++) {
|
for (let i = 0; i < parent.children.length; i++) {
|
||||||
const child = parent.children[i];
|
const child = parent.children[i];
|
||||||
if (child instanceof LeafNode) {
|
if (child instanceof LeafNode) {
|
||||||
if (child !== exclude) {
|
if (child !== exclude) {
|
||||||
parent.setChildVisible(i, false);
|
if (parent.isChildVisible(i)) {
|
||||||
|
parent.setChildVisible(i, false);
|
||||||
|
} else {
|
||||||
|
hiddenOnMaximize.push(child);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
hideAllViewsBut(child, exclude);
|
hideAllViewsBut(child, exclude);
|
||||||
@ -366,7 +400,7 @@ export class Gridview implements IDisposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hideAllViewsBut(this.root, node);
|
hideAllViewsBut(this.root, node);
|
||||||
this._maximizedNode = node;
|
this._maximizedNode = { leaf: node, hiddenOnMaximize };
|
||||||
this._onDidMaxmizedNodeChange.fire();
|
this._onDidMaxmizedNodeChange.fire();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,11 +409,15 @@ export class Gridview implements IDisposable {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const hiddenOnMaximize = this._maximizedNode.hiddenOnMaximize;
|
||||||
|
|
||||||
function showViewsInReverseOrder(parent: BranchNode): void {
|
function showViewsInReverseOrder(parent: BranchNode): void {
|
||||||
for (let index = parent.children.length - 1; index >= 0; index--) {
|
for (let index = parent.children.length - 1; index >= 0; index--) {
|
||||||
const child = parent.children[index];
|
const child = parent.children[index];
|
||||||
if (child instanceof LeafNode) {
|
if (child instanceof LeafNode) {
|
||||||
parent.setChildVisible(index, true);
|
if (!hiddenOnMaximize.includes(child)) {
|
||||||
|
parent.setChildVisible(index, true);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
showViewsInReverseOrder(child);
|
showViewsInReverseOrder(child);
|
||||||
}
|
}
|
||||||
@ -395,8 +433,8 @@ export class Gridview implements IDisposable {
|
|||||||
public serialize(): SerializedGridview<any> {
|
public serialize(): SerializedGridview<any> {
|
||||||
if (this.hasMaximizedView()) {
|
if (this.hasMaximizedView()) {
|
||||||
/**
|
/**
|
||||||
* do not persist maximized view state but we must first exit any maximized views
|
* do not persist maximized view state
|
||||||
* before serialization to ensure the correct dimensions are persisted
|
* firstly exit any maximized views to ensure the correct dimensions are persisted
|
||||||
*/
|
*/
|
||||||
this.exitMaximizedView();
|
this.exitMaximizedView();
|
||||||
}
|
}
|
||||||
@ -427,7 +465,8 @@ export class Gridview implements IDisposable {
|
|||||||
this.proportionalLayout,
|
this.proportionalLayout,
|
||||||
this.styles,
|
this.styles,
|
||||||
this.root.size,
|
this.root.size,
|
||||||
this.root.orthogonalSize
|
this.root.orthogonalSize,
|
||||||
|
this._locked
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -487,8 +526,8 @@ export class Gridview implements IDisposable {
|
|||||||
this.proportionalLayout,
|
this.proportionalLayout,
|
||||||
this.styles,
|
this.styles,
|
||||||
node.size, // <- orthogonal size - flips at each depth
|
node.size, // <- orthogonal size - flips at each depth
|
||||||
orthogonalSize, // <- size - flips at each depth
|
orthogonalSize, // <- size - flips at each depth,
|
||||||
|
this._locked,
|
||||||
children
|
children
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@ -540,7 +579,8 @@ export class Gridview implements IDisposable {
|
|||||||
this.proportionalLayout,
|
this.proportionalLayout,
|
||||||
this.styles,
|
this.styles,
|
||||||
this.root.orthogonalSize,
|
this.root.orthogonalSize,
|
||||||
this.root.size
|
this.root.size,
|
||||||
|
this._locked
|
||||||
);
|
);
|
||||||
|
|
||||||
if (oldRoot.children.length === 0) {
|
if (oldRoot.children.length === 0) {
|
||||||
@ -655,7 +695,8 @@ export class Gridview implements IDisposable {
|
|||||||
proportionalLayout,
|
proportionalLayout,
|
||||||
styles,
|
styles,
|
||||||
0,
|
0,
|
||||||
0
|
0,
|
||||||
|
this._locked
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -739,7 +780,8 @@ export class Gridview implements IDisposable {
|
|||||||
this.proportionalLayout,
|
this.proportionalLayout,
|
||||||
this.styles,
|
this.styles,
|
||||||
parent.size,
|
parent.size,
|
||||||
parent.orthogonalSize
|
parent.orthogonalSize,
|
||||||
|
this._locked
|
||||||
);
|
);
|
||||||
grandParent.addChild(newParent, parent.size, parentIndex);
|
grandParent.addChild(newParent, parent.size, parentIndex);
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ import {
|
|||||||
import { LayoutPriority } from '../splitview/splitview';
|
import { LayoutPriority } from '../splitview/splitview';
|
||||||
import { Emitter, Event } from '../events';
|
import { Emitter, Event } from '../events';
|
||||||
import { IViewSize } from './gridview';
|
import { IViewSize } from './gridview';
|
||||||
|
import { BaseGrid, IGridPanelView } from './baseComponentGridview';
|
||||||
|
|
||||||
export interface GridviewInitParameters extends PanelInitParameters {
|
export interface GridviewInitParameters extends PanelInitParameters {
|
||||||
minimumWidth?: number;
|
minimumWidth?: number;
|
||||||
@ -24,7 +25,7 @@ export interface GridviewInitParameters extends PanelInitParameters {
|
|||||||
maximumHeight?: number;
|
maximumHeight?: number;
|
||||||
priority?: LayoutPriority;
|
priority?: LayoutPriority;
|
||||||
snap?: boolean;
|
snap?: boolean;
|
||||||
accessor: GridviewComponent;
|
accessor: BaseGrid<IGridPanelView>;
|
||||||
isVisible?: boolean;
|
isVisible?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,14 +158,16 @@ export abstract class GridviewPanel<
|
|||||||
this.api.initialize(this); // TODO: required to by-pass 'super before this' requirement
|
this.api.initialize(this); // TODO: required to by-pass 'super before this' requirement
|
||||||
|
|
||||||
this.addDisposables(
|
this.addDisposables(
|
||||||
this.api.onVisibilityChange((event) => {
|
this.api.onDidHiddenChange((event) => {
|
||||||
const { isVisible } = event;
|
const { isHidden } = event;
|
||||||
const { accessor } = this._params as GridviewInitParameters;
|
const { accessor } = this._params as GridviewInitParameters;
|
||||||
accessor.setVisible(this, isVisible);
|
|
||||||
|
accessor.setVisible(this, !isHidden);
|
||||||
}),
|
}),
|
||||||
this.api.onActiveChange(() => {
|
this.api.onActiveChange(() => {
|
||||||
const { accessor } = this._params as GridviewInitParameters;
|
const { accessor } = this._params as GridviewInitParameters;
|
||||||
accessor.setActive(this);
|
|
||||||
|
accessor.doSetGroupActive(this);
|
||||||
}),
|
}),
|
||||||
this.api.onDidConstraintsChangeInternal((event) => {
|
this.api.onDidConstraintsChangeInternal((event) => {
|
||||||
if (
|
if (
|
||||||
|
@ -17,5 +17,5 @@ export interface GridviewComponentOptions {
|
|||||||
};
|
};
|
||||||
frameworkComponentFactory?: FrameworkFactory<GridviewPanel>;
|
frameworkComponentFactory?: FrameworkFactory<GridviewPanel>;
|
||||||
styles?: ISplitviewStyles;
|
styles?: ISplitviewStyles;
|
||||||
parentElement?: HTMLElement;
|
parentElement: HTMLElement;
|
||||||
}
|
}
|
||||||
|
@ -24,10 +24,10 @@ export namespace Disposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class CompositeDisposable {
|
export class CompositeDisposable {
|
||||||
private readonly _disposables: IDisposable[];
|
private _disposables: IDisposable[];
|
||||||
private _isDisposed = false;
|
private _isDisposed = false;
|
||||||
|
|
||||||
protected get isDisposed(): boolean {
|
get isDisposed(): boolean {
|
||||||
return this._isDisposed;
|
return this._isDisposed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,9 +40,13 @@ export class CompositeDisposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public dispose(): void {
|
public dispose(): void {
|
||||||
this._disposables.forEach((arg) => arg.dispose());
|
if (this._isDisposed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this._isDisposed = true;
|
this._isDisposed = true;
|
||||||
|
this._disposables.forEach((arg) => arg.dispose());
|
||||||
|
this._disposables = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ export class OverlayRenderContainer extends CompositeDisposable {
|
|||||||
toggleClass(
|
toggleClass(
|
||||||
focusContainer,
|
focusContainer,
|
||||||
'dv-render-overlay-float',
|
'dv-render-overlay-float',
|
||||||
panel.group.api.location === 'floating'
|
panel.group.api.location.type === 'floating'
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,5 +25,5 @@ export interface PaneviewComponentOptions {
|
|||||||
};
|
};
|
||||||
disableDnd?: boolean;
|
disableDnd?: boolean;
|
||||||
showDndOverlay?: (event: PaneviewDndOverlayEvent) => boolean;
|
showDndOverlay?: (event: PaneviewDndOverlayEvent) => boolean;
|
||||||
parentElement?: HTMLElement;
|
parentElement: HTMLElement;
|
||||||
}
|
}
|
||||||
|
@ -5,22 +5,31 @@ import { Box } from './types';
|
|||||||
|
|
||||||
export type PopoutWindowOptions = {
|
export type PopoutWindowOptions = {
|
||||||
url: string;
|
url: string;
|
||||||
|
onDidOpen?: (event: { id: string; window: Window }) => void;
|
||||||
|
onWillClose?: (event: { id: string; window: Window }) => void;
|
||||||
} & Box;
|
} & Box;
|
||||||
|
|
||||||
export class PopoutWindow extends CompositeDisposable {
|
export class PopoutWindow extends CompositeDisposable {
|
||||||
|
private readonly _onWillClose = new Emitter<void>();
|
||||||
|
readonly onWillClose = this._onWillClose.event;
|
||||||
|
|
||||||
private readonly _onDidClose = new Emitter<void>();
|
private readonly _onDidClose = new Emitter<void>();
|
||||||
readonly onDidClose = this._onDidClose.event;
|
readonly onDidClose = this._onDidClose.event;
|
||||||
|
|
||||||
private _window: { value: Window; disposable: IDisposable } | null = null;
|
private _window: { value: Window; disposable: IDisposable } | null = null;
|
||||||
|
|
||||||
|
get window(): Window | null {
|
||||||
|
return this._window?.value ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly id: string,
|
private readonly target: string,
|
||||||
private readonly className: string,
|
private readonly className: string,
|
||||||
private readonly options: PopoutWindowOptions
|
private readonly options: PopoutWindowOptions
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.addDisposables(this._onDidClose, {
|
this.addDisposables(this._onWillClose, this._onDidClose, {
|
||||||
dispose: () => {
|
dispose: () => {
|
||||||
this.close();
|
this.close();
|
||||||
},
|
},
|
||||||
@ -42,13 +51,22 @@ export class PopoutWindow extends CompositeDisposable {
|
|||||||
|
|
||||||
close(): void {
|
close(): void {
|
||||||
if (this._window) {
|
if (this._window) {
|
||||||
|
this._onWillClose.fire();
|
||||||
|
|
||||||
|
this.options.onWillClose?.({
|
||||||
|
id: this.target,
|
||||||
|
window: this._window.value,
|
||||||
|
});
|
||||||
|
|
||||||
this._window.disposable.dispose();
|
this._window.disposable.dispose();
|
||||||
this._window.value.close();
|
this._window.value.close();
|
||||||
this._window = null;
|
this._window = null;
|
||||||
|
|
||||||
|
this._onDidClose.fire();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open(content: HTMLElement): void {
|
async open(): Promise<HTMLElement | null> {
|
||||||
if (this._window) {
|
if (this._window) {
|
||||||
throw new Error('instance of popout window is already open');
|
throw new Error('instance of popout window is already open');
|
||||||
}
|
}
|
||||||
@ -64,55 +82,93 @@ export class PopoutWindow extends CompositeDisposable {
|
|||||||
.map(([key, value]) => `${key}=${value}`)
|
.map(([key, value]) => `${key}=${value}`)
|
||||||
.join(',');
|
.join(',');
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/Window/open
|
/**
|
||||||
const externalWindow = window.open(url, this.id, features);
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/Window/open
|
||||||
|
*/
|
||||||
|
const externalWindow = window.open(url, this.target, features);
|
||||||
|
|
||||||
if (!externalWindow) {
|
if (!externalWindow) {
|
||||||
return;
|
/**
|
||||||
|
* Popup blocked
|
||||||
|
*/
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const disposable = new CompositeDisposable();
|
const disposable = new CompositeDisposable();
|
||||||
|
|
||||||
this._window = { value: externalWindow, disposable };
|
this._window = { value: externalWindow, disposable };
|
||||||
|
|
||||||
const cleanUp = () => {
|
|
||||||
this._onDidClose.fire();
|
|
||||||
this._window = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
// prevent any default content from loading
|
|
||||||
// externalWindow.document.body.replaceWith(document.createElement('div'));
|
|
||||||
|
|
||||||
disposable.addDisposables(
|
disposable.addDisposables(
|
||||||
addDisposableWindowListener(window, 'beforeunload', () => {
|
addDisposableWindowListener(window, 'beforeunload', () => {
|
||||||
cleanUp();
|
/**
|
||||||
|
* before the main window closes we should close this popup too
|
||||||
|
* to be good citizens
|
||||||
|
*
|
||||||
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event
|
||||||
|
*/
|
||||||
this.close();
|
this.close();
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
externalWindow.addEventListener('load', () => {
|
const container = this.createPopoutWindowContainer();
|
||||||
const externalDocument = externalWindow.document;
|
|
||||||
externalDocument.title = document.title;
|
|
||||||
|
|
||||||
const div = document.createElement('div');
|
if (this.className) {
|
||||||
div.classList.add('dv-popout-window');
|
container.classList.add(this.className);
|
||||||
div.style.position = 'absolute';
|
}
|
||||||
div.style.width = '100%';
|
|
||||||
div.style.height = '100%';
|
|
||||||
div.style.top = '0px';
|
|
||||||
div.style.left = '0px';
|
|
||||||
div.classList.add(this.className);
|
|
||||||
div.appendChild(content);
|
|
||||||
|
|
||||||
externalDocument.body.replaceChildren(div);
|
this.options.onDidOpen?.({
|
||||||
externalDocument.body.classList.add(this.className);
|
id: this.target,
|
||||||
|
window: externalWindow,
|
||||||
|
});
|
||||||
|
|
||||||
addStyles(externalDocument, window.document.styleSheets);
|
return new Promise<HTMLElement | null>((resolve) => {
|
||||||
|
externalWindow.addEventListener('unload', (e) => {
|
||||||
|
// if page fails to load before unloading
|
||||||
|
// this.close();
|
||||||
|
});
|
||||||
|
|
||||||
externalWindow.addEventListener('beforeunload', () => {
|
externalWindow.addEventListener('load', () => {
|
||||||
// TODO: indicate external window is closing
|
/**
|
||||||
cleanUp();
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event
|
||||||
|
*/
|
||||||
|
|
||||||
|
const externalDocument = externalWindow.document;
|
||||||
|
externalDocument.title = document.title;
|
||||||
|
|
||||||
|
externalDocument.body.appendChild(container);
|
||||||
|
|
||||||
|
addStyles(externalDocument, window.document.styleSheets);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* beforeunload must be registered after load for reasons I could not determine
|
||||||
|
* otherwise the beforeunload event will not fire when the window is closed
|
||||||
|
*/
|
||||||
|
addDisposableWindowListener(
|
||||||
|
externalWindow,
|
||||||
|
'beforeunload',
|
||||||
|
() => {
|
||||||
|
/**
|
||||||
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event
|
||||||
|
*/
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
resolve(container);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private createPopoutWindowContainer(): HTMLElement {
|
||||||
|
const el = document.createElement('div');
|
||||||
|
el.classList.add('dv-popout-window');
|
||||||
|
el.id = 'dv-popout-window';
|
||||||
|
el.style.position = 'absolute';
|
||||||
|
el.style.width = '100%';
|
||||||
|
el.style.height = '100%';
|
||||||
|
el.style.top = '0px';
|
||||||
|
el.style.left = '0px';
|
||||||
|
|
||||||
|
return el;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,19 +17,12 @@ export abstract class Resizable extends CompositeDisposable {
|
|||||||
this._disableResizing = value;
|
this._disableResizing = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(parentElement?: HTMLElement, disableResizing = false) {
|
constructor(parentElement: HTMLElement, disableResizing = false) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this._disableResizing = disableResizing;
|
this._disableResizing = disableResizing;
|
||||||
|
|
||||||
if (parentElement) {
|
this._element = parentElement;
|
||||||
this._element = parentElement;
|
|
||||||
} else {
|
|
||||||
this._element = document.createElement('div');
|
|
||||||
this._element.style.height = '100%';
|
|
||||||
this._element.style.width = '100%';
|
|
||||||
this._element.className = 'dv-resizable-container';
|
|
||||||
}
|
|
||||||
|
|
||||||
this.addDisposables(
|
this.addDisposables(
|
||||||
watchElementResize(this._element, (entry) => {
|
watchElementResize(this._element, (entry) => {
|
||||||
|
@ -28,5 +28,5 @@ export interface SplitviewComponentOptions extends SplitViewOptions {
|
|||||||
[componentName: string]: any;
|
[componentName: string]: any;
|
||||||
};
|
};
|
||||||
frameworkWrapper?: FrameworkFactory<SplitviewPanel>;
|
frameworkWrapper?: FrameworkFactory<SplitviewPanel>;
|
||||||
parentElement?: HTMLElement;
|
parentElement: HTMLElement;
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,12 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
|
&.dv-splitview-disabled {
|
||||||
|
& > .sash-container > .sash {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&.animation {
|
&.animation {
|
||||||
.view,
|
.view,
|
||||||
.sash {
|
.sash {
|
||||||
|
@ -109,6 +109,7 @@ export class Splitview {
|
|||||||
private proportionalLayout: boolean;
|
private proportionalLayout: boolean;
|
||||||
private _startSnappingEnabled = true;
|
private _startSnappingEnabled = true;
|
||||||
private _endSnappingEnabled = true;
|
private _endSnappingEnabled = true;
|
||||||
|
private _disabled = false;
|
||||||
|
|
||||||
private readonly _onDidSashEnd = new Emitter<void>();
|
private readonly _onDidSashEnd = new Emitter<void>();
|
||||||
readonly onDidSashEnd = this._onDidSashEnd.event;
|
readonly onDidSashEnd = this._onDidSashEnd.event;
|
||||||
@ -200,6 +201,16 @@ export class Splitview {
|
|||||||
this.updateSashEnablement();
|
this.updateSashEnablement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get disabled(): boolean {
|
||||||
|
return this._disabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
set disabled(value: boolean) {
|
||||||
|
this._disabled = value;
|
||||||
|
|
||||||
|
toggleClass(this.element, 'dv-splitview-disabled', value);
|
||||||
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly container: HTMLElement,
|
private readonly container: HTMLElement,
|
||||||
options: SplitViewOptions
|
options: SplitViewOptions
|
||||||
|
@ -89,10 +89,10 @@ export abstract class SplitviewPanel
|
|||||||
|
|
||||||
this.addDisposables(
|
this.addDisposables(
|
||||||
this._onDidChange,
|
this._onDidChange,
|
||||||
this.api.onVisibilityChange((event) => {
|
this.api.onDidHiddenChange((event) => {
|
||||||
const { isVisible } = event;
|
const { isHidden } = event;
|
||||||
const { accessor } = this._params as PanelViewInitParameters;
|
const { accessor } = this._params as PanelViewInitParameters;
|
||||||
accessor.setVisible(this, isVisible);
|
accessor.setVisible(this, !isHidden);
|
||||||
}),
|
}),
|
||||||
this.api.onActiveChange(() => {
|
this.api.onActiveChange(() => {
|
||||||
const { accessor } = this._params as PanelViewInitParameters;
|
const { accessor } = this._params as PanelViewInitParameters;
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
@mixin dockview-theme-dark-mixin {
|
@mixin dockview-theme-dark-mixin {
|
||||||
@include dockview-theme-core-mixin();
|
@include dockview-theme-core-mixin();
|
||||||
|
|
||||||
//
|
//
|
||||||
--dv-group-view-background-color: #1e1e1e;
|
--dv-group-view-background-color: #1e1e1e;
|
||||||
//
|
//
|
||||||
@ -228,13 +229,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@mixin dockview-design-replit-mixin {
|
@mixin dockview-design-replit-mixin {
|
||||||
&.dv-dockview {
|
--dv-group-gap-size: 3px;
|
||||||
padding: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.view:has(> .groupview) {
|
|
||||||
padding: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dv-resize-container:has(> .groupview) {
|
.dv-resize-container:has(> .groupview) {
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {
|
import {
|
||||||
DockviewComponent,
|
DockviewComponent,
|
||||||
DockviewDropEvent,
|
DockviewWillDropEvent,
|
||||||
DockviewDndOverlayEvent,
|
DockviewDndOverlayEvent,
|
||||||
GroupPanelFrameworkComponentFactory,
|
GroupPanelFrameworkComponentFactory,
|
||||||
DockviewPanelApi,
|
DockviewPanelApi,
|
||||||
@ -12,6 +12,7 @@ import {
|
|||||||
IHeaderActionsRenderer,
|
IHeaderActionsRenderer,
|
||||||
DockviewPanelRenderer,
|
DockviewPanelRenderer,
|
||||||
DroptargetOverlayModel,
|
DroptargetOverlayModel,
|
||||||
|
DockviewDidDropEvent,
|
||||||
} from 'dockview-core';
|
} from 'dockview-core';
|
||||||
import { ReactPanelContentPart } from './reactContentPart';
|
import { ReactPanelContentPart } from './reactContentPart';
|
||||||
import { ReactPanelHeaderPart } from './reactHeaderPart';
|
import { ReactPanelHeaderPart } from './reactHeaderPart';
|
||||||
@ -61,7 +62,8 @@ export interface IDockviewReactProps {
|
|||||||
components: PanelCollection<IDockviewPanelProps>;
|
components: PanelCollection<IDockviewPanelProps>;
|
||||||
tabComponents?: PanelCollection<IDockviewPanelHeaderProps>;
|
tabComponents?: PanelCollection<IDockviewPanelHeaderProps>;
|
||||||
watermarkComponent?: React.FunctionComponent<IWatermarkPanelProps>;
|
watermarkComponent?: React.FunctionComponent<IWatermarkPanelProps>;
|
||||||
onDidDrop?: (event: DockviewDropEvent) => void;
|
onDidDrop?: (event: DockviewDidDropEvent) => void;
|
||||||
|
onWillDrop?: (event: DockviewWillDropEvent) => void;
|
||||||
showDndOverlay?: (event: DockviewDndOverlayEvent) => boolean;
|
showDndOverlay?: (event: DockviewDndOverlayEvent) => boolean;
|
||||||
hideBorders?: boolean;
|
hideBorders?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
@ -81,6 +83,8 @@ export interface IDockviewReactProps {
|
|||||||
debug?: boolean;
|
debug?: boolean;
|
||||||
defaultRenderer?: DockviewPanelRenderer;
|
defaultRenderer?: DockviewPanelRenderer;
|
||||||
rootOverlayModel?: DroptargetOverlayModel;
|
rootOverlayModel?: DroptargetOverlayModel;
|
||||||
|
locked?: boolean;
|
||||||
|
disableDnd?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_REACT_TAB = 'props.defaultTabComponent';
|
const DEFAULT_REACT_TAB = 'props.defaultTabComponent';
|
||||||
@ -183,6 +187,8 @@ export const DockviewReact = React.forwardRef(
|
|||||||
defaultRenderer: props.defaultRenderer,
|
defaultRenderer: props.defaultRenderer,
|
||||||
debug: props.debug,
|
debug: props.debug,
|
||||||
rootOverlayModel: props.rootOverlayModel,
|
rootOverlayModel: props.rootOverlayModel,
|
||||||
|
locked: props.locked,
|
||||||
|
disableDnd: props.disableDnd,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { clientWidth, clientHeight } = domRef.current;
|
const { clientWidth, clientHeight } = domRef.current;
|
||||||
@ -199,6 +205,24 @@ export const DockviewReact = React.forwardRef(
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (!dockviewRef.current) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dockviewRef.current.locked = !!props.locked;
|
||||||
|
}, [props.locked]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (!dockviewRef.current) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dockviewRef.current.updateOptions({
|
||||||
|
disableDnd: props.disableDnd,
|
||||||
|
});
|
||||||
|
}, [props.disableDnd]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!dockviewRef.current) {
|
if (!dockviewRef.current) {
|
||||||
return () => {
|
return () => {
|
||||||
@ -217,6 +241,24 @@ export const DockviewReact = React.forwardRef(
|
|||||||
};
|
};
|
||||||
}, [props.onDidDrop]);
|
}, [props.onDidDrop]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (!dockviewRef.current) {
|
||||||
|
return () => {
|
||||||
|
// noop
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const disposable = dockviewRef.current.onWillDrop((event) => {
|
||||||
|
if (props.onWillDrop) {
|
||||||
|
props.onWillDrop(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
disposable.dispose();
|
||||||
|
};
|
||||||
|
}, [props.onWillDrop]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!dockviewRef.current) {
|
if (!dockviewRef.current) {
|
||||||
return;
|
return;
|
||||||
|
@ -3,6 +3,7 @@ import {
|
|||||||
GridviewPanel,
|
GridviewPanel,
|
||||||
GridviewInitParameters,
|
GridviewInitParameters,
|
||||||
IFrameworkPart,
|
IFrameworkPart,
|
||||||
|
GridviewComponent,
|
||||||
} from 'dockview-core';
|
} from 'dockview-core';
|
||||||
import { ReactPart, ReactPortalStore } from '../react';
|
import { ReactPart, ReactPortalStore } from '../react';
|
||||||
import { IGridviewPanelProps } from './gridview';
|
import { IGridviewPanelProps } from './gridview';
|
||||||
@ -25,8 +26,10 @@ export class ReactGridPanelView extends GridviewPanel {
|
|||||||
{
|
{
|
||||||
params: this._params?.params ?? {},
|
params: this._params?.params ?? {},
|
||||||
api: this.api,
|
api: this.api,
|
||||||
|
// TODO: fix casting hack
|
||||||
containerApi: new GridviewApi(
|
containerApi: new GridviewApi(
|
||||||
(this._params as GridviewInitParameters).accessor
|
(this._params as GridviewInitParameters)
|
||||||
|
.accessor as GridviewComponent
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
"dockview": "^1.9.2",
|
"dockview": "^1.9.2",
|
||||||
"prism-react-renderer": "^2.3.1",
|
"prism-react-renderer": "^2.3.1",
|
||||||
"react-dnd": "^16.0.1",
|
"react-dnd": "^16.0.1",
|
||||||
|
"react-laag": "^2.0.5",
|
||||||
"recoil": "^0.7.7",
|
"recoil": "^0.7.7",
|
||||||
"source-map-loader": "^4.0.2",
|
"source-map-loader": "^4.0.2",
|
||||||
"uuid": "^9.0.1"
|
"uuid": "^9.0.1"
|
||||||
|
@ -87,7 +87,7 @@ const RightControls = (props: IDockviewHeaderActionsProps) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const [isPopout, setIsPopout] = React.useState<boolean>(
|
const [isPopout, setIsPopout] = React.useState<boolean>(
|
||||||
props.api.location === 'popout'
|
props.api.location.type === 'popout'
|
||||||
);
|
);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
@ -96,7 +96,7 @@ const RightControls = (props: IDockviewHeaderActionsProps) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const disposable2 = props.api.onDidLocationChange(() => {
|
const disposable2 = props.api.onDidLocationChange(() => {
|
||||||
setIsPopout(props.api.location === 'popout');
|
setIsPopout(props.api.location.type === 'popout');
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
@ -255,13 +255,13 @@ const LeftComponent = (props: IDockviewHeaderActionsProps) => {
|
|||||||
|
|
||||||
const RightComponent = (props: IDockviewHeaderActionsProps) => {
|
const RightComponent = (props: IDockviewHeaderActionsProps) => {
|
||||||
const [floating, setFloating] = React.useState<boolean>(
|
const [floating, setFloating] = React.useState<boolean>(
|
||||||
props.api.location === 'floating'
|
props.api.location.type === 'floating'
|
||||||
);
|
);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const disposable = props.group.api.onDidLocationChange(
|
const disposable = props.group.api.onDidLocationChange(
|
||||||
(event) => {
|
(event) => {
|
||||||
setFloating(event.location === 'floating');
|
setFloating(event.location.type === 'floating');
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -9,7 +9,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"dockview": "*",
|
"dockview": "*",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0"
|
"react-dom": "^18.2.0",
|
||||||
|
"react-laag": "^2.0.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react": "^18.0.28",
|
"@types/react": "^18.0.28",
|
||||||
|
@ -5,12 +5,34 @@ import {
|
|||||||
IDockviewHeaderActionsProps,
|
IDockviewHeaderActionsProps,
|
||||||
IDockviewPanelProps,
|
IDockviewPanelProps,
|
||||||
SerializedDockview,
|
SerializedDockview,
|
||||||
|
DockviewPanelApi,
|
||||||
} from 'dockview';
|
} from 'dockview';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Icon } from './utils';
|
import { Icon } from './utils';
|
||||||
|
import { PopoverMenu } from './popover';
|
||||||
|
|
||||||
|
function usePanelWindowObject(api: DockviewPanelApi): Window {
|
||||||
|
const [document, setDocument] = React.useState<Window>(api.getWindow());
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
const disposable = api.onDidLocationChange((event) => {
|
||||||
|
setDocument(api.getWindow());
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
disposable.dispose();
|
||||||
|
};
|
||||||
|
}, [api]);
|
||||||
|
|
||||||
|
return document;
|
||||||
|
}
|
||||||
|
|
||||||
const components = {
|
const components = {
|
||||||
default: (props: IDockviewPanelProps<{ title: string }>) => {
|
default: (props: IDockviewPanelProps<{ title: string }>) => {
|
||||||
|
const _window = usePanelWindowObject(props.api);
|
||||||
|
|
||||||
|
const [reset, setReset] = React.useState<boolean>(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
@ -19,7 +41,19 @@ const components = {
|
|||||||
background: 'var(--dv-group-view-background-color)',
|
background: 'var(--dv-group-view-background-color)',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{props.params.title}
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
console.log(_window);
|
||||||
|
setReset(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
setReset(false);
|
||||||
|
}, 2000);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Print
|
||||||
|
</button>
|
||||||
|
{!reset && <PopoverMenu window={_window} />}
|
||||||
|
{props.api.title}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -31,31 +65,31 @@ function loadDefaultLayout(api: DockviewApi) {
|
|||||||
component: 'default',
|
component: 'default',
|
||||||
});
|
});
|
||||||
|
|
||||||
api.addPanel({
|
// api.addPanel({
|
||||||
id: 'panel_2',
|
// id: 'panel_2',
|
||||||
component: 'default',
|
// component: 'default',
|
||||||
});
|
// });
|
||||||
|
|
||||||
api.addPanel({
|
// api.addPanel({
|
||||||
id: 'panel_3',
|
// id: 'panel_3',
|
||||||
component: 'default',
|
// component: 'default',
|
||||||
});
|
// });
|
||||||
|
|
||||||
api.addPanel({
|
// api.addPanel({
|
||||||
id: 'panel_4',
|
// id: 'panel_4',
|
||||||
component: 'default',
|
// component: 'default',
|
||||||
});
|
// });
|
||||||
|
|
||||||
api.addPanel({
|
// api.addPanel({
|
||||||
id: 'panel_5',
|
// id: 'panel_5',
|
||||||
component: 'default',
|
// component: 'default',
|
||||||
position: { direction: 'right' },
|
// position: { direction: 'right' },
|
||||||
});
|
// });
|
||||||
|
|
||||||
api.addPanel({
|
// api.addPanel({
|
||||||
id: 'panel_6',
|
// id: 'panel_6',
|
||||||
component: 'default',
|
// component: 'default',
|
||||||
});
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
let panelCount = 0;
|
let panelCount = 0;
|
||||||
@ -205,12 +239,12 @@ const LeftComponent = (props: IDockviewHeaderActionsProps) => {
|
|||||||
|
|
||||||
const RightComponent = (props: IDockviewHeaderActionsProps) => {
|
const RightComponent = (props: IDockviewHeaderActionsProps) => {
|
||||||
const [popout, setPopout] = React.useState<boolean>(
|
const [popout, setPopout] = React.useState<boolean>(
|
||||||
props.api.location === 'popout'
|
props.api.location.type === 'popout'
|
||||||
);
|
);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const disposable = props.group.api.onDidLocationChange((event) => [
|
const disposable = props.group.api.onDidLocationChange((event) => [
|
||||||
setPopout(event.location === 'popout'),
|
setPopout(event.location.type === 'popout'),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
@ -223,7 +257,7 @@ const RightComponent = (props: IDockviewHeaderActionsProps) => {
|
|||||||
const group = props.containerApi.addGroup();
|
const group = props.containerApi.addGroup();
|
||||||
props.group.api.moveTo({ group });
|
props.group.api.moveTo({ group });
|
||||||
} else {
|
} else {
|
||||||
props.containerApi.addPopoutGroup(props.group, {
|
const window = props.containerApi.addPopoutGroup(props.group, {
|
||||||
popoutUrl: '/popout/index.html',
|
popoutUrl: '/popout/index.html',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
55
packages/docs/sandboxes/popoutgroup-dockview/src/popover.tsx
Normal file
55
packages/docs/sandboxes/popoutgroup-dockview/src/popover.tsx
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import { useLayer, Arrow } from 'react-laag';
|
||||||
|
import { motion, AnimatePresence } from 'framer-motion';
|
||||||
|
import * as React from 'react';
|
||||||
|
import { DockviewPanelApi } from 'dockview';
|
||||||
|
|
||||||
|
export function PopoverMenu(props: { window: Window }) {
|
||||||
|
const [isOpen, setOpen] = React.useState(false);
|
||||||
|
|
||||||
|
// helper function to close the menu
|
||||||
|
function close() {
|
||||||
|
setOpen(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { renderLayer, triggerProps, layerProps, arrowProps } = useLayer({
|
||||||
|
isOpen,
|
||||||
|
onOutsideClick: close, // close the menu when the user clicks outside
|
||||||
|
onDisappear: close, // close the menu when the menu gets scrolled out of sight
|
||||||
|
overflowContainer: false, // keep the menu positioned inside the container
|
||||||
|
auto: true, // automatically find the best placement
|
||||||
|
placement: 'top-end', // we prefer to place the menu "top-end"
|
||||||
|
triggerOffset: 12, // keep some distance to the trigger
|
||||||
|
containerOffset: 16, // give the menu some room to breath relative to the container
|
||||||
|
arrowOffset: 16, // let the arrow have some room to breath also,
|
||||||
|
environment: props.window,
|
||||||
|
container: props.window
|
||||||
|
? () => {
|
||||||
|
const el = props.window.document.body;
|
||||||
|
Object.setPrototypeOf(el, HTMLElement.prototype);
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Again, we're using framer-motion for the transition effect
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<button {...triggerProps} onClick={() => setOpen(!isOpen)}>
|
||||||
|
{isOpen ? 'Hide' : 'Show'}
|
||||||
|
</button>
|
||||||
|
{renderLayer(
|
||||||
|
<AnimatePresence>
|
||||||
|
{isOpen && (
|
||||||
|
<motion.ul {...layerProps}>
|
||||||
|
<li>Item 1</li>
|
||||||
|
<li>Item 2</li>
|
||||||
|
<li>Item 3</li>
|
||||||
|
<li>Item 4</li>
|
||||||
|
<Arrow {...arrowProps} />
|
||||||
|
</motion.ul>
|
||||||
|
)}
|
||||||
|
</AnimatePresence>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@ -93,7 +93,7 @@ export const App: React.FC = (props: { theme?: string }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const Container = () => {
|
const Container = (props: any) => {
|
||||||
const [value, setValue] = React.useState<string>('50');
|
const [value, setValue] = React.useState<string>('50');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -108,7 +108,7 @@ const Container = () => {
|
|||||||
value={value}
|
value={value}
|
||||||
/>
|
/>
|
||||||
<div style={{ height: `${value}%`, width: `${value}%` }}>
|
<div style={{ height: `${value}%`, width: `${value}%` }}>
|
||||||
<App />
|
<App {...props} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -13882,6 +13882,13 @@ react-json-view-lite@^1.2.0:
|
|||||||
resolved "https://registry.yarnpkg.com/react-json-view-lite/-/react-json-view-lite-1.2.1.tgz#c59a0bea4ede394db331d482ee02e293d38f8218"
|
resolved "https://registry.yarnpkg.com/react-json-view-lite/-/react-json-view-lite-1.2.1.tgz#c59a0bea4ede394db331d482ee02e293d38f8218"
|
||||||
integrity sha512-Itc0g86fytOmKZoIoJyGgvNqohWSbh3NXIKNgH6W6FT9PC1ck4xas1tT3Rr/b3UlFXyA9Jjaw9QSXdZy2JwGMQ==
|
integrity sha512-Itc0g86fytOmKZoIoJyGgvNqohWSbh3NXIKNgH6W6FT9PC1ck4xas1tT3Rr/b3UlFXyA9Jjaw9QSXdZy2JwGMQ==
|
||||||
|
|
||||||
|
react-laag@^2.0.5:
|
||||||
|
version "2.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-laag/-/react-laag-2.0.5.tgz#549f1035b761b9ba09ac98fd128ccad63464c877"
|
||||||
|
integrity sha512-RCvublJhdcgGRHU1wMYJ8kRtnYsKUgYusLvVhMuftg65POnnOB4+fwXvnETm6adc0cMnc1spujlrK6bGIz6aug==
|
||||||
|
dependencies:
|
||||||
|
tiny-warning "^1.0.3"
|
||||||
|
|
||||||
react-loadable-ssr-addon-v5-slorber@^1.0.1:
|
react-loadable-ssr-addon-v5-slorber@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz#2cdc91e8a744ffdf9e3556caabeb6e4278689883"
|
resolved "https://registry.yarnpkg.com/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz#2cdc91e8a744ffdf9e3556caabeb6e4278689883"
|
||||||
@ -15678,7 +15685,7 @@ tiny-invariant@^1.0.2:
|
|||||||
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642"
|
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642"
|
||||||
integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==
|
integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==
|
||||||
|
|
||||||
tiny-warning@^1.0.0:
|
tiny-warning@^1.0.0, tiny-warning@^1.0.3:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
|
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
|
||||||
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
|
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
|
||||||
|
Loading…
Reference in New Issue
Block a user