Skip to content

Commit 86ec536

Browse files
committed
fix submenus across workbench
1 parent 375bdea commit 86ec536

8 files changed

Lines changed: 46 additions & 18 deletions

File tree

src/vs/base/browser/contextmenu.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { IAction, IActionRunner, SubmenuAction } from 'vs/base/common/actions';
6+
import { IAction, IActionRunner, SubmenuAction, SubmenuActions } from 'vs/base/common/actions';
77
import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
88
import { ResolvedKeybinding } from 'vs/base/common/keyCodes';
99
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
@@ -16,8 +16,8 @@ export interface IContextMenuEvent {
1616
}
1717

1818
export class ContextSubMenu extends SubmenuAction {
19-
constructor(label: string, public entries: Array<ContextSubMenu | IAction>) {
20-
super(label, entries, 'contextsubmenu');
19+
constructor(label: string, public actions: SubmenuActions) {
20+
super(label, actions, 'contextsubmenu');
2121
}
2222
}
2323

src/vs/base/browser/ui/menu/menu.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,8 @@ export class Menu extends ActionBar {
293293
if (action instanceof Separator) {
294294
return new MenuSeparatorActionViewItem(options.context, action, { icon: true });
295295
} else if (action instanceof SubmenuAction) {
296-
const menuActionViewItem = new SubmenuMenuActionViewItem(action, action.entries, parentData, options);
296+
const actions = Array.isArray(action.actions) ? action.actions : action.actions();
297+
const menuActionViewItem = new SubmenuMenuActionViewItem(action, actions, parentData, options);
297298

298299
if (options.enableMnemonics) {
299300
const mnemonic = menuActionViewItem.getMnemonic();

src/vs/base/browser/ui/menu/menubar.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export interface IMenuBarOptions {
3838
}
3939

4040
export interface MenuBarMenu {
41-
actions: ReadonlyArray<IAction>;
41+
actions: IAction[];
4242
label: string;
4343
}
4444

@@ -57,7 +57,7 @@ export class MenuBar extends Disposable {
5757
buttonElement: HTMLElement;
5858
titleElement: HTMLElement;
5959
label: string;
60-
actions?: ReadonlyArray<IAction>;
60+
actions?: IAction[];
6161
}[];
6262

6363
private overflowMenu!: {

src/vs/base/common/actions.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,8 +230,10 @@ export class Separator extends Action {
230230
}
231231
}
232232

233+
export type SubmenuActions = IAction[] | (() => IAction[]);
234+
233235
export class SubmenuAction extends Action {
234-
constructor(label: string, public entries: ReadonlyArray<SubmenuAction | IAction>, cssClass?: string) {
236+
constructor(label: string, readonly actions: SubmenuActions, cssClass?: string) {
235237
super(!!cssClass ? cssClass : 'submenu', label, '', true);
236238
}
237239
}

src/vs/platform/actions/common/actions.ts

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { Action } from 'vs/base/common/actions';
6+
import { Action, IAction, Separator, SubmenuAction } from 'vs/base/common/actions';
77
import { SyncDescriptor0, createSyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
88
import { IConstructorSignature2, createDecorator, BrandedService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
99
import { IKeybindings, KeybindingsRegistry, IKeybindingRule } from 'vs/platform/keybinding/common/keybindingsRegistry';
@@ -295,12 +295,35 @@ export class ExecuteCommandAction extends Action {
295295
}
296296
}
297297

298-
export class SubmenuItemAction extends Action {
298+
export class SubmenuItemAction extends SubmenuAction {
299299

300-
readonly item: ISubmenuItem;
301-
constructor(item: ISubmenuItem) {
302-
typeof item.title === 'string' ? super('', item.title, 'submenu') : super('', item.title.value, 'submenu');
303-
this.item = item;
300+
constructor(
301+
readonly item: ISubmenuItem,
302+
menuService: IMenuService,
303+
contextKeyService: IContextKeyService,
304+
options?: IMenuActionOptions
305+
) {
306+
super(typeof item.title === 'string' ? item.title : item.title.value, () => {
307+
const result: IAction[] = [];
308+
const menu = menuService.createMenu(item.submenu, contextKeyService);
309+
const groups = menu.getActions(options);
310+
menu.dispose();
311+
312+
for (let group of groups) {
313+
const [, actions] = group;
314+
315+
if (actions.length > 0) {
316+
result.push(...actions);
317+
result.push(new Separator());
318+
}
319+
}
320+
321+
if (result.length) {
322+
result.pop(); // remove last separator
323+
}
324+
325+
return result;
326+
}, 'submenu');
304327
}
305328
}
306329

src/vs/platform/actions/common/menuService.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export class MenuService implements IMenuService {
2020
}
2121

2222
createMenu(id: MenuId, contextKeyService: IContextKeyService): IMenu {
23-
return new Menu(id, this._commandService, contextKeyService);
23+
return new Menu(id, this._commandService, contextKeyService, this);
2424
}
2525
}
2626

@@ -38,7 +38,8 @@ class Menu implements IMenu {
3838
constructor(
3939
private readonly _id: MenuId,
4040
@ICommandService private readonly _commandService: ICommandService,
41-
@IContextKeyService private readonly _contextKeyService: IContextKeyService
41+
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
42+
@IMenuService private readonly _menuService: IMenuService
4243
) {
4344
this._build();
4445

@@ -114,7 +115,7 @@ class Menu implements IMenu {
114115
if (this._contextKeyService.contextMatchesRules(item.when)) {
115116
const action = isIMenuItem(item)
116117
? new MenuItemAction(item.command, item.alt, options, this._contextKeyService, this._commandService)
117-
: new SubmenuItemAction(item);
118+
: new SubmenuItemAction(item, this._menuService, this._contextKeyService, options);
118119

119120
activeActions.push(action);
120121
}

src/vs/workbench/contrib/scm/browser/scmViewPane.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1102,7 +1102,7 @@ class ViewModel {
11021102
const viewAction = new SCMViewSubMenuAction(this);
11031103

11041104
if (this.repositories.elements.length !== 1) {
1105-
return viewAction.entries;
1105+
return Array.isArray(viewAction.actions) ? viewAction.actions : viewAction.actions();
11061106
}
11071107

11081108
const menus = this.menus.getRepositoryMenus(this.repositories.elements[0].provider);

src/vs/workbench/services/contextmenu/electron-sandbox/contextmenuService.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,10 @@ class NativeContextMenuService extends Disposable implements IContextMenuService
138138

139139
// Submenu
140140
if (entry instanceof ContextSubMenu) {
141+
const actions = Array.isArray(entry.actions) ? entry.actions : entry.actions();
141142
return {
142143
label: unmnemonicLabel(stripCodicons(entry.label)).trim(),
143-
submenu: this.createMenu(delegate, entry.entries, onHide)
144+
submenu: this.createMenu(delegate, actions, onHide)
144145
};
145146
}
146147

0 commit comments

Comments
 (0)