feat: improve layout events

This commit is contained in:
mathuo 2021-10-25 21:21:48 +01:00
parent dd81a1bbad
commit ecbf0f7fc7
No known key found for this signature in database
GPG Key ID: C6EEDEFD6CA07281
17 changed files with 480 additions and 344 deletions

View File

@ -5,13 +5,13 @@
"requires": true,
"packages": {
"": {
"name": "dockview-demo",
"version": "0.0.23",
"version": "0.0.25",
"license": "MIT",
"dependencies": {
"dockview": "^0.0.23",
"dockview": "^0.0.25",
"react": "^17.0.1",
"react-dom": "^17.0.1"
"react-dom": "^17.0.1",
"recoil": "^0.4.1"
},
"devDependencies": {
"@babel/core": "^7.13.10",
@ -9340,9 +9340,9 @@
}
},
"node_modules/dockview": {
"version": "0.0.23",
"resolved": "https://registry.npmjs.org/dockview/-/dockview-0.0.23.tgz",
"integrity": "sha512-thuhpBS/loWdlDcF1B3I/+rg49I6phbEldyozx7H09/59++/r/caWIojxjkBh6vQA09dm9+tzUk4jXAcQmduFQ==",
"version": "0.0.25",
"resolved": "https://registry.npmjs.org/dockview/-/dockview-0.0.25.tgz",
"integrity": "sha512-XRUIh4OT33sTKVdAzZsh6JTyha6OeI/6Ew2eOrrp+I3UzSfruj3yf2nwrJA2iGlVmndBCc7amAV74zhco17H+g==",
"peerDependencies": {
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
@ -11374,6 +11374,11 @@
"node": ">=6"
}
},
"node_modules/hamt_plus": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/hamt_plus/-/hamt_plus-1.0.2.tgz",
"integrity": "sha1-4hwlKWjH4zsg9qGwlM2FeHomVgE="
},
"node_modules/has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
@ -15895,6 +15900,25 @@
"node": ">=8.10.0"
}
},
"node_modules/recoil": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/recoil/-/recoil-0.4.1.tgz",
"integrity": "sha512-vp6KPwlHOjJ4bJofmdDchmgI9ilMTCoUisK8/WYLl8dThH7e7KmtZttiLgvDb2Em99dUfTEsk8vT8L1nUMgqXQ==",
"dependencies": {
"hamt_plus": "1.0.2"
},
"peerDependencies": {
"react": ">=16.13.1"
},
"peerDependenciesMeta": {
"react-dom": {
"optional": true
},
"react-native": {
"optional": true
}
}
},
"node_modules/recursive-readdir": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz",
@ -27250,9 +27274,9 @@
}
},
"dockview": {
"version": "0.0.23",
"resolved": "https://registry.npmjs.org/dockview/-/dockview-0.0.23.tgz",
"integrity": "sha512-thuhpBS/loWdlDcF1B3I/+rg49I6phbEldyozx7H09/59++/r/caWIojxjkBh6vQA09dm9+tzUk4jXAcQmduFQ==",
"version": "0.0.25",
"resolved": "https://registry.npmjs.org/dockview/-/dockview-0.0.25.tgz",
"integrity": "sha512-XRUIh4OT33sTKVdAzZsh6JTyha6OeI/6Ew2eOrrp+I3UzSfruj3yf2nwrJA2iGlVmndBCc7amAV74zhco17H+g==",
"requires": {}
},
"doctrine": {
@ -28898,6 +28922,11 @@
"pify": "^4.0.1"
}
},
"hamt_plus": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/hamt_plus/-/hamt_plus-1.0.2.tgz",
"integrity": "sha1-4hwlKWjH4zsg9qGwlM2FeHomVgE="
},
"has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
@ -32357,6 +32386,14 @@
"picomatch": "^2.2.1"
}
},
"recoil": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/recoil/-/recoil-0.4.1.tgz",
"integrity": "sha512-vp6KPwlHOjJ4bJofmdDchmgI9ilMTCoUisK8/WYLl8dThH7e7KmtZttiLgvDb2Em99dUfTEsk8vT8L1nUMgqXQ==",
"requires": {
"hamt_plus": "1.0.2"
}
},
"recursive-readdir": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz",

View File

@ -16,7 +16,8 @@
"dependencies": {
"dockview": "^0.0.25",
"react": "^17.0.1",
"react-dom": "^17.0.1"
"react-dom": "^17.0.1",
"recoil": "^0.4.1"
},
"devDependencies": {
"@babel/core": "^7.13.10",

View File

@ -1,8 +1,14 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import './index.scss';
import { Application } from './layout-grid/application';
import { RecoilRoot } from 'recoil';
import './index.scss';
document.getElementById('app').classList.add('dockview-theme-dark');
ReactDOM.render(<Application />, document.getElementById('app'));
ReactDOM.render(
<RecoilRoot>
<Application />
</RecoilRoot>,
document.getElementById('app')
);

View File

@ -50,13 +50,19 @@ export const Application = () => {
// event.api.fromJSON(require('./application.layout.json'));
let success = false;
const state = localStorage.getItem('dockview-layout');
if (state) {
console.log('loading from save');
const jsonstate = JSON.parse(state) as SerializedGridview;
event.api.fromJSON(jsonstate);
} else {
try {
event.api.fromJSON(JSON.parse(state));
success = true;
} catch (err) {
console.error('failed to load layout', err);
}
}
if (!success) {
event.api.addPanel({
id: 'i',
component: 'activitybar',
@ -110,7 +116,6 @@ export const Application = () => {
return (
<GridviewReact
// className={'visual-studio-theme'}
components={rootcomponents}
onReady={onReady}
orientation={Orientation.VERTICAL}

View File

@ -8,21 +8,6 @@ export const ControlCenter = () => {
const dragRef = React.useRef<HTMLDivElement>();
// React.useEffect(() => {
// const api = registry.get<DockviewApi>('dockview');
// const target = api.createDragTarget(
// { element: dragRef.current, content: 'drag me' },
// () => ({
// id: 'yellow',
// component: 'test_component',
// })
// );
// return () => {
// target.dispose();
// };
// }, []);
const onDragStart = (event: React.DragEvent) => {
event.dataTransfer.setData('text/plain', 'Panel2');
};

View File

@ -1,13 +1,27 @@
import * as React from 'react';
import { IGridviewPanelProps } from 'dockview';
import { atom, useRecoilValue } from 'recoil';
export const selectedPanelAtom = atom<string>({
key: 'selectedPanelAtom',
default: '',
});
export const Footer = (props: IGridviewPanelProps) => {
const selectedPanel = useRecoilValue(selectedPanelAtom);
return (
<div
style={{
height: '22px',
backgroundColor: 'dodgerblue',
display: 'flex',
alignItems: 'center',
padding: '0px 8px',
}}
></div>
>
<span style={{ flexGrow: 1 }} />
<span>{selectedPanel}</span>
</div>
);
};

View File

@ -22,6 +22,8 @@ import './layoutGrid.scss';
import { WelcomePanel } from '../panels/welcome/welcome';
import { SplitviewPanel } from '../panels/splitview/splitview';
import { GridviewDemoPanel } from '../panels/gridview/gridview';
import { useRecoilCallback } from 'recoil';
import { selectedPanelAtom } from './footer';
const Test = (props: IDockviewPanelProps) => {
const [counter, setCounter] = React.useState<number>(0);
@ -102,23 +104,6 @@ const components: PanelCollection<IDockviewPanelProps> = {
}
};
React.useEffect(() => {
const compDis = new CompositeDisposable(
props.api.onDidDimensionsChange((event) => {
// _api.current?.layout(event.width, event.height);
}),
_api.current.onGridEvent((event) => {
if (event.kind === GroupChangeKind.LAYOUT_CONFIG_UPDATED) {
props.api.setState('layout', _api.current.toJSON());
}
})
);
return () => {
compDis.dispose();
};
}, []);
return (
<div
style={{
@ -296,101 +281,66 @@ export const nextGuid = (() => {
})();
export const TestGrid = (props: IGridviewPanelProps) => {
const _api = React.useRef<DockviewApi>();
const [api, setApi] = React.useState<DockviewApi>();
const registry = useLayoutRegistry();
const onReady = (event: DockviewReadyEvent) => {
const api = event.api;
_api.current = event.api;
setApi(api);
registry.register('dockview', api);
};
// api.addDndHandle('text/plain', (ev) => {
// const { event } = ev;
const setSelectedPanel = useRecoilCallback(
({ set }) => (value: string) => set(selectedPanelAtom, value),
[]
);
// return {
// id: 'yellow',
// component: 'test_component',
// };
// });
React.useEffect(() => {
if (!api) {
return () => {
//
};
}
props.api.setConstraints({
minimumWidth: () => api.minimumWidth,
minimumHeight: () => api.minimumHeight,
});
// api.addDndHandle('Files', (ev) => {
// const { event } = ev;
// ev.event.event.preventDefault();
// return {
// id: Date.now().toString(),
// title: event.event.dataTransfer.files[0].name,
// component: 'test_component',
// };
// });
const disposable = new CompositeDisposable(
api.onDidLayoutChange(() => {
const state = api.toJSON();
localStorage.setItem('dockview', JSON.stringify(state));
}),
api.onGridEvent((e) => {
console.log(e);
if (e.kind === GroupChangeKind.PANEL_ACTIVE) {
setSelectedPanel(e.panel?.id || '');
}
})
);
const state = localStorage.getItem('dockview');
let success = false;
if (state) {
api.fromJSON(JSON.parse(state));
} else {
try {
api.fromJSON(JSON.parse(state));
success = true;
} catch (err) {
console.error('failed to load layout', err);
}
}
if (!success) {
api.addPanel({
component: 'welcome',
id: 'welcome',
title: 'Welcome',
});
// event.api.deserialize(require('./layoutGrid.layout.json'));
return;
api.addPanel({
component: 'test_component',
id: nextGuid(),
title: 'Item 1',
params: { text: 'how low?' },
});
api.addPanel({
component: 'test_component',
id: 'item2',
title: 'Item 2',
});
api.addPanel({
component: 'split_panel',
id: nextGuid(),
title: 'Item 3 with a long title',
});
api.addPanel({
component: 'test_component',
id: nextGuid(),
title: 'Item 3',
position: { direction: 'below', referencePanel: 'item2' },
suppressClosable: true,
});
}
// api.addPanel({
// component: 'test',
// id: 'test',
// title: 'Test',
// });
};
React.useEffect(() => {
props.api.setConstraints({
minimumWidth: () => _api.current.minimumWidth,
minimumHeight: () => _api.current.minimumHeight,
});
const disposable = new CompositeDisposable(
_api.current.onDidLayoutChange(() => {
const state = _api.current.toJSON();
localStorage.setItem('dockview', JSON.stringify(state));
}),
props.api.onDidDimensionsChange((event) => {
const { width, height } = event;
// _api.current.layout(width, height);
})
);
return () => {
disposable.dispose();
};
}, []);
}, [api]);
const [coord, setCoord] = React.useState<{
x: number;

View File

@ -1,5 +1,4 @@
import { DockviewComponent } from '../../dockview/dockviewComponent';
import {
GroupPanelPartInitParameters,
IContentRenderer,
@ -9,7 +8,10 @@ import { Orientation } from '../../splitview/core/splitview';
import { ReactPanelDeserialzier } from '../../react/deserializer';
import { Position } from '../../dnd/droptarget';
import { GroupviewPanel } from '../../groupview/groupviewPanel';
import { IGroupPanel } from '../../groupview/groupPanel';
import {
GroupChangeEvent,
GroupChangeKind,
} from '../../gridview/baseComponentGridview';
class PanelContentPartTest implements IContentRenderer {
element: HTMLElement = document.createElement('div');
@ -618,4 +620,111 @@ describe('dockviewComponent', () => {
disposable.dispose();
});
test('events flow', () => {
dockview.layout(1000, 1000);
let events: GroupChangeEvent[] = [];
const disposable = dockview.onGridEvent((e) => events.push(e));
const panel1 = dockview.addPanel({
id: 'panel1',
component: 'default',
});
expect(events).toEqual([
{ kind: GroupChangeKind.ADD_GROUP },
{ kind: GroupChangeKind.GROUP_ACTIVE },
{ kind: GroupChangeKind.ADD_PANEL, panel: panel1 },
{ kind: GroupChangeKind.PANEL_ACTIVE, panel: panel1 },
]);
events = [];
const panel2 = dockview.addPanel({
id: 'panel2',
component: 'default',
});
expect(events).toEqual([
{ kind: GroupChangeKind.ADD_PANEL, panel: panel2 },
{ kind: GroupChangeKind.PANEL_ACTIVE, panel: panel2 },
]);
events = [];
const panel3 = dockview.addPanel({
id: 'panel3',
component: 'default',
});
expect(events).toEqual([
{ kind: GroupChangeKind.ADD_PANEL, panel: panel3 },
{ kind: GroupChangeKind.PANEL_ACTIVE, panel: panel3 },
]);
events = [];
dockview.removePanel(panel1);
expect(events).toEqual([
{ kind: GroupChangeKind.REMOVE_PANEL, panel: panel1 },
]);
events = [];
dockview.removePanel(panel3);
expect(events).toEqual([
{ kind: GroupChangeKind.REMOVE_PANEL, panel: panel3 },
{ kind: GroupChangeKind.PANEL_ACTIVE, panel: panel2 },
]);
events = [];
const panel4 = dockview.addPanel({
id: 'panel4',
component: 'default',
position: { referencePanel: panel2.id, direction: 'right' },
});
expect(events).toEqual([
{ kind: GroupChangeKind.ADD_GROUP },
{ kind: GroupChangeKind.GROUP_ACTIVE },
{ kind: GroupChangeKind.ADD_PANEL, panel: panel4 },
{ kind: GroupChangeKind.PANEL_ACTIVE, panel: panel4 },
]);
events = [];
const panel5 = dockview.addPanel({
id: 'panel5',
component: 'default',
position: { referencePanel: panel4.id, direction: 'within' },
});
expect(events).toEqual([
{ kind: GroupChangeKind.ADD_PANEL, panel: panel5 },
{ kind: GroupChangeKind.PANEL_ACTIVE, panel: panel5 },
]);
events = [];
dockview.moveGroupOrPanel(
panel2.group!,
panel5.group!.id,
panel5.id,
Position.Center
);
expect(events).toEqual([
{ kind: GroupChangeKind.REMOVE_PANEL, panel: panel5 },
{ kind: GroupChangeKind.PANEL_ACTIVE, panel: panel4 },
{ kind: GroupChangeKind.ADD_PANEL, panel: panel5 },
{ kind: GroupChangeKind.PANEL_ACTIVE, panel: panel5 },
{ kind: GroupChangeKind.GROUP_ACTIVE },
{ kind: GroupChangeKind.PANEL_ACTIVE, panel: panel5 },
]);
events = [];
dockview.moveGroupOrPanel(
panel2.group!,
panel4.group!.id,
panel4.id,
Position.Center
);
expect(events).toEqual([
{ kind: GroupChangeKind.REMOVE_PANEL, panel: panel4 },
{ kind: GroupChangeKind.REMOVE_GROUP },
{ kind: GroupChangeKind.ADD_PANEL, panel: panel4 },
{ kind: GroupChangeKind.PANEL_ACTIVE, panel: panel4 },
]);
disposable.dispose();
});
});

View File

@ -1,6 +1,9 @@
import {
GroupChangeEvent,
GroupChangeKind,
} from '../../gridview/baseComponentGridview';
import { GridviewComponent } from '../../gridview/gridviewComponent';
import { GridviewPanel } from '../../gridview/gridviewPanel';
import { GroupChangeEvent, GroupChangeKind } from '../../groupview/groupview';
import { IFrameworkPart } from '../../panel/types';
import { Orientation } from '../../splitview/core/splitview';

View File

@ -13,7 +13,7 @@ import {
} from '../../groupview/types';
import { PanelUpdateEvent } from '../../panel/types';
import { GroupviewPanel } from '../../groupview/groupviewPanel';
import { GroupChangeKind, GroupOptions } from '../../groupview/groupview';
import { GroupChangeKind2, GroupOptions } from '../../groupview/groupview';
import { DockviewPanelApi } from '../../api/groupPanelApi';
import {
DefaultGroupPanelView,
@ -259,7 +259,7 @@ describe('groupview', () => {
});
const events: Array<{
kind: GroupChangeKind;
kind: GroupChangeKind2;
}> = [];
const disposable = groupview2.model.onDidGroupChange((e) => {
events.push(e);
@ -269,19 +269,19 @@ describe('groupview', () => {
expect(events).toEqual([
{
kind: GroupChangeKind.ADD_PANEL,
kind: GroupChangeKind2.ADD_PANEL,
panel: panel1,
},
{
kind: GroupChangeKind.ADD_PANEL,
kind: GroupChangeKind2.ADD_PANEL,
panel: panel2,
},
{
kind: GroupChangeKind.ADD_PANEL,
kind: GroupChangeKind2.ADD_PANEL,
panel: panel3,
},
{
kind: GroupChangeKind.PANEL_ACTIVE,
kind: GroupChangeKind2.PANEL_ACTIVE,
panel: panel2,
},
]);
@ -291,7 +291,7 @@ describe('groupview', () => {
test('panel events flow', () => {
let events: Array<{
kind: GroupChangeKind;
kind: GroupChangeKind2;
}> = [];
const disposable = groupview.model.onDidGroupChange((e) => {
events.push(e);
@ -306,11 +306,11 @@ describe('groupview', () => {
groupview.model.openPanel(panel1);
expect(events).toEqual([
{
kind: GroupChangeKind.ADD_PANEL,
kind: GroupChangeKind2.ADD_PANEL,
panel: panel1,
},
{
kind: GroupChangeKind.PANEL_ACTIVE,
kind: GroupChangeKind2.PANEL_ACTIVE,
panel: panel1,
},
]);
@ -319,11 +319,11 @@ describe('groupview', () => {
groupview.model.openPanel(panel2);
expect(events).toEqual([
{
kind: GroupChangeKind.ADD_PANEL,
kind: GroupChangeKind2.ADD_PANEL,
panel: panel2,
},
{
kind: GroupChangeKind.PANEL_ACTIVE,
kind: GroupChangeKind2.PANEL_ACTIVE,
panel: panel2,
},
]);
@ -332,11 +332,11 @@ describe('groupview', () => {
groupview.model.openPanel(panel3);
expect(events).toEqual([
{
kind: GroupChangeKind.ADD_PANEL,
kind: GroupChangeKind2.ADD_PANEL,
panel: panel3,
},
{
kind: GroupChangeKind.PANEL_ACTIVE,
kind: GroupChangeKind2.PANEL_ACTIVE,
panel: panel3,
},
]);
@ -345,11 +345,11 @@ describe('groupview', () => {
groupview.model.removePanel(panel3);
expect(events).toEqual([
{
kind: GroupChangeKind.REMOVE_PANEL,
kind: GroupChangeKind2.REMOVE_PANEL,
panel: panel3,
},
{
kind: GroupChangeKind.PANEL_ACTIVE,
kind: GroupChangeKind2.PANEL_ACTIVE,
panel: panel2,
},
]);
@ -358,7 +358,7 @@ describe('groupview', () => {
groupview.model.removePanel(panel1);
expect(events).toEqual([
{
kind: GroupChangeKind.REMOVE_PANEL,
kind: GroupChangeKind2.REMOVE_PANEL,
panel: panel1,
},
]);
@ -367,12 +367,9 @@ describe('groupview', () => {
groupview.model.removePanel(panel2);
expect(events).toEqual([
{
kind: GroupChangeKind.REMOVE_PANEL,
kind: GroupChangeKind2.REMOVE_PANEL,
panel: panel2,
},
{
kind: GroupChangeKind.PANEL_ACTIVE,
},
]);
events = [];

View File

@ -7,7 +7,7 @@ import {
AddPanelOptions,
MovementOptions,
} from '../dockview/options';
import { Direction } from '../gridview/baseComponentGridview';
import { Direction, GroupChangeEvent } from '../gridview/baseComponentGridview';
import {
AddComponentOptions,
IGridviewComponent,
@ -31,6 +31,8 @@ import { Orientation, Sizing } from '../splitview/core/splitview';
import { ISplitviewPanel } from '../splitview/splitviewPanel';
import { GroupviewPanel } from '../groupview/groupviewPanel';
import { Event } from '../events';
import { GridviewPanel } from '../gridview/gridviewPanel';
import { IDisposable } from '../lifecycle';
export interface CommonApi {
readonly height: number;
@ -42,27 +44,27 @@ export interface CommonApi {
}
export class SplitviewApi implements CommonApi {
get minimumSize() {
get minimumSize(): number {
return this.component.minimumSize;
}
get maximumSize() {
get maximumSize(): number {
return this.component.maximumSize;
}
get height() {
get height(): number {
return this.component.height;
}
get width() {
get width(): number {
return this.component.width;
}
get length() {
get length(): number {
return this.component.length;
}
get onDidLayoutChange() {
get onDidLayoutChange(): Event<void> {
return this.component.onDidLayoutChange;
}
@ -76,73 +78,73 @@ export class SplitviewApi implements CommonApi {
this.component.updateOptions(options);
}
removePanel(panel: ISplitviewPanel, sizing?: Sizing) {
removePanel(panel: ISplitviewPanel, sizing?: Sizing): void {
this.component.removePanel(panel, sizing);
}
setVisible(panel: ISplitviewPanel, isVisible: boolean) {
return this.component.setVisible(panel, isVisible);
setVisible(panel: ISplitviewPanel, isVisible: boolean): void {
this.component.setVisible(panel, isVisible);
}
getPanels(): ISplitviewPanel[] {
return this.component.getPanels();
}
focus() {
return this.component.focus();
focus(): void {
this.component.focus();
}
getPanel(id: string) {
getPanel(id: string): ISplitviewPanel | undefined {
return this.component.getPanel(id);
}
setActive(panel: ISplitviewPanel) {
return this.component.setActive(panel);
setActive(panel: ISplitviewPanel): void {
this.component.setActive(panel);
}
layout(width: number, height: number) {
layout(width: number, height: number): void {
return this.component.layout(width, height);
}
addPanel(options: AddSplitviewComponentOptions) {
return this.component.addPanel(options);
addPanel(options: AddSplitviewComponentOptions): void {
this.component.addPanel(options);
}
resizeToFit() {
return this.component.resizeToFit();
resizeToFit(): void {
this.component.resizeToFit();
}
movePanel(from: number, to: number) {
movePanel(from: number, to: number): void {
this.component.movePanel(from, to);
}
fromJSON(data: SerializedSplitview, deferComponentLayout?: boolean) {
return this.component.fromJSON(data, deferComponentLayout);
fromJSON(data: SerializedSplitview, deferComponentLayout?: boolean): void {
this.component.fromJSON(data, deferComponentLayout);
}
toJSON() {
toJSON(): SerializedSplitview {
return this.component.toJSON();
}
}
export class PaneviewApi implements CommonApi {
get width() {
get width(): number {
return this.component.width;
}
get height() {
get height(): number {
return this.component.height;
}
get minimumSize() {
get minimumSize(): number {
return this.component.minimumSize;
}
get maximumSize() {
get maximumSize(): number {
return this.component.maximumSize;
}
get onDidLayoutChange() {
get onDidLayoutChange(): Event<void> {
return this.component.onDidLayoutChange;
}
@ -160,75 +162,73 @@ export class PaneviewApi implements CommonApi {
return this.component.getPanel(id);
}
movePanel(from: number, to: number) {
movePanel(from: number, to: number): void {
this.component.movePanel(from, to);
}
focus() {
return this.component.focus();
focus(): void {
this.component.focus();
}
layout(width: number, height: number) {
return this.component.layout(width, height);
layout(width: number, height: number): void {
this.component.layout(width, height);
}
addPanel(options: AddPaneviewCompponentOptions) {
addPanel(options: AddPaneviewCompponentOptions): IDisposable {
return this.component.addPanel(options);
}
resizeToFit() {
return this.component.resizeToFit();
resizeToFit(): void {
this.component.resizeToFit();
}
fromJSON(data: SerializedPaneview, deferComponentLayout?: boolean) {
return this.component.fromJSON(data, deferComponentLayout);
fromJSON(data: SerializedPaneview, deferComponentLayout?: boolean): void {
this.component.fromJSON(data, deferComponentLayout);
}
toJSON() {
toJSON(): SerializedPaneview {
return this.component.toJSON();
}
}
export class GridviewApi implements CommonApi {
get width() {
get width(): number {
return this.component.width;
}
get height() {
get height(): number {
return this.component.height;
}
get minimumHeight() {
get minimumHeight(): number {
return this.component.minimumHeight;
}
get maximumHeight() {
get maximumHeight(): number {
return this.component.maximumHeight;
}
get minimumWidth() {
get minimumWidth(): number {
return this.component.minimumWidth;
}
get maximumWidth() {
get maximumWidth(): number {
return this.component.maximumWidth;
}
get onGridEvent() {
get onGridEvent(): Event<GroupChangeEvent> {
return this.component.onGridEvent;
}
get onDidLayoutChange() {
get onDidLayoutChange(): Event<void> {
return this.component.onDidLayoutChange;
}
get panels() {
get panels(): GridviewPanel[] {
return this.component.groups;
}
constructor(private readonly component: IGridviewComponent) {}
get orientation() {
get orientation(): Orientation {
return this.component.orientation;
}
@ -236,16 +236,18 @@ export class GridviewApi implements CommonApi {
this.component.updateOptions({ orientation: value });
}
focus() {
return this.component.focus();
constructor(private readonly component: IGridviewComponent) {}
focus(): void {
this.component.focus();
}
layout(width: number, height: number, force = false) {
return this.component.layout(width, height, force);
layout(width: number, height: number, force = false): void {
this.component.layout(width, height, force);
}
addPanel(options: AddComponentOptions) {
return this.component.addPanel(options);
addPanel(options: AddComponentOptions): void {
this.component.addPanel(options);
}
removePanel(panel: IGridviewPanel, sizing?: Sizing): void {
@ -255,169 +257,163 @@ export class GridviewApi implements CommonApi {
movePanel(
panel: IGridviewPanel,
options: { direction: Direction; reference: string; size?: number }
) {
): void {
this.component.movePanel(panel, options);
}
resizeToFit() {
return this.component.resizeToFit();
resizeToFit(): void {
this.component.resizeToFit();
}
getPanel(id: string) {
getPanel(id: string): GridviewPanel | undefined {
return this.component.getPanel(id);
}
toggleVisibility(panel: IGridviewPanel) {
return this.component.toggleVisibility(panel);
toggleVisibility(panel: IGridviewPanel): void {
this.component.toggleVisibility(panel);
}
// isVisible(panel: IGridviewPanel) {
// return this.component.isVisible(panel);
// }
setVisible(panel: IGridviewPanel, visible: boolean) {
return this.component.setVisible(panel, visible);
setVisible(panel: IGridviewPanel, visible: boolean): void {
this.component.setVisible(panel, visible);
}
setActive(panel: IGridviewPanel): void {
this.component.setActive(panel);
}
fromJSON(data: SerializedGridview, deferComponentLayout?: boolean) {
fromJSON(data: SerializedGridview, deferComponentLayout?: boolean): void {
return this.component.fromJSON(data, deferComponentLayout);
}
toJSON() {
toJSON(): SerializedGridview {
return this.component.toJSON();
}
}
export class DockviewApi implements CommonApi {
get width() {
get width(): number {
return this.component.width;
}
get height() {
get height(): number {
return this.component.height;
}
get minimumHeight() {
get minimumHeight(): number {
return this.component.minimumHeight;
}
get maximumHeight() {
get maximumHeight(): number {
return this.component.maximumHeight;
}
get minimumWidth() {
get minimumWidth(): number {
return this.component.minimumWidth;
}
get maximumWidth() {
get maximumWidth(): number {
return this.component.maximumWidth;
}
get size() {
get size(): number {
return this.component.size;
}
get totalPanels() {
get totalPanels(): number {
return this.component.totalPanels;
}
get onGridEvent() {
get onGridEvent(): Event<GroupChangeEvent> {
return this.component.onGridEvent;
}
get onDidLayoutChange() {
get onDidLayoutChange(): Event<void> {
return this.component.onDidLayoutChange;
}
get panels() {
get panels(): IGroupPanel[] {
return this.component.panels;
}
get groups() {
get groups(): GroupviewPanel[] {
return this.component.groups;
}
get activePanel(): IGroupPanel | undefined {
return this.component.activePanel;
}
get activeGroup(): GroupviewPanel | undefined {
return this.component.activeGroup;
}
constructor(private readonly component: IDockviewComponent) {}
focus() {
return this.component.focus();
getTabHeight(): number | undefined {
return this.component.tabHeight;
}
setTabHeight(height: number | undefined): void {
this.component.tabHeight = height;
}
focus(): void {
this.component.focus();
}
getPanel(id: string): IGroupPanel | undefined {
return this.component.getGroupPanel(id);
}
setActivePanel(panel: IGroupPanel) {
return this.component.setActivePanel(panel);
setActivePanel(panel: IGroupPanel): void {
this.component.setActivePanel(panel);
}
layout(width: number, height: number, force = false) {
return this.component.layout(width, height, force);
layout(width: number, height: number, force = false): void {
this.component.layout(width, height, force);
}
addPanel(options: AddPanelOptions) {
addPanel(options: AddPanelOptions): IGroupPanel {
return this.component.addPanel(options);
}
// addDndHandle(type: string, cb: (event: LayoutDropEvent) => PanelOptions) {
// return this.component.addDndHandle(type, cb);
// }
// createDragTarget(
// target: {
// element: HTMLElement;
// content: string;
// },
// options: (() => PanelOptions) | PanelOptions
// ) {
// return this.component.createDragTarget(target, options);
// }
addEmptyGroup(options?: AddGroupOptions) {
return this.component.addEmptyGroup(options);
removePanel(panel: IGroupPanel): void {
this.component.removePanel(panel);
}
moveToNext(options?: MovementOptions) {
return this.component.moveToNext(options);
addEmptyGroup(options?: AddGroupOptions): void {
this.component.addEmptyGroup(options);
}
moveToPrevious(options?: MovementOptions) {
return this.component.moveToPrevious(options);
moveToNext(options?: MovementOptions): void {
this.component.moveToNext(options);
}
closeAllGroups() {
moveToPrevious(options?: MovementOptions): void {
this.component.moveToPrevious(options);
}
closeAllGroups(): Promise<boolean> {
return this.component.closeAllGroups();
}
removeGroup(group: GroupviewPanel) {
return this.component.removeGroup(group);
removeGroup(group: GroupviewPanel): void {
this.component.removeGroup(group);
}
resizeToFit() {
resizeToFit(): void {
return this.component.resizeToFit();
}
getTabHeight() {
return this.component.tabHeight;
}
setTabHeight(height: number | undefined) {
this.component.tabHeight = height;
}
getGroup(id: string) {
getGroup(id: string): GroupviewPanel | undefined {
return this.component.getPanel(id);
}
fromJSON(data: SerializedDockview) {
return this.component.fromJSON(data);
fromJSON(data: SerializedDockview): void {
this.component.fromJSON(data);
}
toJSON() {
toJSON(): SerializedDockview {
return this.component.toJSON();
}
}

View File

@ -29,6 +29,7 @@ import {
} from './options';
import {
BaseGrid,
GroupChangeKind,
IBaseGrid,
toTarget,
} from '../gridview/baseComponentGridview';
@ -38,7 +39,7 @@ import { LayoutMouseEvent, MouseEventKind } from '../groupview/tab';
import { Orientation } from '../splitview/core/splitview';
import { DefaultTab } from './components/tab/defaultTab';
import {
GroupChangeKind,
GroupChangeKind2,
GroupOptions,
GroupPanelViewState,
} from '../groupview/groupview';
@ -74,7 +75,7 @@ export type DockviewComponentUpdateOptions = Pick<
>;
export interface IDockviewComponent extends IBaseGrid<GroupviewPanel> {
readonly activeGroup: GroupviewPanel | undefined;
readonly activePanel: IGroupPanel | undefined;
readonly totalPanels: number;
readonly panels: IGroupPanel[];
tabHeight: number | undefined;
@ -91,6 +92,7 @@ export interface IDockviewComponent extends IBaseGrid<GroupviewPanel> {
removeGroup: (group: GroupviewPanel) => void;
options: DockviewComponentOptions;
addPanel(options: AddPanelOptions): IGroupPanel;
removePanel(panel: IGroupPanel): void;
getGroupPanel: (id: string) => IGroupPanel | undefined;
fireMouseEvent(event: LayoutMouseEvent): void;
createWatermarkComponent(): IWatermarkRenderer;
@ -148,10 +150,20 @@ export class DockviewComponent
this._deserializer = value;
}
get options() {
get options(): DockviewComponentOptions {
return this._options;
}
get activePanel(): IGroupPanel | undefined {
const activeGroup = this.activeGroup;
if (!activeGroup) {
return undefined;
}
return activeGroup.model.activePanel;
}
set tabHeight(height: number | undefined) {
this.options.tabHeight = height;
this._groups.forEach((value) => {
@ -289,8 +301,6 @@ export class DockviewComponent
);
this._panels.set(panel.id, { value: panel, disposable });
this._onGridEvent.fire({ kind: GroupChangeKind.PANEL_CREATED });
}
unregisterPanel(panel: IGroupPanel): void {
@ -305,8 +315,6 @@ export class DockviewComponent
}
this._panels.delete(panel.id);
this._onGridEvent.fire({ kind: GroupChangeKind.PANEL_DESTROYED });
}
/**
@ -451,6 +459,10 @@ export class DockviewComponent
return panel;
}
removePanel(panel: IGroupPanel): void {
panel.group?.model.removePanel(panel);
}
createWatermarkComponent(): IWatermarkRenderer {
return createComponent(
'watermark-id',
@ -599,6 +611,21 @@ export class DockviewComponent
}
}
override doSetGroupActive(
group: GroupviewPanel | undefined,
skipFocus?: boolean
) {
const isGroupAlreadyFocused = this._activeGroup === group;
super.doSetGroupActive(group, skipFocus);
if (!isGroupAlreadyFocused && this._activeGroup?.model.activePanel) {
this._onGridEvent.fire({
kind: GroupChangeKind.PANEL_ACTIVE,
panel: this._activeGroup?.model.activePanel,
});
}
}
createGroup(options?: GroupOptions): GroupviewPanel {
if (!options) {
options = { tabHeight: this.tabHeight };
@ -632,7 +659,32 @@ export class DockviewComponent
this.moveGroupOrPanel(view, groupId, itemId, target, index);
}),
view.model.onDidGroupChange((event) => {
this._onGridEvent.fire(event);
switch (event.kind) {
case GroupChangeKind2.ADD_PANEL:
this._onGridEvent.fire({
kind: GroupChangeKind.ADD_PANEL,
panel: event.panel,
});
break;
case GroupChangeKind2.GROUP_ACTIVE:
this._onGridEvent.fire({
kind: GroupChangeKind.GROUP_ACTIVE,
panel: event.panel,
});
break;
case GroupChangeKind2.REMOVE_PANEL:
this._onGridEvent.fire({
kind: GroupChangeKind.REMOVE_PANEL,
panel: event.panel,
});
break;
case GroupChangeKind2.PANEL_ACTIVE:
this._onGridEvent.fire({
kind: GroupChangeKind.PANEL_ACTIVE,
panel: event.panel,
});
break;
}
})
);
@ -755,7 +807,6 @@ export class DockviewComponent
private addDirtyPanel(panel: IGroupPanel): void {
this.dirtyPanels.add(panel);
panel.setDirty(true);
this._onGridEvent.fire({ kind: GroupChangeKind.PANEL_DIRTY });
this.debouncedDeque();
}
}

View File

@ -1,3 +1,4 @@
import { GroupChangeKind2 } from '..';
import { DockviewApi } from '../api/component.api';
import { DockviewPanelApiImpl } from '../api/groupPanelApi';
import { Event } from '../events';
@ -7,7 +8,6 @@ import {
IGroupPanel,
IGroupPanelInitParameters,
} from '../groupview/groupPanel';
import { GroupChangeKind } from '../groupview/groupview';
import { GroupviewPanel } from '../groupview/groupviewPanel';
import { CompositeDisposable, MutableDisposable } from '../lifecycle';
import { Parameters } from '../panel/types';
@ -170,7 +170,7 @@ export class DockviewGroupPanel
this.mutableDisposable.value = this._group.model.onDidGroupChange(
(ev) => {
if (ev.kind === GroupChangeKind.GROUP_ACTIVE) {
if (ev.kind === GroupChangeKind2.GROUP_ACTIVE) {
const isVisible = !!this._group?.model.isPanelActive(this);
this.api._onDidActiveChange.fire({
isActive: isGroupActive && isVisible,

View File

@ -10,7 +10,24 @@ import {
} from '../splitview/core/splitview';
import { IPanel } from '../panel/types';
import { MovementOptions2 } from '../dockview/options';
import { GroupChangeEvent, GroupChangeKind } from '../groupview/groupview';
import { IGroupPanel } from '../groupview/groupPanel';
export enum GroupChangeKind {
ADD_PANEL = 'ADD_PANEL',
REMOVE_PANEL = 'REMOVE_PANEL',
PANEL_ACTIVE = 'PANEL_ACTIVE',
//
GROUP_ACTIVE = 'GROUP_ACTIVE',
ADD_GROUP = 'ADD_GROUP',
REMOVE_GROUP = 'REMOVE_GROUP',
//
LAYOUT_FROM_JSON = 'LAYOUT_FROM_JSON',
LAYOUT = 'LAYOUT',
}
export interface GroupChangeEvent {
readonly kind: GroupChangeKind;
readonly panel?: IGroupPanel;
}
const nextLayoutId = sequentialNumberGenerator();
@ -252,7 +269,9 @@ export abstract class BaseGrid<T extends IGridPanelView>
this._activeGroup = group;
this._onGridEvent.fire({ kind: GroupChangeKind.GROUP_ACTIVE });
this._onGridEvent.fire({
kind: GroupChangeKind.GROUP_ACTIVE,
});
}
public removeGroup(group: T) {

View File

@ -11,6 +11,7 @@ import { GridviewComponentOptions } from './options';
import {
BaseGrid,
Direction,
GroupChangeKind,
IBaseGrid,
IGridPanelView,
toTarget,
@ -26,7 +27,6 @@ import { GridviewPanelApiImpl } from '../api/gridviewPanelApi';
import { GridviewApi } from '../api/component.api';
import { Orientation, Sizing } from '../splitview/core/splitview';
import { createComponent } from '../panel/componentFactory';
import { GroupChangeKind } from '../groupview/groupview';
interface PanelReference {
api: GridviewPanelApiImpl;

View File

@ -20,24 +20,11 @@ import { GroupviewPanel } from './groupviewPanel';
import { focusedElement } from '../focusedElement';
import { DockviewDropTargets } from './dnd';
export enum GroupChangeKind {
GROUP_ACTIVE = 'GROUP_ACTIVE',
ADD_GROUP = 'ADD_GROUP',
REMOVE_GROUP = 'REMOVE_GROUP',
//
export enum GroupChangeKind2 {
ADD_PANEL = 'ADD_PANEL',
REMOVE_PANEL = 'REMOVE_PANEL',
PANEL_ACTIVE = 'PANEL_ACTIVE',
//
LAYOUT_FROM_JSON = 'LAYOUT_FROM_JSON',
LAYOUT = 'LAYOUT',
//
PANEL_CREATED = 'PANEL_CREATED',
PANEL_DESTROYED = 'PANEL_DESTROYED',
PANEL_DIRTY = 'PANEL_DIRTY',
PANEL_CLEAN = 'PANEL_CLEAN',
//
LAYOUT_CONFIG_UPDATED = 'LAYOUT_CONFIG_UPDATED',
GROUP_ACTIVE = 'GROUP_ACTIVE',
}
export interface DndService {
@ -74,8 +61,8 @@ export interface GroupOptions {
tabHeight?: number;
}
export interface GroupChangeEvent {
readonly kind: GroupChangeKind;
export interface GroupviewChangeEvent {
readonly kind: GroupChangeKind2;
readonly panel?: IGroupPanel;
}
@ -104,11 +91,8 @@ export interface IGroupview extends IDisposable, IGridPanelView {
containsPanel(panel: IGroupPanel): boolean;
removePanel: (panelOrId: IGroupPanel | string) => IGroupPanel;
// events
onDidGroupChange: Event<{ kind: GroupChangeKind }>;
onDidGroupChange: Event<GroupviewChangeEvent>;
onMove: Event<GroupMoveEvent>;
//
// startActiveDrag(panel: IGroupPanel): IDisposable;
//
moveToNext(options?: { panel?: IGroupPanel; suppressRoll?: boolean }): void;
moveToPrevious(options?: {
panel?: IGroupPanel;
@ -141,8 +125,8 @@ export class Groupview extends CompositeDisposable implements IGroupview {
private readonly _onMove = new Emitter<GroupMoveEvent>();
readonly onMove: Event<GroupMoveEvent> = this._onMove.event;
private readonly _onDidGroupChange = new Emitter<GroupChangeEvent>();
readonly onDidGroupChange: Event<{ kind: GroupChangeKind }> =
private readonly _onDidGroupChange = new Emitter<GroupviewChangeEvent>();
readonly onDidGroupChange: Event<GroupviewChangeEvent> =
this._onDidGroupChange.event;
get element(): HTMLElement {
@ -289,20 +273,6 @@ export class Groupview extends CompositeDisposable implements IGroupview {
};
}
// public startActiveDrag(panel: IGroupPanel): IDisposable {
// const index = this.tabsContainer.indexOf(panel.id);
// if (index > -1) {
// const tab = this.tabsContainer.at(index);
// tab.startDragEvent();
// return {
// dispose: () => {
// tab.stopDragEvent();
// },
// };
// }
// return Disposable.NONE;
// }
public moveToNext(options?: {
panel?: IGroupPanel;
suppressRoll?: boolean;
@ -504,27 +474,16 @@ export class Groupview extends CompositeDisposable implements IGroupview {
this.tabsContainer.setActive(this.isActive);
// this.updateActions();
if (!this._activePanel && this.panels.length > 0) {
this.doSetActivePanel(this.panels[0]);
}
this.updateContainer();
// this.panels.forEach((panel) =>
// panel.updateParentGroup(this, this.isActive)
// );
// if (this.watermark?.updateParentGroup) {
// this.watermark.updateParentGroup(this, this.isActive);
// }
if (isGroupActive) {
if (!skipFocus) {
this._activePanel?.focus();
}
this._onDidGroupChange.fire({ kind: GroupChangeKind.GROUP_ACTIVE });
}
}
@ -575,7 +534,7 @@ export class Groupview extends CompositeDisposable implements IGroupview {
}
this._onDidGroupChange.fire({
kind: GroupChangeKind.REMOVE_PANEL,
kind: GroupChangeKind2.REMOVE_PANEL,
panel,
});
}
@ -599,7 +558,10 @@ export class Groupview extends CompositeDisposable implements IGroupview {
this.updateMru(panel);
this.panels.splice(index, 0, panel);
this._onDidGroupChange.fire({ kind: GroupChangeKind.ADD_PANEL, panel });
this._onDidGroupChange.fire({
kind: GroupChangeKind2.ADD_PANEL,
panel,
});
}
private doSetActivePanel(panel: IGroupPanel | undefined) {
@ -611,12 +573,12 @@ export class Groupview extends CompositeDisposable implements IGroupview {
panel.layout(this._width, this._height);
this.updateMru(panel);
}
this._onDidGroupChange.fire({
kind: GroupChangeKind.PANEL_ACTIVE,
panel,
});
this._onDidGroupChange.fire({
kind: GroupChangeKind2.PANEL_ACTIVE,
panel,
});
}
}
private updateMru(panel: IGroupPanel) {

View File

@ -5,6 +5,7 @@ export * from './splitview/splitviewComponent';
export * from './paneview/paneview';
export * from './paneview/paneviewComponent';
export * from './gridview/gridview';
export * from './gridview/baseComponentGridview';
export * from './groupview/groupview';
export * from './groupview/panel/content';
export * from './groupview/tab';