Merge pull request #149468 from microsoft/joh/yeasty-pike

joh/yeasty pike
This commit is contained in:
Johannes Rieken 2022-05-13 15:39:10 +02:00 committed by GitHub
commit 62bd3d754a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 84 additions and 32 deletions

View file

@ -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';
@ -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;
@ -234,6 +236,7 @@ export interface IActionViewItemOptions extends IBaseActionViewItemOptions {
icon?: boolean;
label?: boolean;
keybinding?: string | null;
hoverDelegate?: IHoverDelegate;
}
export class ActionViewItem extends BaseActionViewItem {
@ -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);
@ -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);
}
}
}
}

View file

@ -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';
@ -49,6 +50,7 @@ export interface IActionBarOptions {
readonly allowContextMenu?: boolean;
readonly preventLoopNavigation?: boolean;
readonly focusOnlyEnabledItems?: boolean;
readonly hoverDelegate?: IHoverDelegate;
}
export interface IActionOptions extends IActionViewItemOptions {
@ -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

View file

@ -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);
@ -125,6 +126,7 @@ function fillInActions(
export interface IMenuEntryActionViewItemOptions {
draggable?: boolean;
keybinding?: string;
hoverDelegate?: IHoverDelegate;
}
export class MenuEntryActionViewItem extends ActionViewItem {
@ -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();
}
@ -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 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 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 {
@ -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);

View file

@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
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';
@ -11,13 +12,16 @@ 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 {
@ -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');
@ -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 {
@ -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));