Merge branch 'master' of https://github.com/mathuo/dockview into master

This commit is contained in:
mathuo 2022-03-17 20:04:41 +00:00
commit 317957c26f
No known key found for this signature in database
GPG Key ID: C6EEDEFD6CA07281
13 changed files with 1409 additions and 230 deletions

View File

@ -13,11 +13,12 @@
"forceConsistentCasingInFileNames": true,
"strict": true,
"lib": [
"ES2015",
"ES2016.Array.Include",
"ES2017.String",
"ES2018.Promise",
"DOM",
]
"ES2015",
"ES2016.Array.Include",
"ES2017.String",
"ES2018.Promise",
"ES2019",
"DOM",
]
}
}

View File

@ -13,11 +13,12 @@
"forceConsistentCasingInFileNames": true,
"strict": true,
"lib": [
"ES2015",
"ES2016.Array.Include",
"ES2017.String",
"ES2018.Promise",
"DOM",
]
"ES2015",
"ES2016.Array.Include",
"ES2017.String",
"ES2018.Promise",
"ES2019",
"DOM",
]
}
}

View File

@ -0,0 +1,78 @@
import { IDockviewComponent, IGroupPanel } from '../..';
import { DockviewPanelApiImpl, TitleEvent } from '../../api/groupPanelApi';
import { GroupviewPanel } from '../../groupview/groupviewPanel';
describe('groupPanelApi', () => {
test('title', () => {
const groupPanel: Partial<IGroupPanel> = {
id: 'test_id',
title: 'test_title',
};
const accessor: Partial<IDockviewComponent> = {};
const groupViewPanel = new GroupviewPanel(
<IDockviewComponent>accessor,
'',
{}
);
const cut = new DockviewPanelApiImpl(
<IGroupPanel>groupPanel,
<GroupviewPanel>groupViewPanel
);
let events: TitleEvent[] = [];
const disposable = cut.onDidTitleChange((event) => {
events.push(event);
});
expect(events.length).toBe(0);
expect(cut.title).toBe('test_title');
cut.setTitle('test_title_2');
expect(events.length).toBe(1);
expect(events[0]).toEqual({ title: 'test_title_2' });
expect(cut.title).toBe('test_title'); // title should remain unchanged
disposable.dispose();
});
test('onDidGroupChange', () => {
const groupPanel: Partial<IGroupPanel> = {
id: 'test_id',
};
const accessor: Partial<IDockviewComponent> = {};
const groupViewPanel = new GroupviewPanel(
<IDockviewComponent>accessor,
'',
{}
);
const cut = new DockviewPanelApiImpl(
<IGroupPanel>groupPanel,
<GroupviewPanel>groupViewPanel
);
let events = 0;
const disposable = cut.onDidGroupChange(() => {
events++;
});
expect(events).toBe(0);
expect(cut.group).toBe(groupViewPanel);
const groupViewPanel2 = new GroupviewPanel(
<IDockviewComponent>accessor,
'',
{}
);
cut.group = groupViewPanel2;
expect(events).toBe(1);
expect(cut.group).toBe(groupViewPanel2);
disposable.dispose();
});
});

View File

@ -811,4 +811,31 @@ describe('dockviewComponent', () => {
disposable.dispose();
});
test('that removing a panel from a group reflects in the dockviewcomponent when searching for a panel', () => {
dockview.layout(500, 500);
const panel1 = dockview.addPanel({
id: 'panel1',
component: 'default',
});
const panel2 = dockview.addPanel({
id: 'panel2',
component: 'default',
});
expect(dockview.getGroupPanel('panel1')).toEqual(panel1);
expect(dockview.getGroupPanel('panel2')).toEqual(panel2);
panel1.group.model.removePanel(panel1);
expect(dockview.getGroupPanel('panel1')).toBeUndefined();
expect(dockview.getGroupPanel('panel2')).toEqual(panel2);
dockview.removePanel(panel2);
expect(dockview.getGroupPanel('panel1')).toBeUndefined();
expect(dockview.getGroupPanel('panel2')).toBeUndefined();
});
});

File diff suppressed because it is too large Load Diff

View File

@ -444,4 +444,19 @@ describe('groupview', () => {
groupview.model.closeAllPanels();
expect(removeGroupMock).toBeCalledWith(groupview);
});
test('that group is set on panel during onDidAddPanel event', () => {
const cut = new DockviewComponent(document.createElement('div'), {
components: {
component: TestContentPart,
},
});
const disposable = cut.onDidAddPanel((panel) => {
expect(panel.group).toBeTruthy();
});
const panel = cut.addPanel({ id: 'id', component: 'component' });
disposable.dispose();
});
});

View File

@ -11,6 +11,8 @@ export enum Position {
Center = 'Center',
}
type Quadrant = 'top' | 'bottom' | 'left' | 'right';
export interface DroptargetEvent {
position: Position;
nativeEvent: DragEvent;
@ -100,60 +102,18 @@ export class Droptarget extends CompositeDisposable {
const xp = (100 * x) / width;
const yp = (100 * y) / height;
let isRight = false;
let isLeft = false;
let isTop = false;
let isBottom = false;
switch (this.options.validOverlays) {
case 'all':
isRight = xp > 80;
isLeft = xp < 20;
isTop = !isRight && !isLeft && yp < 20;
isBottom = !isRight && !isLeft && yp > 80;
break;
case 'vertical':
isTop = yp < 50;
isBottom = yp >= 50;
break;
case 'horizontal':
isLeft = xp < 50;
isRight = xp >= 50;
break;
}
const quadrant = this.calculateQuadrant(
this.options.validOverlays,
xp,
yp
);
const isSmallX = width < 100;
const isSmallY = height < 100;
toggleClass(this.overlay, 'right', !isSmallX && isRight);
toggleClass(this.overlay, 'left', !isSmallX && isLeft);
toggleClass(this.overlay, 'top', !isSmallY && isTop);
toggleClass(this.overlay, 'bottom', !isSmallY && isBottom);
this.toggleClasses(quadrant, isSmallX, isSmallY);
toggleClass(
this.overlay,
'small-right',
isSmallX && isRight
);
toggleClass(this.overlay, 'small-left', isSmallX && isLeft);
toggleClass(this.overlay, 'small-top', isSmallY && isTop);
toggleClass(
this.overlay,
'small-bottom',
isSmallY && isBottom
);
if (isRight) {
this._state = Position.Right;
} else if (isLeft) {
this._state = Position.Left;
} else if (isTop) {
this._state = Position.Top;
} else if (isBottom) {
this._state = Position.Bottom;
} else {
this._state = Position.Center;
}
this.setState(quadrant);
},
onDragLeave: (e) => {
this.removeDropTarget();
@ -181,6 +141,87 @@ export class Droptarget extends CompositeDisposable {
this.removeDropTarget();
}
private toggleClasses(
quadrant: Quadrant | null,
isSmallX: boolean,
isSmallY: boolean
) {
if (!this.overlay) {
return;
}
const isLeft = quadrant === 'left';
const isRight = quadrant === 'right';
const isTop = quadrant === 'top';
const isBottom = quadrant === 'bottom';
toggleClass(this.overlay, 'right', !isSmallX && isRight);
toggleClass(this.overlay, 'left', !isSmallX && isLeft);
toggleClass(this.overlay, 'top', !isSmallY && isTop);
toggleClass(this.overlay, 'bottom', !isSmallY && isBottom);
toggleClass(this.overlay, 'small-right', isSmallX && isRight);
toggleClass(this.overlay, 'small-left', isSmallX && isLeft);
toggleClass(this.overlay, 'small-top', isSmallY && isTop);
toggleClass(this.overlay, 'small-bottom', isSmallY && isBottom);
}
private setState(quadrant: Quadrant | null) {
switch (quadrant) {
case 'top':
this._state = Position.Top;
break;
case 'left':
this._state = Position.Left;
break;
case 'bottom':
this._state = Position.Bottom;
break;
case 'right':
this._state = Position.Right;
break;
default:
this._state = Position.Center;
break;
}
}
private calculateQuadrant(
overlayType: DropTargetDirections,
xp: number,
yp: number
): Quadrant | null {
switch (overlayType) {
case 'all':
if (xp < 20) {
return 'left';
}
if (xp > 80) {
return 'right';
}
if (yp < 20) {
return 'top';
}
if (yp > 80) {
return 'bottom';
}
break;
case 'vertical':
if (yp < 50) {
return 'top';
}
return 'bottom';
case 'horizontal':
if (xp < 50) {
return 'left';
}
return 'right';
}
return null;
}
private removeDropTarget() {
if (this.target) {
this._state = undefined;

View File

@ -7,7 +7,7 @@ import { Position } from '../dnd/droptarget';
import { tail, sequenceEquals } from '../array';
import { GroupviewPanelState, IGroupPanel } from '../groupview/groupPanel';
import { DockviewGroupPanel } from './dockviewGroupPanel';
import { CompositeDisposable, IValueDisposable } from '../lifecycle';
import { CompositeDisposable } from '../lifecycle';
import { Event, Emitter } from '../events';
import { Watermark } from './components/watermark/watermark';
import {
@ -100,7 +100,6 @@ export interface IDockviewComponent extends IBaseGrid<GroupviewPanel> {
getGroupPanel: (id: string) => IGroupPanel | undefined;
fireMouseEvent(event: LayoutMouseEvent): void;
createWatermarkComponent(): IWatermarkRenderer;
// lifecycle
addEmptyGroup(options?: AddGroupOptions): void;
closeAllGroups(): void;
@ -113,13 +112,17 @@ export interface IDockviewComponent extends IBaseGrid<GroupviewPanel> {
focus(): void;
toJSON(): SerializedDockview;
fromJSON(data: SerializedDockview): void;
//
readonly onDidRemovePanel: Event<IGroupPanel>;
readonly onDidAddPanel: Event<IGroupPanel>;
readonly onDidActivePanelChange: Event<IGroupPanel | undefined>;
}
export class DockviewComponent
extends BaseGrid<GroupviewPanel>
implements IDockviewComponent
{
private readonly _panels = new Map<string, IValueDisposable<IGroupPanel>>();
// private readonly _panels = new Map<string, IValueDisposable<IGroupPanel>>();
// events
private readonly _onTabInteractionEvent = new Emitter<LayoutMouseEvent>();
@ -133,17 +136,30 @@ export class DockviewComponent
private readonly _onDidDrop = new Emitter<DockviewDropEvent>();
readonly onDidDrop: Event<DockviewDropEvent> = this._onDidDrop.event;
private readonly _onDidRemovePanel = new Emitter<IGroupPanel>();
readonly onDidRemovePanel: Event<IGroupPanel> =
this._onDidRemovePanel.event;
private readonly _onDidAddPanel = new Emitter<IGroupPanel>();
readonly onDidAddPanel: Event<IGroupPanel> = this._onDidAddPanel.event;
private readonly _onDidActivePanelChange = new Emitter<
IGroupPanel | undefined
>();
readonly onDidActivePanelChange: Event<IGroupPanel | undefined> =
this._onDidActivePanelChange.event;
// everything else
private _deserializer: IPanelDeserializer | undefined;
private _api: DockviewApi;
private _options: DockviewComponentOptions;
get totalPanels(): number {
return this._panels.size;
return this.panels.length;
}
get panels(): IGroupPanel[] {
return Array.from(this._panels.values()).map((_) => _.value);
return this.groups.flatMap((group) => group.model.panels);
}
get deserializer(): IPanelDeserializer | undefined {
@ -235,7 +251,7 @@ export class DockviewComponent
}
getGroupPanel(id: string): IGroupPanel | undefined {
return this._panels.get(id)?.value;
return this.panels.find((panel) => panel.id === id);
}
setActivePanel(panel: IGroupPanel): void {
@ -296,35 +312,6 @@ export class DockviewComponent
}
}
private registerPanel(panel: IGroupPanel): void {
if (this._panels.has(panel.id)) {
throw new Error(`panel ${panel.id} already exists`);
}
this._panels.set(panel.id, {
value: panel,
disposable: {
dispose: () => {
/** noop */
},
},
});
}
private unregisterPanel(panel: IGroupPanel): void {
if (!this._panels.has(panel.id)) {
throw new Error(`panel ${panel.id} doesn't exist`);
}
const item = this._panels.get(panel.id);
if (item) {
item.disposable.dispose();
item.value.dispose();
}
this._panels.delete(panel.id);
}
/**
* Serialize the current state of the layout
*
@ -333,13 +320,10 @@ export class DockviewComponent
toJSON(): SerializedDockview {
const data = this.gridview.serialize();
const panels = Array.from(this._panels.values()).reduce(
(collection, panel) => {
collection[panel.value.id] = panel.value.toJSON();
return collection;
},
{} as { [key: string]: GroupviewPanelState }
);
const panels = this.panels.reduce((collection, panel) => {
collection[panel.id] = panel.toJSON();
return collection;
}, {} as { [key: string]: GroupviewPanelState });
return {
grid: data,
@ -351,11 +335,9 @@ export class DockviewComponent
fromJSON(data: SerializedDockview): void {
this.gridview.clear();
this._panels.forEach((panel) => {
panel.disposable.dispose();
panel.value.dispose();
this.panels.forEach((panel) => {
panel.dispose();
});
this._panels.clear();
this._groups.clear();
if (!this.deserializer) {
@ -376,9 +358,7 @@ export class DockviewComponent
new DefaultDeserializer(this, {
createPanel: (id) => {
const panelData = panels[id];
const panel = this.deserializer!.fromJSON(panelData);
this.registerPanel(panel);
return panel;
return this.deserializer!.fromJSON(panelData);
},
})
);
@ -457,7 +437,6 @@ export class DockviewComponent
}
removePanel(panel: IGroupPanel): void {
this.unregisterPanel(panel);
const group = panel.group;
if (!group) {
@ -491,9 +470,9 @@ export class DockviewComponent
const group = this.createGroup();
if (options) {
const referencePanel = this._panels.get(
options.referencePanel
)?.value;
const referencePanel = this.panels.find(
(panel) => panel.id === options.referencePanel
);
if (!referencePanel) {
throw new Error(
@ -551,7 +530,7 @@ export class DockviewComponent
if (!target || target === Position.Center) {
const groupItem: IGroupPanel | undefined =
sourceGroup?.model.removePanel(itemId) ||
this._panels.get(itemId)?.value;
this.panels.find((panel) => panel.id === itemId);
if (!groupItem) {
throw new Error(`No panel with id ${itemId}`);
@ -603,7 +582,7 @@ export class DockviewComponent
} else {
const groupItem: IGroupPanel | undefined =
sourceGroup?.model.removePanel(itemId) ||
this._panels.get(itemId)?.value;
this.panels.find((panel) => panel.id === itemId);
if (!groupItem) {
throw new Error(`No panel with id ${itemId}`);
@ -632,6 +611,9 @@ export class DockviewComponent
kind: GroupChangeKind.PANEL_ACTIVE,
panel: this._activeGroup?.model.activePanel,
});
this._onDidActivePanelChange.fire(
this._activeGroup?.model.activePanel
);
}
}
@ -677,24 +659,25 @@ export class DockviewComponent
kind: GroupChangeKind.ADD_PANEL,
panel: event.panel,
});
break;
case GroupChangeKind2.GROUP_ACTIVE:
this._onGridEvent.fire({
kind: GroupChangeKind.GROUP_ACTIVE,
panel: event.panel,
});
if (event.panel) {
this._onDidAddPanel.fire(event.panel);
}
break;
case GroupChangeKind2.REMOVE_PANEL:
this._onGridEvent.fire({
kind: GroupChangeKind.REMOVE_PANEL,
panel: event.panel,
});
if (event.panel) {
this._onDidRemovePanel.fire(event.panel);
}
break;
case GroupChangeKind2.PANEL_ACTIVE:
this._onGridEvent.fire({
kind: GroupChangeKind.PANEL_ACTIVE,
panel: event.panel,
});
this._onDidActivePanelChange.fire(event.panel);
break;
}
})
@ -732,7 +715,6 @@ export class DockviewComponent
params: options?.params || {},
});
this.registerPanel(panel);
return panel;
}
@ -778,4 +760,12 @@ export class DockviewComponent
group.value.model.containsPanel(panel)
)?.value;
}
public dispose(): void {
super.dispose();
this._onDidActivePanelChange.dispose();
this._onDidAddPanel.dispose();
this._onDidRemovePanel.dispose();
}
}

View File

@ -1,4 +1,3 @@
import { GroupChangeKind2 } from '../groupview/groupview';
import { DockviewApi } from '../api/component.api';
import { DockviewPanelApiImpl } from '../api/groupPanelApi';
import {
@ -147,20 +146,6 @@ export class DockviewGroupPanel
this._group = group;
this.api.group = group;
this.mutableDisposable.value = this._group.model.onDidGroupChange(
(ev) => {
if (ev.kind === GroupChangeKind2.GROUP_ACTIVE) {
const isVisible = !!this._group?.model.isPanelActive(this);
this.api._onDidActiveChange.fire({
isActive: isGroupActive && isVisible,
});
this.api._onDidVisibilityChange.fire({
isVisible,
});
}
}
);
const isPanelVisible = this._group.model.isPanelActive(this);
this.api._onDidActiveChange.fire({

View File

@ -74,6 +74,9 @@ export interface IBaseGrid<T extends IGridPanelView> {
readonly groups: T[];
readonly onGridEvent: Event<GroupChangeEvent>;
readonly onDidLayoutChange: Event<void>;
readonly onDidRemoveGroup: Event<T>;
readonly onDidAddGroup: Event<T>;
readonly onDidActiveGroupChange: Event<T | undefined>;
getPanel(id: string): T | undefined;
toJSON(): object;
fromJSON(data: any): void;
@ -99,6 +102,16 @@ export abstract class BaseGrid<T extends IGridPanelView>
private _onDidLayoutChange = new Emitter<void>();
readonly onDidLayoutChange = this._onDidLayoutChange.event;
private readonly _onDidRemoveGroup = new Emitter<T>();
readonly onDidRemoveGroup: Event<T> = this._onDidRemoveGroup.event;
private readonly _onDidAddGroup = new Emitter<T>();
readonly onDidAddGroup: Event<T> = this._onDidAddGroup.event;
private readonly _onDidActiveGroupChange = new Emitter<T | undefined>();
readonly onDidActiveGroupChange: Event<T | undefined> =
this._onDidActiveGroupChange.event;
get id() {
return this._id;
}
@ -154,8 +167,7 @@ export abstract class BaseGrid<T extends IGridPanelView>
this.element.appendChild(this.gridview.element);
// TODO for some reason this is required before anything will layout correctly
this.layout(0, 0, true);
this.layout(0, 0, true); // set some elements height/widths
this.addDisposables(
this.gridview.onDidChange(() => {
@ -209,6 +221,7 @@ export abstract class BaseGrid<T extends IGridPanelView>
this.gridview.addView(group, size ?? Sizing.Distribute, location);
this._onGridEvent.fire({ kind: GroupChangeKind.ADD_GROUP });
this._onDidAddGroup.fire(group);
this.doSetGroupActive(group);
}
@ -231,6 +244,7 @@ export abstract class BaseGrid<T extends IGridPanelView>
}
this._onGridEvent.fire({ kind: GroupChangeKind.REMOVE_GROUP });
this._onDidRemoveGroup.fire(group);
if (!options?.skipActive && this._activeGroup === group) {
const groups = Array.from(this._groups.values());
@ -270,6 +284,7 @@ export abstract class BaseGrid<T extends IGridPanelView>
this._onGridEvent.fire({
kind: GroupChangeKind.GROUP_ACTIVE,
});
this._onDidActiveGroupChange.fire(group);
}
public removeGroup(group: T) {
@ -338,6 +353,11 @@ export abstract class BaseGrid<T extends IGridPanelView>
super.dispose();
this._onGridEvent.dispose();
this._onDidActiveGroupChange.dispose();
this._onDidAddGroup.dispose();
this._onDidRemoveGroup.dispose();
this._onDidLayoutChange.dispose();
this.gridview.dispose();
}
}

View File

@ -17,6 +17,19 @@ import { Node } from './types';
import { Emitter, Event } from '../events';
import { IDisposable, MutableDisposable } from '../lifecycle';
function findLeaf(candiateNode: Node, last: boolean): LeafNode {
if (candiateNode instanceof LeafNode) {
return candiateNode;
}
if (candiateNode instanceof BranchNode) {
return findLeaf(
candiateNode.children[last ? candiateNode.children.length - 1 : 0],
last
);
}
throw new Error('invalid node');
}
function flipNode<T extends Node>(
node: T,
size: number,
@ -289,7 +302,8 @@ export class Gridview implements IDisposable {
public deserialize(json: any, deserializer: IViewDeserializer) {
const orientation = json.orientation;
const height = json.height;
const height =
orientation === Orientation.VERTICAL ? json.height : json.width;
this._deserialize(
json.root as ISerializedBranchNode,
orientation,
@ -308,7 +322,8 @@ export class Gridview implements IDisposable {
root,
orientation,
deserializer,
orthogonalSize
orthogonalSize,
true
) as BranchNode;
}
@ -316,7 +331,8 @@ export class Gridview implements IDisposable {
node: ISerializedNode,
orientation: Orientation,
deserializer: IViewDeserializer,
orthogonalSize: number
orthogonalSize: number,
isRoot = false
): Node {
let result: Node;
if (node.type === 'branch') {
@ -333,12 +349,14 @@ export class Gridview implements IDisposable {
} as INodeDescriptor;
});
// HORIZONTAL => height=orthogonalsize width=size
// VERTICAL => height=size width=orthogonalsize
result = new BranchNode(
orientation,
this.proportionalLayout,
this.styles,
node.size,
orthogonalSize,
isRoot ? orthogonalSize : node.size,
isRoot ? node.size : orthogonalSize,
children
);
} else {
@ -437,21 +455,6 @@ export class Gridview implements IDisposable {
throw new Error('invalid location');
}
const findLeaf = (candiateNode: Node, last: boolean): LeafNode => {
if (candiateNode instanceof LeafNode) {
return candiateNode;
}
if (candiateNode instanceof BranchNode) {
return findLeaf(
candiateNode.children[
last ? candiateNode.children.length - 1 : 0
],
last
);
}
throw new Error('invalid node');
};
for (let i = path.length - 1; i > -1; i--) {
const n = path[i];
const l = location[i] || 0;

View File

@ -19,7 +19,6 @@ export enum GroupChangeKind2 {
ADD_PANEL = 'ADD_PANEL',
REMOVE_PANEL = 'REMOVE_PANEL',
PANEL_ACTIVE = 'PANEL_ACTIVE',
GROUP_ACTIVE = 'GROUP_ACTIVE',
}
export interface DndService {
@ -365,6 +364,10 @@ export class Groupview extends CompositeDisposable implements IGroupview {
) {
options.index = this.panels.length;
}
// ensure the group is updated before we fire any events
panel.updateParentGroup(this.parent, true);
if (this._activePanel === panel) {
this.accessor.doSetGroupActive(this.parent);
return;

View File

@ -5,7 +5,7 @@ import {
PaneTransfer,
} from '../dnd/dataTransfer';
import { Droptarget, DroptargetEvent, Position } from '../dnd/droptarget';
import { Emitter, Event } from '../events';
import { Emitter } from '../events';
import { IDisposable } from '../lifecycle';
import { Orientation } from '../splitview/core/splitview';
import {
@ -14,23 +14,6 @@ import {
PaneviewPanel,
} from './paneviewPanel';
interface ViewContainer {
readonly title: string;
readonly icon: string;
}
interface ViewContainerModel {
readonly title: string;
readonly icon: string;
readonly onDidAdd: Event<void>;
readonly onDidRemove: Event<void>;
}
interface IViewContainerService {
getViewContainerById(id: string): ViewContainer;
getViewContainerModel(container: ViewContainer): ViewContainerModel;
}
export interface PaneviewDropEvent2 extends DroptargetEvent {
panel: IPaneviewPanel;
getData: () => PaneTransfer | undefined;
@ -101,54 +84,58 @@ export abstract class DraggablePaneviewPanel extends PaneviewPanel {
this.handler,
this.target,
this.target.onDrop((event) => {
const data = getPaneData();
if (!data) {
this._onDidDrop.fire({
...event,
panel: this,
getData: () => getPaneData(),
});
return;
}
const containerApi = (this._params! as PanePanelInitParameter)
.containerApi;
const panelId = data.paneId;
const existingPanel = containerApi.getPanel(panelId);
if (!existingPanel) {
this._onDidDrop.fire({
...event,
panel: this,
getData: () => getPaneData(),
});
return;
}
const allPanels = containerApi.getPanels();
const fromIndex = allPanels.indexOf(existingPanel);
let toIndex = containerApi.getPanels().indexOf(this);
if (
event.position === Position.Left ||
event.position === Position.Top
) {
toIndex = Math.max(0, toIndex - 1);
}
if (
event.position === Position.Right ||
event.position === Position.Bottom
) {
if (fromIndex > toIndex) {
toIndex++;
}
toIndex = Math.min(allPanels.length - 1, toIndex);
}
containerApi.movePanel(fromIndex, toIndex);
this.onDrop(event);
})
);
}
private onDrop(event: DroptargetEvent) {
const data = getPaneData();
if (!data) {
this._onDidDrop.fire({
...event,
panel: this,
getData: () => getPaneData(),
});
return;
}
const containerApi = (this._params! as PanePanelInitParameter)
.containerApi;
const panelId = data.paneId;
const existingPanel = containerApi.getPanel(panelId);
if (!existingPanel) {
this._onDidDrop.fire({
...event,
panel: this,
getData: () => getPaneData(),
});
return;
}
const allPanels = containerApi.getPanels();
const fromIndex = allPanels.indexOf(existingPanel);
let toIndex = containerApi.getPanels().indexOf(this);
if (
event.position === Position.Left ||
event.position === Position.Top
) {
toIndex = Math.max(0, toIndex - 1);
}
if (
event.position === Position.Right ||
event.position === Position.Bottom
) {
if (fromIndex > toIndex) {
toIndex++;
}
toIndex = Math.min(allPanels.length - 1, toIndex);
}
containerApi.movePanel(fromIndex, toIndex);
}
}