Skip to content

Commit

Permalink
context menu: support sub menus
Browse files Browse the repository at this point in the history
  • Loading branch information
isidorn committed May 18, 2016
1 parent 8f6b370 commit 2d052f7
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 25 deletions.
8 changes: 7 additions & 1 deletion src/vs/platform/contextview/browser/contextView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,16 @@ export interface IContextMenuService {

export interface IContextMenuDelegate {
getAnchor(): HTMLElement | { x: number; y: number; };
getActions(): TPromise<IAction[]>;
getActions(): TPromise<(IAction|ContextSubMenu)[]>;
getActionItem?(action: IAction): ActionBar.IActionItem;
getActionsContext?(): any;
getKeyBinding?(action: IAction): Keybinding;
getMenuClassName?(): string;
onHide?(didCancel: boolean): void;
}

export class ContextSubMenu {
constructor(public label: string, public entries: (ContextSubMenu|IAction)[]) {
// noop
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {IAction} from 'vs/base/common/actions';
import {Separator} from 'vs/base/browser/ui/actionbar/actionbar';
import dom = require('vs/base/browser/dom');
import {$} from 'vs/base/browser/builder';
import {IContextMenuService, IContextMenuDelegate} from 'vs/platform/contextview/browser/contextView';
import {IContextMenuService, IContextMenuDelegate, ContextSubMenu} from 'vs/platform/contextview/browser/contextView';
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
import {IMessageService} from 'vs/platform/message/common/message';
import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService';
Expand All @@ -32,29 +32,7 @@ export class ContextMenuService implements IContextMenuService {
}

return TPromise.timeout(0).then(() => { // https://github.com/Microsoft/vscode/issues/3638
let menu = new remote.Menu();

actions.forEach(a => {
if (a instanceof Separator) {
menu.append(new remote.MenuItem({ type: 'separator' }));
} else {
const keybinding = !!delegate.getKeyBinding ? delegate.getKeyBinding(a) : undefined;
const accelerator = keybinding && this.keybindingService.getElectronAcceleratorFor(keybinding);

const item = new remote.MenuItem({
label: a.label,
checked: a.checked,
accelerator,
enabled: a.enabled,
click: () => {
this.runAction(a, delegate);
}
});

menu.append(item);
}
});

const menu = this.createMenu(delegate, actions);
const anchor = delegate.getAnchor();
let x: number, y: number;

Expand Down Expand Up @@ -83,6 +61,40 @@ export class ContextMenuService implements IContextMenuService {
});
}

private createMenu(delegate: IContextMenuDelegate, entries: (IAction|ContextSubMenu)[]): Electron.Menu {
const menu = new remote.Menu();

entries.forEach(e => {
if (e instanceof Separator) {
menu.append(new remote.MenuItem({ type: 'separator' }));
} else if (e instanceof ContextSubMenu) {
const submenu = new remote.MenuItem({
submenu: this.createMenu(delegate, e.entries),
label: e.label
});

menu.append(submenu);
} else {
const keybinding = !!delegate.getKeyBinding ? delegate.getKeyBinding(e) : undefined;
const accelerator = keybinding && this.keybindingService.getElectronAcceleratorFor(keybinding);

const item = new remote.MenuItem({
label: e.label,
checked: e.checked,
accelerator,
enabled: e.enabled,
click: () => {
this.runAction(e, delegate);
}
});

menu.append(item);
}
});

return menu;
}

private runAction(actionToRun: IAction, delegate: IContextMenuDelegate): void {
this.telemetryService.publicLog('workbenchActionExecuted', { id: actionToRun.id, from: 'contextMenu' });

Expand Down

0 comments on commit 2d052f7

Please sign in to comment.