Skip to content

Commit dbfe999

Browse files
authored
Context menu grouping is broken (microsoft#211625)
* Context menu grouping is broken Fixes microsoft#211488 * Make grouping explicit
1 parent 78dcc8f commit dbfe999

File tree

1 file changed

+48
-22
lines changed

1 file changed

+48
-22
lines changed

src/vs/workbench/browser/parts/views/treeView.ts

Lines changed: 48 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { IIdentityProvider, IListVirtualDelegate } from 'vs/base/browser/ui/list
1313
import { ElementsDragAndDropData, ListViewTargetSector } from 'vs/base/browser/ui/list/listView';
1414
import { IAsyncDataSource, ITreeContextMenuEvent, ITreeDragAndDrop, ITreeDragOverReaction, ITreeNode, ITreeRenderer, TreeDragOverBubble } from 'vs/base/browser/ui/tree/tree';
1515
import { CollapseAllAction } from 'vs/base/browser/ui/tree/treeDefaults';
16-
import { ActionRunner, IAction } from 'vs/base/common/actions';
16+
import { ActionRunner, IAction, Separator } from 'vs/base/common/actions';
1717
import { timeout } from 'vs/base/common/async';
1818
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
1919
import { Codicon } from 'vs/base/common/codicons';
@@ -1599,13 +1599,53 @@ class TreeMenus implements IDisposable {
15991599
this.contextKeyService = service;
16001600
}
16011601

1602+
private filterNonUniversalActions(groups: Map<string, IAction>[], newActions: IAction[]) {
1603+
const newActionsSet: Set<string> = new Set(newActions.map(a => a.id));
1604+
for (const group of groups) {
1605+
const actions = group.keys();
1606+
for (const action of actions) {
1607+
if (!newActionsSet.has(action)) {
1608+
group.delete(action);
1609+
}
1610+
}
1611+
}
1612+
}
1613+
1614+
private buildMenu(groups: Map<string, IAction>[]): IAction[] {
1615+
const result: IAction[] = [];
1616+
for (const group of groups) {
1617+
if (group.size > 0) {
1618+
if (result.length) {
1619+
result.push(new Separator());
1620+
}
1621+
result.push(...group.values());
1622+
}
1623+
}
1624+
return result;
1625+
}
1626+
1627+
private createGroups(actions: IAction[]): Map<string, IAction>[] {
1628+
const groups: Map<string, IAction>[] = [];
1629+
let group: Map<string, IAction> = new Map();
1630+
for (const action of actions) {
1631+
if (action instanceof Separator) {
1632+
groups.push(group);
1633+
group = new Map();
1634+
} else {
1635+
group.set(action.id, action);
1636+
}
1637+
}
1638+
groups.push(group);
1639+
return groups;
1640+
}
1641+
16021642
private getActions(menuId: MenuId, elements: ITreeItem[], listen?: DisposableStore): { primary: IAction[]; secondary: IAction[] } {
16031643
if (!this.contextKeyService) {
16041644
return { primary: [], secondary: [] };
16051645
}
16061646

1607-
const allowedPrimary = new Map<string, IAction>();
1608-
const allowedSecondary = new Map<string, IAction>();
1647+
let primaryGroups: Map<string, IAction>[] = [];
1648+
let secondaryGroups: Map<string, IAction>[] = [];
16091649
for (let i = 0; i < elements.length; i++) {
16101650
const element = elements[i];
16111651
const contextKeyService = this.contextKeyService.createOverlay([
@@ -1619,25 +1659,11 @@ class TreeMenus implements IDisposable {
16191659
const result = { primary, secondary, menu };
16201660
createAndFillInContextMenuActions(menu, { shouldForwardArgs: true }, result, 'inline');
16211661
if (i === 0) {
1622-
for (const action of result.primary) {
1623-
allowedPrimary.set(action.id, action);
1624-
}
1625-
for (const action of result.secondary) {
1626-
allowedSecondary.set(action.id, action);
1627-
}
1662+
primaryGroups = this.createGroups(result.primary);
1663+
secondaryGroups = this.createGroups(result.secondary);
16281664
} else {
1629-
const primaryKeys = allowedPrimary.keys();
1630-
for (const key of primaryKeys) {
1631-
if (!result.primary.some(action => action.id === key)) {
1632-
allowedPrimary.delete(key);
1633-
}
1634-
}
1635-
const secondaryKeys = allowedSecondary.keys();
1636-
for (const key of secondaryKeys) {
1637-
if (!result.secondary.some(action => action.id === key)) {
1638-
allowedSecondary.delete(key);
1639-
}
1640-
}
1665+
this.filterNonUniversalActions(primaryGroups, result.primary);
1666+
this.filterNonUniversalActions(secondaryGroups, result.secondary);
16411667
}
16421668
if (listen && elements.length === 1) {
16431669
listen.add(menu.onDidChange(() => this._onDidChange.fire(element)));
@@ -1647,7 +1673,7 @@ class TreeMenus implements IDisposable {
16471673
}
16481674
}
16491675

1650-
return { primary: Array.from(allowedPrimary.values()), secondary: Array.from(allowedSecondary.values()) };
1676+
return { primary: this.buildMenu(primaryGroups), secondary: this.buildMenu(secondaryGroups) };
16511677
}
16521678

16531679
dispose() {

0 commit comments

Comments
 (0)