Merge from vscode 731f9c25632dbbf01ee3a7892ad9d2791fe0260c

This commit is contained in:
ADS Merger
2020-07-24 05:27:34 +00:00
parent eccf3cf5fe
commit d965d4aef3
145 changed files with 3072 additions and 1550 deletions

View File

@@ -5,8 +5,7 @@
import { addClasses, createCSSRule, removeClasses, asCSSUrl } from 'vs/base/browser/dom';
import { domEvent } from 'vs/base/browser/event';
import { ActionViewItem, Separator } from 'vs/base/browser/ui/actionbar/actionbar';
import { IAction } from 'vs/base/common/actions';
import { IAction, Separator } from 'vs/base/common/actions';
import { Emitter } from 'vs/base/common/event';
import { IdGenerator } from 'vs/base/common/idGenerator';
import { IDisposable, toDisposable, MutableDisposable, DisposableStore, dispose } from 'vs/base/common/lifecycle';
@@ -17,6 +16,8 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView
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> {
@@ -125,19 +126,11 @@ export function fillInActions(groups: ReadonlyArray<[string, ReadonlyArray<MenuI
}
}
export function createActionViewItem(action: IAction, keybindingService: IKeybindingService, notificationService: INotificationService, contextMenuService: IContextMenuService): ActionViewItem | undefined {
if (action instanceof MenuItemAction) {
return new MenuEntryActionViewItem(action, keybindingService, notificationService, contextMenuService);
}
return undefined;
}
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());
@@ -165,7 +158,7 @@ export class MenuEntryActionViewItem extends ActionViewItem {
this._altKey.suppressAltKeyUp();
}
this.actionRunner.run(this._commandAction)
this.actionRunner.run(this._commandAction, this._context)
.then(undefined, err => this._notificationService.error(err));
}
@@ -236,7 +229,7 @@ export class MenuEntryActionViewItem extends ActionViewItem {
}
}
_updateItemClass(item: ICommandAction): void {
protected _updateItemClass(item: ICommandAction): void { // {{SQL CARBON EDIT}} make it overwritable
this._itemClassDispose.value = undefined;
const icon = this._commandAction.checked && (item.toggled as { icon?: Icon })?.icon ? (item.toggled as { icon: Icon }).icon : item.icon;
@@ -257,17 +250,17 @@ export class MenuEntryActionViewItem extends ActionViewItem {
// icon path
let iconClass: string;
if (icon?.dark?.scheme) {
if (icon.dark?.scheme) {
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) {
@@ -284,17 +277,34 @@ export class MenuEntryActionViewItem extends ActionViewItem {
}
}
// Need to subclass MenuEntryActionViewItem in order to respect
// the action context coming from any action bar, without breaking
// existing users
export class ContextAwareMenuEntryActionViewItem extends MenuEntryActionViewItem {
export class SubmenuEntryActionViewItem extends DropdownMenuActionViewItem {
onClick(event: MouseEvent): void {
event.preventDefault();
event.stopPropagation();
constructor(
action: SubmenuItemAction,
@INotificationService _notificationService: INotificationService,
@IContextMenuService _contextMenuService: IContextMenuService
) {
const classNames: string[] = [];
this.actionRunner.run(this._commandAction, this._context)
.then(undefined, err => this._notificationService.error(err));
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 });
}
}
@@ -323,7 +333,7 @@ export class LabeledMenuItemActionItem extends MenuEntryActionViewItem {
// Overwrite item class to ensure that we can pass in a CSS class that other items use
// Leverages the _defaultCSSClassToAdd property that's passed into the constructor
_updateItemClass(item: ICommandAction): void {
protected _updateItemClass(item: ICommandAction): void {
dispose(this._labeledItemClassDispose);
this._labeledItemClassDispose = undefined;
@@ -336,13 +346,13 @@ export class LabeledMenuItemActionItem extends MenuEntryActionViewItem {
if (item.icon?.dark?.scheme) {
const iconPathMapKey = item.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(`.codicon.${iconClass}`, `background-image: ${asCSSUrl(item.icon.light || item.icon.dark)}`);
createCSSRule(`.vs-dark .codicon.${iconClass}, .hc-black .codicon.${iconClass}`, `background-image: ${asCSSUrl(item.icon.dark)}`);
MenuEntryActionViewItem.ICON_PATH_TO_CSS_RULES.set(iconPathMapKey, iconClass);
ICON_PATH_TO_CSS_RULES.set(iconPathMapKey, iconClass);
}
if (this.label) {

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Action } from 'vs/base/common/actions';
import { Action, IAction, Separator, SubmenuAction } from 'vs/base/common/actions';
import { SyncDescriptor0, createSyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { IConstructorSignature2, createDecorator, BrandedService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindings, KeybindingsRegistry, IKeybindingRule } from 'vs/platform/keybinding/common/keybindingsRegistry';
@@ -47,6 +47,7 @@ export interface IMenuItem {
export interface ISubmenuItem {
title: string | ILocalizedString;
submenu: MenuId;
icon?: Icon;
when?: ContextKeyExpression;
group?: 'navigation' | string;
order?: number;
@@ -302,12 +303,35 @@ export class ExecuteCommandAction extends Action {
}
}
export class SubmenuItemAction extends Action {
export class SubmenuItemAction extends SubmenuAction {
readonly item: ISubmenuItem;
constructor(item: ISubmenuItem) {
typeof item.title === 'string' ? super('', item.title, 'submenu') : super('', item.title.value, 'submenu');
this.item = item;
constructor(
readonly item: ISubmenuItem,
menuService: IMenuService,
contextKeyService: IContextKeyService,
options?: IMenuActionOptions
) {
super(`submenuitem.${item.submenu.id}`, typeof item.title === 'string' ? item.title : item.title.value, () => {
const result: IAction[] = [];
const menu = menuService.createMenu(item.submenu, contextKeyService);
const groups = menu.getActions(options);
menu.dispose();
for (let group of groups) {
const [, actions] = group;
if (actions.length > 0) {
result.push(...actions);
result.push(new Separator());
}
}
if (result.length) {
result.pop(); // remove last separator
}
return result;
}, 'submenu');
}
}

View File

@@ -20,7 +20,7 @@ export class MenuService implements IMenuService {
}
createMenu(id: MenuId, contextKeyService: IContextKeyService): IMenu {
return new Menu(id, this._commandService, contextKeyService);
return new Menu(id, this._commandService, contextKeyService, this);
}
}
@@ -38,7 +38,8 @@ class Menu implements IMenu {
constructor(
private readonly _id: MenuId,
@ICommandService private readonly _commandService: ICommandService,
@IContextKeyService private readonly _contextKeyService: IContextKeyService
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
@IMenuService private readonly _menuService: IMenuService
) {
this._build();
@@ -114,7 +115,7 @@ class Menu implements IMenu {
if (this._contextKeyService.contextMatchesRules(item.when)) {
const action = isIMenuItem(item)
? new MenuItemAction(item.command, item.alt, options, this._contextKeyService, this._commandService)
: new SubmenuItemAction(item);
: new SubmenuItemAction(item, this._menuService, this._contextKeyService, options);
activeActions.push(action);
}