diff --git a/src/vs/platform/actions/browser/menuItemActionItem.ts b/src/vs/platform/actions/browser/menuItemActionItem.ts index 5d3974e1f9c..7624f6187df 100644 --- a/src/vs/platform/actions/browser/menuItemActionItem.ts +++ b/src/vs/platform/actions/browser/menuItemActionItem.ts @@ -9,8 +9,10 @@ import {localize} from 'vs/nls'; import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; import {IMenu, MenuItemAction} from 'vs/platform/actions/common/actions'; import {IAction} from 'vs/base/common/actions'; +import {IDisposable, dispose} from 'vs/base/common/lifecycle'; import {ActionItem, Separator} from 'vs/base/browser/ui/actionbar/actionbar'; import {domEvent} from 'vs/base/browser/event'; +import {Emitter} from 'vs/base/common/event'; export function fillInActions(menu: IMenu, target: IAction[] | { primary: IAction[]; secondary: IAction[];}): void { @@ -44,6 +46,28 @@ export function createActionItem(action: IAction, keybindingService: IKeybinding } } + +const _altKey = new class extends Emitter { + + private _subscriptions: IDisposable[] = []; + + constructor() { + super({ + onFirstListenerAdd: () => { + domEvent(document.body, 'keydown')(this._key, this, this._subscriptions); + domEvent(document.body, 'keyup')(this._key, this, this._subscriptions); + }, + onLastListenerRemove: () => { + this._subscriptions = dispose(this._subscriptions); + } + }); + } + + private _key(e: KeyboardEvent) { + this.fire(e.type === 'keydown' && e.altKey); + } +}; + class MenuItemActionItem extends ActionItem { private _altKeyDown: boolean = false; @@ -55,7 +79,7 @@ class MenuItemActionItem extends ActionItem { super(undefined, action, { icon: !!action.command.iconClass, label: !action.command.iconClass }); } - private get command() { + private get _command() { const {command, altCommand} = this._action; return this._altKeyDown && altCommand || command; } @@ -70,38 +94,45 @@ class MenuItemActionItem extends ActionItem { render(container: HTMLElement): void { super.render(container); - this._callOnDispose.push(domEvent(container, 'mousemove')(e => { - if (this._altKeyDown !== e.altKey) { - this._altKeyDown = e.altKey; + let altSubscription: IDisposable; + this._callOnDispose.push(domEvent(container, 'mouseleave')(_ => dispose(altSubscription))); + this._callOnDispose.push(domEvent(container, 'mouseenter')(e => { + altSubscription = _altKey.event(value => { + this._altKeyDown = value; this._updateLabel(); this._updateTooltip(); this._updateClass(); - } + }); })); } _updateLabel(): void { if (this.options.label) { - this.$e.text(this.command.title); + this.$e.text(this._command.title); } } _updateTooltip(): void { const element = this.$e.getHTMLElement(); - const keybinding = this._keybindingService.lookupKeybindings(this.command.id)[0]; + const keybinding = this._keybindingService.lookupKeybindings(this._command.id)[0]; const keybindingLabel = keybinding && this._keybindingService.getLabelFor(keybinding); element.title = keybindingLabel - ? localize('titleAndKb', "{0} ({1})", this.command.title, keybindingLabel) - : this.command.title; + ? localize('titleAndKb', "{0} ({1})", this._command.title, keybindingLabel) + : this._command.title; } _updateClass(): void { if (this.options.icon) { const element = this.$e.getHTMLElement(); - const {iconClass} = this.command; - element.classList.add('icon', iconClass); + const {command, altCommand} = (this._action); + if (this._command !== command) { + element.classList.remove(command.iconClass); + } else if (altCommand) { + element.classList.remove(altCommand.iconClass); + } + element.classList.add('icon', this._command.iconClass); } } }