提交 e6f3f165 编写于 作者: J João Moreno

SubmenuEntryActionViewItem

上级 6d2a2f0f
......@@ -13,6 +13,7 @@ import { Emitter } from 'vs/base/common/event';
import { BaseActionViewItem, IBaseActionViewItemOptions } from 'vs/base/browser/ui/actionbar/actionViewItems';
import { IActionProvider, DropdownMenu, IDropdownMenuOptions, ILabelRenderer } from 'vs/base/browser/ui/dropdown/dropdown';
import { IContextMenuProvider } from 'vs/base/browser/contextmenu';
import { asArray } from 'vs/base/common/arrays';
export interface IKeybindingProvider {
(action: IAction): ResolvedKeybinding | undefined;
......@@ -26,7 +27,7 @@ export interface IDropdownMenuActionViewItemOptions extends IBaseActionViewItemO
readonly actionViewItemProvider?: IActionViewItemProvider;
readonly keybindingProvider?: IKeybindingProvider;
readonly actionRunner?: IActionRunner;
readonly clazz?: string;
readonly classNames?: string[] | string;
readonly anchorAlignmentProvider?: IAnchorAlignmentProvider;
readonly menuAsChild?: boolean;
}
......@@ -57,11 +58,17 @@ export class DropdownMenuActionViewItem extends BaseActionViewItem {
render(container: HTMLElement): void {
const labelRenderer: ILabelRenderer = (el: HTMLElement): IDisposable | null => {
this.element = append(el, $('a.action-label.codicon')); // todo@aeschli: remove codicon, should come through `this.options.clazz`
if (this.options.clazz) {
addClasses(this.element, this.options.clazz);
this.element = append(el, $('a.action-label'));
const classNames = this.options.classNames ? asArray(this.options.classNames) : [];
// todo@aeschli: remove codicon, should come through `this.options.classNames`
if (!classNames.find(c => c === 'icon')) {
classNames.push('codicon');
}
addClasses(this.element, ...classNames);
this.element.tabIndex = 0;
this.element.setAttribute('role', 'button');
this.element.setAttribute('aria-haspopup', 'true');
......
......@@ -61,49 +61,57 @@ export class ToolBar extends Disposable {
ariaLabel: options.ariaLabel,
actionRunner: options.actionRunner,
actionViewItemProvider: (action: IAction) => {
if (action instanceof SubmenuAction) {
const actions = Array.isArray(action.actions) ? action.actions : action.actions();
const result = new DropdownMenuActionViewItem(
if (action.id === ToggleMenuAction.ID) {
this.toggleMenuActionViewItem = new DropdownMenuActionViewItem(
action,
actions,
(<ToggleMenuAction>action).menuActions,
contextMenuProvider,
{
actionViewItemProvider: this.options.actionViewItemProvider,
actionRunner: this.actionRunner,
keybindingProvider: this.options.getKeyBinding,
clazz: action.class,
classNames: toolBarMoreIcon.classNames,
anchorAlignmentProvider: this.options.anchorAlignmentProvider,
menuAsChild: true
}
);
result.setActionContext(this.actionBar.context);
this.submenuActionViewItems.push(result);
this.disposables.add(this._onDidChangeDropdownVisibility.add(result.onDidChangeVisibility));
this.toggleMenuActionViewItem.setActionContext(this.actionBar.context);
this.disposables.add(this._onDidChangeDropdownVisibility.add(this.toggleMenuActionViewItem.onDidChangeVisibility));
return result;
return this.toggleMenuActionViewItem;
}
if (action.id === ToggleMenuAction.ID) {
this.toggleMenuActionViewItem = new DropdownMenuActionViewItem(
if (options.actionViewItemProvider) {
const result = options.actionViewItemProvider(action);
if (result) {
return result;
}
}
if (action instanceof SubmenuAction) {
const actions = Array.isArray(action.actions) ? action.actions : action.actions();
const result = new DropdownMenuActionViewItem(
action,
(<ToggleMenuAction>action).menuActions,
actions,
contextMenuProvider,
{
actionViewItemProvider: this.options.actionViewItemProvider,
actionRunner: this.actionRunner,
keybindingProvider: this.options.getKeyBinding,
clazz: toolBarMoreIcon.classNames,
classNames: action.class,
anchorAlignmentProvider: this.options.anchorAlignmentProvider,
menuAsChild: true
}
);
this.toggleMenuActionViewItem.setActionContext(this.actionBar.context);
this.disposables.add(this._onDidChangeDropdownVisibility.add(this.toggleMenuActionViewItem.onDidChangeVisibility));
result.setActionContext(this.actionBar.context);
this.submenuActionViewItems.push(result);
this.disposables.add(this._onDidChangeDropdownVisibility.add(result.onDidChangeVisibility));
return this.toggleMenuActionViewItem;
return result;
}
return options.actionViewItemProvider ? options.actionViewItemProvider(action) : undefined;
return undefined;
}
}));
}
......
......@@ -17,6 +17,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
import { DropdownMenuActionViewItem } from 'vs/base/browser/ui/dropdown/dropdownActionViewItem';
// The alternative key on all platforms is alt. On windows we also support shift as an alternative key #44136
class AlternativeKeyEmitter extends Emitter<boolean> {
......@@ -126,9 +127,9 @@ function fillInActions(groups: ReadonlyArray<[string, ReadonlyArray<MenuItemActi
const ids = new IdGenerator('menu-item-action-item-icon-');
export class MenuEntryActionViewItem extends ActionViewItem {
const ICON_PATH_TO_CSS_RULES = new Map<string /* path*/, string /* CSS rule */>();
static readonly ICON_PATH_TO_CSS_RULES: Map<string /* path*/, string /* CSS rule */> = new Map<string, string>();
export class MenuEntryActionViewItem extends ActionViewItem {
private _wantsAltCommand: boolean = false;
private readonly _itemClassDispose = this._register(new MutableDisposable());
......@@ -227,7 +228,7 @@ export class MenuEntryActionViewItem extends ActionViewItem {
}
}
_updateItemClass(item: ICommandAction): void {
private _updateItemClass(item: ICommandAction): void {
this._itemClassDispose.value = undefined;
const icon = this._commandAction.checked && (item.toggled as { icon?: Icon })?.icon ? (item.toggled as { icon: Icon }).icon : item.icon;
......@@ -252,13 +253,13 @@ export class MenuEntryActionViewItem extends ActionViewItem {
const iconPathMapKey = icon.dark.toString();
if (MenuEntryActionViewItem.ICON_PATH_TO_CSS_RULES.has(iconPathMapKey)) {
iconClass = MenuEntryActionViewItem.ICON_PATH_TO_CSS_RULES.get(iconPathMapKey)!;
if (ICON_PATH_TO_CSS_RULES.has(iconPathMapKey)) {
iconClass = ICON_PATH_TO_CSS_RULES.get(iconPathMapKey)!;
} else {
iconClass = ids.nextId();
createCSSRule(`.icon.${iconClass}`, `background-image: ${asCSSUrl(icon.light || icon.dark)}`);
createCSSRule(`.vs-dark .icon.${iconClass}, .hc-black .icon.${iconClass}`, `background-image: ${asCSSUrl(icon.dark)}`);
MenuEntryActionViewItem.ICON_PATH_TO_CSS_RULES.set(iconPathMapKey, iconClass);
ICON_PATH_TO_CSS_RULES.set(iconPathMapKey, iconClass);
}
if (this.label) {
......@@ -274,3 +275,34 @@ export class MenuEntryActionViewItem extends ActionViewItem {
}
}
}
export class SubmenuEntryActionViewItem extends DropdownMenuActionViewItem {
constructor(
action: SubmenuItemAction,
@INotificationService _notificationService: INotificationService,
@IContextMenuService _contextMenuService: IContextMenuService
) {
const classNames: string[] = [];
if (action.item.icon) {
if (ThemeIcon.isThemeIcon(action.item.icon)) {
classNames.push(ThemeIcon.asClassName(action.item.icon)!);
} else if (action.item.icon.dark?.scheme) {
const iconPathMapKey = action.item.icon.dark.toString();
if (ICON_PATH_TO_CSS_RULES.has(iconPathMapKey)) {
classNames.push('icon', ICON_PATH_TO_CSS_RULES.get(iconPathMapKey)!);
} else {
const className = ids.nextId();
classNames.push('icon', className);
createCSSRule(`.icon.${className}`, `background-image: ${asCSSUrl(action.item.icon.light || action.item.icon.dark)}`);
createCSSRule(`.vs-dark .icon.${className}, .hc-black .icon.${className}`, `background-image: ${asCSSUrl(action.item.icon.dark)}`);
ICON_PATH_TO_CSS_RULES.set(iconPathMapKey, className);
}
}
}
super(action, Array.isArray(action.actions) ? action.actions : action.actions(), _contextMenuService, { classNames });
}
}
......@@ -211,7 +211,7 @@ export class NotificationRenderer implements IListRenderer<INotificationViewItem
ariaLabel: localize('notificationActions', "Notification Actions"),
actionViewItemProvider: action => {
if (action && action instanceof ConfigureNotificationAction) {
const item = new DropdownMenuActionViewItem(action, action.configurationActions, this.contextMenuService, { actionRunner: this.actionRunner, clazz: action.class });
const item = new DropdownMenuActionViewItem(action, action.configurationActions, this.contextMenuService, { actionRunner: this.actionRunner, classNames: action.class });
data.toDispose.add(item);
return item;
......
......@@ -158,7 +158,7 @@ export class CommentNode extends Disposable {
{
actionViewItemProvider: action => this.actionViewItemProvider(action as Action),
actionRunner: this.actionRunner,
clazz: 'toolbar-toggle-pickReactions codicon codicon-reactions',
classNames: ['toolbar-toggle-pickReactions', 'codicon', 'codicon-reactions'],
anchorAlignmentProvider: () => AnchorAlignment.RIGHT
}
);
......@@ -267,7 +267,7 @@ export class CommentNode extends Disposable {
return this.actionViewItemProvider(action as Action);
},
actionRunner: this.actionRunner,
clazz: 'toolbar-toggle-pickReactions',
classNames: 'toolbar-toggle-pickReactions',
anchorAlignmentProvider: () => AnchorAlignment.RIGHT
}
);
......@@ -287,7 +287,7 @@ export class CommentNode extends Disposable {
{
actionViewItemProvider: action => this.actionViewItemProvider(action as Action),
actionRunner: this.actionRunner,
clazz: 'toolbar-toggle-pickReactions',
classNames: 'toolbar-toggle-pickReactions',
anchorAlignmentProvider: () => AnchorAlignment.RIGHT
}
);
......
......@@ -182,7 +182,7 @@ class FiltersDropdownMenuActionViewItem extends DropdownMenuActionViewItem {
contextMenuService,
{
actionRunner,
clazz: action.class,
classNames: action.class,
anchorAlignmentProvider: () => AnchorAlignment.RIGHT
}
);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册