diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 431b9a0d69d49..e17803e32e71a 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -157,7 +157,8 @@ export class ActivitybarPart extends Part implements IActivityBarService { hidePart: () => this.layoutService.setSideBarHidden(true), dndHandler: new CompositeDragAndDrop(this.viewDescriptorService, ViewContainerLocation.Sidebar, (id: string, focus?: boolean) => this.viewsService.openViewContainer(id, focus), - (from: string, to: string, before?: Before2D) => this.compositeBar.move(from, to, before?.verticallyBefore) + (from: string, to: string, before?: Before2D) => this.compositeBar.move(from, to, before?.verticallyBefore), + () => this.compositeBar.getCompositeBarItems(), ), compositeSize: 52, colors: (theme: IColorTheme) => this.getActivitybarItemColors(theme), @@ -542,7 +543,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { } this.viewContainerDisposables.delete(viewContainer.id); - this.hideComposite(viewContainer.id); + this.removeComposite(viewContainer.id); } private updateActivity(viewContainer: ViewContainer, viewContainerModel: IViewContainerModel): void { @@ -619,6 +620,17 @@ export class ActivitybarPart extends Part implements IActivityBarService { } } + private removeComposite(compositeId: string): void { + this.compositeBar.removeComposite(compositeId); + + const compositeActions = this.compositeActions.get(compositeId); + if (compositeActions) { + compositeActions.activityAction.dispose(); + compositeActions.pinnedAction.dispose(); + this.compositeActions.delete(compositeId); + } + } + getPinnedViewContainerIds(): string[] { const pinnedCompositeIds = this.compositeBar.getPinnedComposites().map(v => v.id); return this.getViewContainers() diff --git a/src/vs/workbench/browser/parts/compositeBar.ts b/src/vs/workbench/browser/parts/compositeBar.ts index e42e96e59404b..d491ecb491576 100644 --- a/src/vs/workbench/browser/parts/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositeBar.ts @@ -39,6 +39,7 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop { private targetContainerLocation: ViewContainerLocation, private openComposite: (id: string, focus?: boolean) => Promise, private moveComposite: (from: string, to: string, before?: Before2D) => void, + private getItems: () => ICompositeBarItem[], ) { } drop(data: CompositeDragAndDropData, targetCompositeId: string | undefined, originalEvent: DragEvent, before?: Before2D): void { @@ -61,12 +62,7 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop { return; } - this.viewDescriptorService.moveViewContainerToLocation(currentContainer, this.targetContainerLocation); - - if (targetCompositeId) { - this.moveComposite(currentContainer.id, targetCompositeId, before); - } - + this.viewDescriptorService.moveViewContainerToLocation(currentContainer, this.targetContainerLocation, this.getTargetIndex(targetCompositeId, before)); this.openComposite(currentContainer.id); } } @@ -100,6 +96,16 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop { return this.canDrop(data, targetCompositeId); } + private getTargetIndex(targetId: string | undefined, before2d: Before2D | undefined): number | undefined { + if (!targetId) { + return undefined; + } + + const items = this.getItems(); + const before = this.targetContainerLocation === ViewContainerLocation.Panel ? before2d?.horizontallyBefore : before2d?.verticallyBefore; + return items.findIndex(o => o.id === targetId) + (before ? 0 : 1); + } + private canDrop(data: CompositeDragAndDropData, targetCompositeId: string | undefined): boolean { const dragData = data.getData(); @@ -668,9 +674,18 @@ class CompositeBarModel { } this._items = result; } + + this.updateItemsOrder(); return hasChanges; } + + private updateItemsOrder(): void { + if (this._items) { + this.items.forEach((item, index) => item.order = index); + } + } + get visibleItems(): ICompositeBarModelItem[] { return this.items.filter(item => item.visible); } @@ -706,6 +721,8 @@ class CompositeBarModel { item.visible = true; changed = true; } + + this.updateItemsOrder(); return changed; } else { const item = this.createCompositeBarItem(id, name, order, true, true); @@ -718,6 +735,8 @@ class CompositeBarModel { } this.items.splice(index, 0, item); } + + this.updateItemsOrder(); return true; } } @@ -726,6 +745,7 @@ class CompositeBarModel { for (let index = 0; index < this.items.length; index++) { if (this.items[index].id === id) { this.items.splice(index, 1); + this.updateItemsOrder(); return true; } } @@ -761,6 +781,8 @@ class CompositeBarModel { // Make sure a moved composite gets pinned sourceItem.pinned = true; + this.updateItemsOrder(); + return true; } diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index cb1f43092cc35..c1cc1af78b430 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -144,7 +144,8 @@ export class PanelPart extends CompositePart implements IPanelService { this.dndHandler = new CompositeDragAndDrop(this.viewDescriptorService, ViewContainerLocation.Panel, (id: string, focus?: boolean) => (this.openPanel(id, focus) as Promise).then(panel => panel || null), - (from: string, to: string, before?: Before2D) => this.compositeBar.move(from, to, before?.horizontallyBefore) + (from: string, to: string, before?: Before2D) => this.compositeBar.move(from, to, before?.horizontallyBefore), + () => this.compositeBar.getCompositeBarItems() ); this.compositeBar = this._register(this.instantiationService.createInstance(CompositeBar, this.getCachedPanels(), { @@ -211,7 +212,15 @@ export class PanelPart extends CompositePart implements IPanelService { const isActive = activePanel?.getId() === panel.id || (!activePanel && this.getLastActivePanelId() === panel.id); if (isActive || !this.shouldBeHidden(panel.id, cachedPanel)) { - this.compositeBar.addComposite(panel); + + // Override order + const newPanel = { + id: panel.id, + name: panel.name, + order: cachedPanel?.order === undefined ? panel.order : cachedPanel.order + }; + + this.compositeBar.addComposite(newPanel); // Pin it by default if it is new if (!cachedPanel) { diff --git a/src/vs/workbench/common/views.ts b/src/vs/workbench/common/views.ts index 7ed78a972f589..0a7e94dc9f549 100644 --- a/src/vs/workbench/common/views.ts +++ b/src/vs/workbench/common/views.ts @@ -50,8 +50,6 @@ export interface IViewContainerDescriptor { readonly alwaysUseContainerInfo?: boolean; - readonly order?: number; - readonly focusCommand?: { id: string, keybindings?: IKeybindings }; readonly viewOrderDelegate?: ViewOrderDelegate; @@ -61,6 +59,8 @@ export interface IViewContainerDescriptor { readonly extensionId?: ExtensionIdentifier; readonly rejectAddedViews?: boolean; + + order?: number; } export interface IViewContainersRegistry { @@ -510,7 +510,7 @@ export interface IViewDescriptorService { getViewContainerModel(viewContainer: ViewContainer): IViewContainerModel; readonly onDidChangeContainerLocation: Event<{ viewContainer: ViewContainer, from: ViewContainerLocation, to: ViewContainerLocation }>; - moveViewContainerToLocation(viewContainer: ViewContainer, location: ViewContainerLocation): void; + moveViewContainerToLocation(viewContainer: ViewContainer, location: ViewContainerLocation, order?: number): void; // Views getViewDescriptorById(id: string): IViewDescriptor | null; diff --git a/src/vs/workbench/services/views/browser/viewDescriptorService.ts b/src/vs/workbench/services/views/browser/viewDescriptorService.ts index ee11c37e6beb8..5436753128f9b 100644 --- a/src/vs/workbench/services/views/browser/viewDescriptorService.ts +++ b/src/vs/workbench/services/views/browser/viewDescriptorService.ts @@ -295,7 +295,7 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor return this.viewContainersRegistry.getDefaultViewContainer(location); } - moveViewContainerToLocation(viewContainer: ViewContainer, location: ViewContainerLocation): void { + moveViewContainerToLocation(viewContainer: ViewContainer, location: ViewContainerLocation, order?: number): void { const from = this.getViewContainerLocation(viewContainer); const to = location; if (from !== to) { @@ -304,6 +304,10 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor const defaultLocation = this.isGeneratedContainerId(viewContainer.id) ? true : this.getViewContainerLocation(viewContainer) === this.getDefaultViewContainerLocation(viewContainer); this.getOrCreateDefaultViewContainerLocationContextKey(viewContainer).set(defaultLocation); + if (order !== undefined) { + viewContainer.order = order; + } + this._onDidChangeContainerLocation.fire({ viewContainer, from, to }); const views = this.getViewsByContainer(viewContainer);