Skip to content

Commit

Permalink
Merge pull request #149468 from microsoft/joh/yeasty-pike
Browse files Browse the repository at this point in the history
joh/yeasty pike
  • Loading branch information
jrieken committed May 13, 2022
2 parents 575bf6b + d092cb8 commit 62bd3d7
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 33 deletions.
21 changes: 19 additions & 2 deletions src/vs/base/browser/ui/actionbar/actionViewItems.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { $, addDisposableListener, append, EventHelper, EventLike, EventType } f
import { EventType as TouchEventType, Gesture } from 'vs/base/browser/touch';
import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';
import { IHoverDelegate } from 'vs/base/browser/ui/iconLabel/iconHoverDelegate';
import { ICustomHover, setupCustomHover } from 'vs/base/browser/ui/iconLabel/iconLabelHover';
import { ISelectBoxOptions, ISelectOptionItem, SelectBox } from 'vs/base/browser/ui/selectBox/selectBox';
import { Action, ActionRunner, IAction, IActionChangeEvent, IActionRunner, Separator } from 'vs/base/common/actions';
import { Disposable } from 'vs/base/common/lifecycle';
Expand All @@ -28,7 +30,7 @@ export class BaseActionViewItem extends Disposable implements IActionViewItem {
element: HTMLElement | undefined;

_context: unknown;
_action: IAction;
readonly _action: IAction;

get action() {
return this._action;
Expand Down Expand Up @@ -234,6 +236,7 @@ export interface IActionViewItemOptions extends IBaseActionViewItemOptions {
icon?: boolean;
label?: boolean;
keybinding?: string | null;
hoverDelegate?: IHoverDelegate;
}

export class ActionViewItem extends BaseActionViewItem {
Expand All @@ -242,6 +245,7 @@ export class ActionViewItem extends BaseActionViewItem {
protected override options: IActionViewItemOptions;

private cssClass?: string;
private customHover?: ICustomHover;

constructor(context: unknown, action: IAction, options: IActionViewItemOptions = {}) {
super(context, action, options);
Expand Down Expand Up @@ -326,10 +330,23 @@ export class ActionViewItem extends BaseActionViewItem {
title = nls.localize({ key: 'titleLabel', comment: ['action title', 'action keybinding'] }, "{0} ({1})", title, this.options.keybinding);
}
}
this._applyUpdateTooltip(title);
}

protected _applyUpdateTooltip(title: string | undefined | null): void {
if (title && this.label) {
this.label.title = title;
this.label.setAttribute('aria-label', title);
if (!this.options.hoverDelegate) {
this.label.title = title;
} else {
this.label.title = '';
if (!this.customHover) {
this.customHover = setupCustomHover(this.options.hoverDelegate, this.label, title);
this._store.add(this.customHover);
} else {
this.customHover.update(title);
}
}
}
}

Expand Down
4 changes: 3 additions & 1 deletion src/vs/base/browser/ui/actionbar/actionbar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import * as DOM from 'vs/base/browser/dom';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { ActionViewItem, BaseActionViewItem, IActionViewItemOptions } from 'vs/base/browser/ui/actionbar/actionViewItems';
import { IHoverDelegate } from 'vs/base/browser/ui/iconLabel/iconHoverDelegate';
import { ActionRunner, IAction, IActionRunner, IRunEvent, Separator } from 'vs/base/common/actions';
import { Emitter } from 'vs/base/common/event';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
Expand Down Expand Up @@ -49,6 +50,7 @@ export interface IActionBarOptions {
readonly allowContextMenu?: boolean;
readonly preventLoopNavigation?: boolean;
readonly focusOnlyEnabledItems?: boolean;
readonly hoverDelegate?: IHoverDelegate;
}

export interface IActionOptions extends IActionViewItemOptions {
Expand Down Expand Up @@ -327,7 +329,7 @@ export class ActionBar extends Disposable implements IActionRunner {
}

if (!item) {
item = new ActionViewItem(this.context, action, options);
item = new ActionViewItem(this.context, action, { hoverDelegate: this.options.hoverDelegate, ...options });
}

// Prevent native context menu on actions
Expand Down
46 changes: 23 additions & 23 deletions src/vs/platform/actions/browser/menuEntryActionViewItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService';
import { isDark } from 'vs/platform/theme/common/theme';
import { IHoverDelegate } from 'vs/base/browser/ui/iconLabel/iconHoverDelegate';

export function createAndFillInContextMenuActions(menu: IMenu, options: IMenuActionOptions | undefined, target: IAction[] | { primary: IAction[]; secondary: IAction[] }, primaryGroup?: string): IDisposable {
const groups = menu.getActions(options);
Expand Down Expand Up @@ -125,6 +126,7 @@ function fillInActions(
export interface IMenuEntryActionViewItemOptions {
draggable?: boolean;
keybinding?: string;
hoverDelegate?: IHoverDelegate;
}

export class MenuEntryActionViewItem extends ActionViewItem {
Expand All @@ -134,14 +136,14 @@ export class MenuEntryActionViewItem extends ActionViewItem {
private readonly _altKey: ModifierKeyEmitter;

constructor(
_action: MenuItemAction,
action: MenuItemAction,
options: IMenuEntryActionViewItemOptions | undefined,
@IKeybindingService protected readonly _keybindingService: IKeybindingService,
@INotificationService protected _notificationService: INotificationService,
@IContextKeyService protected _contextKeyService: IContextKeyService,
@IThemeService protected _themeService: IThemeService
) {
super(undefined, _action, { icon: !!(_action.class || _action.item.icon), label: !_action.class && !_action.item.icon, draggable: options?.draggable, keybinding: options?.keybinding });
super(undefined, action, { icon: !!(action.class || action.item.icon), label: !action.class && !action.item.icon, draggable: options?.draggable, keybinding: options?.keybinding, hoverDelegate: options?.hoverDelegate });
this._altKey = ModifierKeyEmitter.getInstance();
}

Expand Down Expand Up @@ -209,26 +211,24 @@ export class MenuEntryActionViewItem extends ActionViewItem {
}

override updateTooltip(): void {
if (this.label) {
const keybinding = this._keybindingService.lookupKeybinding(this._commandAction.id, this._contextKeyService);
const keybindingLabel = keybinding && keybinding.getLabel();

const tooltip = this._commandAction.tooltip || this._commandAction.label;
let title = keybindingLabel
? localize('titleAndKb', "{0} ({1})", tooltip, keybindingLabel)
: tooltip;
if (!this._wantsAltCommand && this._menuItemAction.alt?.enabled) {
const altTooltip = this._menuItemAction.alt.tooltip || this._menuItemAction.alt.label;
const altKeybinding = this._keybindingService.lookupKeybinding(this._menuItemAction.alt.id, this._contextKeyService);
const altKeybindingLabel = altKeybinding && altKeybinding.getLabel();
const altTitleSection = altKeybindingLabel
? localize('titleAndKb', "{0} ({1})", altTooltip, altKeybindingLabel)
: altTooltip;
title += `\n[${UILabelProvider.modifierLabels[OS].altKey}] ${altTitleSection}`;
}
this.label.title = title;
this.label.setAttribute('aria-label', title);
const keybinding = this._keybindingService.lookupKeybinding(this._commandAction.id, this._contextKeyService);
const keybindingLabel = keybinding && keybinding.getLabel();

const tooltip = this._commandAction.tooltip || this._commandAction.label;
let title = keybindingLabel
? localize('titleAndKb', "{0} ({1})", tooltip, keybindingLabel)
: tooltip;
if (!this._wantsAltCommand && this._menuItemAction.alt?.enabled) {
const altTooltip = this._menuItemAction.alt.tooltip || this._menuItemAction.alt.label;
const altKeybinding = this._keybindingService.lookupKeybinding(this._menuItemAction.alt.id, this._contextKeyService);
const altKeybindingLabel = altKeybinding && altKeybinding.getLabel();
const altTitleSection = altKeybindingLabel
? localize('titleAndKb', "{0} ({1})", altTooltip, altKeybindingLabel)
: altTooltip;

title = localize('titleAndKbAndAlt', "{0}\n[{1}] {2}", title, UILabelProvider.modifierLabels[OS].altKey, altTitleSection);
}
this._applyUpdateTooltip(title);
}

override updateClass(): void {
Expand Down Expand Up @@ -481,9 +481,9 @@ export class DropdownWithDefaultActionViewItem extends BaseActionViewItem {
/**
* Creates action view items for menu actions or submenu actions.
*/
export function createActionViewItem(instaService: IInstantiationService, action: IAction, options?: IDropdownMenuActionViewItemOptions): undefined | MenuEntryActionViewItem | SubmenuEntryActionViewItem | BaseActionViewItem {
export function createActionViewItem(instaService: IInstantiationService, action: IAction, options?: IDropdownMenuActionViewItemOptions | IMenuEntryActionViewItemOptions): undefined | MenuEntryActionViewItem | SubmenuEntryActionViewItem | BaseActionViewItem {
if (action instanceof MenuItemAction) {
return instaService.createInstance(MenuEntryActionViewItem, action, undefined);
return instaService.createInstance(MenuEntryActionViewItem, action, options);
} else if (action instanceof SubmenuItemAction) {
if (action.item.rememberDefaultAction) {
return instaService.createInstance(DropdownWithDefaultActionViewItem, action, options);
Expand Down
47 changes: 40 additions & 7 deletions src/vs/workbench/browser/parts/titlebar/titleMenuControl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,24 @@
*--------------------------------------------------------------------------------------------*/

import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
import { IHoverDelegate } from 'vs/base/browser/ui/iconLabel/iconHoverDelegate';
import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar';
import { Action, IAction } from 'vs/base/common/actions';
import { Codicon } from 'vs/base/common/codicons';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { localize } from 'vs/nls';
import { createActionViewItem, createAndFillInContextMenuActions, MenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { IMenuService, MenuId, MenuItemAction } from 'vs/platform/actions/common/actions';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
import * as colors from 'vs/platform/theme/common/colorRegistry';
import { WindowTitle } from 'vs/workbench/browser/parts/titlebar/windowTitle';
import { MENUBAR_SELECTION_BACKGROUND, MENUBAR_SELECTION_FOREGROUND, TITLE_BAR_ACTIVE_FOREGROUND } from 'vs/workbench/common/theme';
import { IHoverService } from 'vs/workbench/services/hover/browser/hover';

export class TitleMenuControl {

Expand All @@ -32,14 +36,37 @@ export class TitleMenuControl {
@IInstantiationService instantiationService: IInstantiationService,
@IMenuService menuService: IMenuService,
@IQuickInputService quickInputService: IQuickInputService,
@IHoverService hoverService: IHoverService,
@IConfigurationService configurationService: IConfigurationService,
@IKeybindingService keybindingService: IKeybindingService,
) {
this.element.classList.add('title-menu');

const hoverDelegate = new class implements IHoverDelegate {

private _lastHoverHideTime: number = 0;

readonly showHover = hoverService.showHover.bind(hoverService);
readonly placement = 'element';

get delay(): number {
return Date.now() - this._lastHoverHideTime < 200
? 0 // show instantly when a hover was recently shown
: configurationService.getValue<number>('workbench.hover.delay');
}

onDidHideHover() {
this._lastHoverHideTime = Date.now();
}
};

const titleToolbar = new ToolBar(this.element, contextMenuService, {
actionViewItemProvider: (action) => {

if (action instanceof MenuItemAction && action.id === 'workbench.action.quickOpen') {

class InputLikeViewItem extends MenuEntryActionViewItem {

override render(container: HTMLElement): void {
super.render(container);
container.classList.add('quickopen');
Expand All @@ -49,11 +76,17 @@ export class TitleMenuControl {
}

private _updateFromWindowTitle() {
if (this.label) {
this.label.classList.add('search');
this.label.innerText = localize('search', "Search {0}", windowTitle.workspaceName);
this.label.title = windowTitle.value;
if (!this.label) {
return;
}
this.label.classList.add('search');
this.label.innerText = localize('search', "Search {0}", windowTitle.workspaceName);

const kb = keybindingService.lookupKeybinding(action.id)?.getLabel();
const title = kb
? localize('title', "Search {0} ({1}) \u2014 {2}", windowTitle.workspaceName, kb, windowTitle.value)
: localize('title2', "Search {0} \u2014 {1}", windowTitle.workspaceName, windowTitle.value);
this._applyUpdateTooltip(title);
}

private _renderAllQuickPickItem(parent: HTMLElement): void {
Expand All @@ -63,16 +96,16 @@ export class TitleMenuControl {
const action = new Action('all', localize('all', "Show Quick Pick Options..."), Codicon.chevronDown.classNames, true, () => {
quickInputService.quickAccess.show('?');
});
const dropdown = new ActionViewItem(undefined, action, { icon: true, label: false });
const dropdown = new ActionViewItem(undefined, action, { icon: true, label: false, hoverDelegate });
dropdown.render(container);
this._store.add(dropdown);
this._store.add(action);
}
}
return instantiationService.createInstance(InputLikeViewItem, action, undefined);
return instantiationService.createInstance(InputLikeViewItem, action, { hoverDelegate });
}

return createActionViewItem(instantiationService, action);
return createActionViewItem(instantiationService, action, { hoverDelegate });
}
});
const titleMenu = this._disposables.add(menuService.createMenu(MenuId.TitleMenu, contextKeyService));
Expand Down

0 comments on commit 62bd3d7

Please sign in to comment.