Merge pull request #85814 from microsoft/joh/themeicons

Allow ThemeIcon for menu items
This commit is contained in:
Johannes Rieken 2019-11-29 16:48:21 +01:00 committed by GitHub
commit 614f3651cd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 140 additions and 126 deletions

View file

@ -31,6 +31,7 @@ import { IFileService } from 'vs/platform/files/common/files';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogs';
import { mnemonicButtonLabel } from 'vs/base/common/labels';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
const RUN_TEXTMATE_IN_WORKER = false;
@ -1089,8 +1090,8 @@ export class CodeWindow extends Disposable implements ICodeWindow {
private createTouchBarGroupSegments(items: ISerializableCommandAction[] = []): ITouchBarSegment[] {
const segments: ITouchBarSegment[] = items.map(item => {
let icon: NativeImage | undefined;
if (item.iconLocation && item.iconLocation?.dark?.scheme === 'file') {
icon = nativeImage.createFromPath(URI.revive(item.iconLocation.dark).fsPath);
if (item.icon && !ThemeIcon.isThemeIcon(item.icon) && item.icon?.dark?.scheme === 'file') {
icon = nativeImage.createFromPath(URI.revive(item.icon.dark).fsPath);
if (icon.isEmpty()) {
icon = undefined;
}

View file

@ -16,6 +16,7 @@ import { ICommandAction, IMenu, IMenuActionOptions, MenuItemAction, SubmenuItemA
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';
// The alternative key on all platforms is alt. On windows we also support shift as an alternative key #44136
class AlternativeKeyEmitter extends Emitter<boolean> {
@ -147,7 +148,7 @@ export class MenuEntryActionViewItem extends ActionViewItem {
@INotificationService protected _notificationService: INotificationService,
@IContextMenuService _contextMenuService: IContextMenuService
) {
super(undefined, _action, { icon: !!(_action.class || _action.item.iconLocation || _action.item.iconClassName), label: !_action.class && !_action.item.iconLocation && !_action.item.iconClassName });
super(undefined, _action, { icon: !!(_action.class || _action.item.icon), label: !_action.class && !_action.item.icon });
this._altKey = AlternativeKeyEmitter.getInstance(_contextMenuService);
}
@ -236,35 +237,32 @@ export class MenuEntryActionViewItem extends ActionViewItem {
_updateItemClass(item: ICommandAction): void {
this._itemClassDispose.value = undefined;
// icon class
if (item.iconClassName) {
let iconClass = item.iconClassName;
if (this.label) {
addClasses(this.label, 'codicon', iconClass);
if (ThemeIcon.isThemeIcon(item.icon)) {
// theme icons
const iconClass = ThemeIcon.asClassName(item.icon);
if (this.label && iconClass) {
addClasses(this.label, iconClass);
this._itemClassDispose.value = toDisposable(() => {
if (this.label) {
removeClasses(this.label, 'codicon', iconClass);
removeClasses(this.label, iconClass);
}
});
}
}
// icon path
else if (item.iconLocation) {
} else if (item.icon) {
// icon path
let iconClass: string;
if (item.iconLocation?.dark?.scheme) {
if (item.icon?.dark?.scheme) {
const iconPathMapKey = item.iconLocation.dark.toString();
const iconPathMapKey = item.icon.dark.toString();
if (MenuEntryActionViewItem.ICON_PATH_TO_CSS_RULES.has(iconPathMapKey)) {
iconClass = MenuEntryActionViewItem.ICON_PATH_TO_CSS_RULES.get(iconPathMapKey)!;
} else {
iconClass = ids.nextId();
createCSSRule(`.icon.${iconClass}`, `background-image: ${asCSSUrl(item.iconLocation.light || item.iconLocation.dark)}`);
createCSSRule(`.vs-dark .icon.${iconClass}, .hc-black .icon.${iconClass}`, `background-image: ${asCSSUrl(item.iconLocation.dark)}`);
createCSSRule(`.icon.${iconClass}`, `background-image: ${asCSSUrl(item.icon.light || item.icon.dark)}`);
createCSSRule(`.vs-dark .icon.${iconClass}, .hc-black .icon.${iconClass}`, `background-image: ${asCSSUrl(item.icon.dark)}`);
MenuEntryActionViewItem.ICON_PATH_TO_CSS_RULES.set(iconPathMapKey, iconClass);
}
@ -277,11 +275,7 @@ export class MenuEntryActionViewItem extends ActionViewItem {
}
});
}
}
}
}
}

View file

@ -12,6 +12,7 @@ import { ICommandService, ICommandHandler, CommandsRegistry } from 'vs/platform/
import { IDisposable } from 'vs/base/common/lifecycle';
import { Event, Emitter } from 'vs/base/common/event';
import { URI, UriComponents } from 'vs/base/common/uri';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
export interface ILocalizedString {
value: string;
@ -22,8 +23,7 @@ export interface ICommandAction {
id: string;
title: string | ILocalizedString;
category?: string | ILocalizedString;
iconClassName?: string;
iconLocation?: { dark?: URI; light?: URI; };
icon?: { dark?: URI; light?: URI; } | ThemeIcon;
precondition?: ContextKeyExpr;
toggled?: ContextKeyExpr;
}

View file

@ -26,6 +26,42 @@ export interface ThemeIcon {
readonly id: string;
}
export namespace ThemeIcon {
export function isThemeIcon(obj: any): obj is ThemeIcon {
return obj && typeof obj === 'object' && typeof (<ThemeIcon>obj).id === 'string';
}
const _regexFromString = /^\$\(([a-z.]+\/)?([a-z-~]+)\)$/i;
export function fromString(str: string): ThemeIcon | undefined {
const match = _regexFromString.exec(str);
if (!match) {
return undefined;
}
let [, owner, name] = match;
if (!owner) {
owner = `codicon/`;
}
return { id: owner + name };
}
const _regexAsClassName = /^(codicon\/)?([a-z-]+)(~[a-z]+)?$/i;
export function asClassName(icon: ThemeIcon): string | undefined {
// todo@martin,joh -> this should go into the ThemeService
const match = _regexAsClassName.exec(icon.id);
if (!match) {
return undefined;
}
let [, , name, modifier] = match;
let className = `codicon codicon-${name}`;
if (modifier) {
className += ` ${modifier.substr(1)}`;
}
return className;
}
}
export const FileThemeIcon = { id: 'file' };
export const FolderThemeIcon = { id: 'folder' };

View file

@ -13,6 +13,7 @@ import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { MenuId, MenuRegistry, ILocalizedString, IMenuItem } from 'vs/platform/actions/common/actions';
import { URI } from 'vs/base/common/uri';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
namespace schema {
@ -347,10 +348,14 @@ commandsExtensionPoint.setHandler(extensions => {
const { icon, enablement, category, title, command } = userFriendlyCommand;
let absoluteIcon: { dark: URI; light?: URI; } | undefined;
let absoluteIcon: { dark: URI; light?: URI; } | ThemeIcon | undefined;
if (icon) {
if (typeof icon === 'string') {
absoluteIcon = { dark: resources.joinPath(extension.description.extensionLocation, icon) };
if (extension.description.enableProposedApi) {
absoluteIcon = ThemeIcon.fromString(icon) || { dark: resources.joinPath(extension.description.extensionLocation, icon) };
} else {
absoluteIcon = { dark: resources.joinPath(extension.description.extensionLocation, icon) };
}
} else {
absoluteIcon = {
dark: resources.joinPath(extension.description.extensionLocation, icon.dark),
@ -367,7 +372,7 @@ commandsExtensionPoint.setHandler(extensions => {
title,
category,
precondition: ContextKeyExpr.deserialize(enablement),
iconLocation: absoluteIcon
icon: absoluteIcon
});
_commandRegistrations.add(registration);
}

View file

@ -54,6 +54,7 @@ import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { withNullAsUndefined } from 'vs/base/common/types';
import { IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
import { EditorAutoSave } from 'vs/workbench/browser/parts/editor/editorAutoSave';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
// Register String Editor
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
@ -420,12 +421,12 @@ editorCommands.setup();
// Touch Bar
if (isMacintosh) {
MenuRegistry.appendMenuItem(MenuId.TouchBarContext, {
command: { id: NavigateBackwardsAction.ID, title: NavigateBackwardsAction.LABEL, iconLocation: { dark: URI.parse(require.toUrl('vs/workbench/browser/parts/editor/media/back-tb.png')) } },
command: { id: NavigateBackwardsAction.ID, title: NavigateBackwardsAction.LABEL, icon: { dark: URI.parse(require.toUrl('vs/workbench/browser/parts/editor/media/back-tb.png')) } },
group: 'navigation'
});
MenuRegistry.appendMenuItem(MenuId.TouchBarContext, {
command: { id: NavigateForwardAction.ID, title: NavigateForwardAction.LABEL, iconLocation: { dark: URI.parse(require.toUrl('vs/workbench/browser/parts/editor/media/forward-tb.png')) } },
command: { id: NavigateForwardAction.ID, title: NavigateForwardAction.LABEL, icon: { dark: URI.parse(require.toUrl('vs/workbench/browser/parts/editor/media/forward-tb.png')) } },
group: 'navigation'
});
}
@ -455,18 +456,15 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: editorCommands.
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: editorCommands.CLOSE_EDITORS_IN_GROUP_COMMAND_ID, title: nls.localize('closeAll', "Close All") }, group: '5_close', order: 10, when: ContextKeyExpr.has('config.workbench.editor.showTabs') });
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: editorCommands.CLOSE_SAVED_EDITORS_COMMAND_ID, title: nls.localize('closeAllSaved', "Close Saved") }, group: '5_close', order: 20, when: ContextKeyExpr.has('config.workbench.editor.showTabs') });
interface IEditorToolItem { id: string; title: string; iconDark?: URI; iconLight?: URI; iconClassName?: string; }
interface IEditorToolItem { id: string; title: string; icon?: { dark?: URI; light?: URI; } | ThemeIcon; }
function appendEditorToolItem(primary: IEditorToolItem, when: ContextKeyExpr | undefined, order: number, alternative?: IEditorToolItem): void {
function appendEditorToolItem(primary: IEditorToolItem, when: ContextKeyExpr | undefined, order: number, alternative?: IEditorToolItem, precondition?: ContextKeyExpr | undefined): void {
const item: IMenuItem = {
command: {
id: primary.id,
title: primary.title,
iconClassName: primary.iconClassName,
iconLocation: {
dark: primary.iconDark,
light: primary.iconLight
}
icon: primary.icon,
precondition
},
group: 'navigation',
when,
@ -477,11 +475,7 @@ function appendEditorToolItem(primary: IEditorToolItem, when: ContextKeyExpr | u
item.alt = {
id: alternative.id,
title: alternative.title,
iconClassName: alternative.iconClassName,
iconLocation: {
dark: alternative.iconDark,
light: alternative.iconLight
}
icon: alternative.icon
};
}
@ -493,14 +487,14 @@ appendEditorToolItem(
{
id: SplitEditorAction.ID,
title: nls.localize('splitEditorRight', "Split Editor Right"),
iconClassName: 'codicon-split-horizontal'
icon: { id: 'codicon/split-horizontal' }
},
ContextKeyExpr.not('splitEditorsVertically'),
100000, // towards the end
{
id: editorCommands.SPLIT_EDITOR_DOWN,
title: nls.localize('splitEditorDown', "Split Editor Down"),
iconClassName: 'codicon-split-vertical'
icon: { id: 'codicon/split-vertical' }
}
);
@ -508,14 +502,14 @@ appendEditorToolItem(
{
id: SplitEditorAction.ID,
title: nls.localize('splitEditorDown', "Split Editor Down"),
iconClassName: 'codicon-split-vertical'
icon: { id: 'codicon/split-vertical' }
},
ContextKeyExpr.has('splitEditorsVertically'),
100000, // towards the end
{
id: editorCommands.SPLIT_EDITOR_RIGHT,
title: nls.localize('splitEditorRight', "Split Editor Right"),
iconClassName: 'codicon-split-horizontal'
icon: { id: 'codicon/split-horizontal' }
}
);
@ -524,14 +518,14 @@ appendEditorToolItem(
{
id: editorCommands.CLOSE_EDITOR_COMMAND_ID,
title: nls.localize('close', "Close"),
iconClassName: 'codicon-close'
icon: { id: 'codicon/close' }
},
ContextKeyExpr.and(ContextKeyExpr.not('config.workbench.editor.showTabs'), ContextKeyExpr.not('groupActiveEditorDirty')),
1000000, // towards the far end
{
id: editorCommands.CLOSE_EDITORS_IN_GROUP_COMMAND_ID,
title: nls.localize('closeAll', "Close All"),
iconClassName: 'codicon-close-all'
icon: { id: 'codicon/close-all' }
}
);
@ -539,14 +533,14 @@ appendEditorToolItem(
{
id: editorCommands.CLOSE_EDITOR_COMMAND_ID,
title: nls.localize('close', "Close"),
iconClassName: 'codicon-close-dirty'
icon: { id: 'codicon/close-dirty' }
},
ContextKeyExpr.and(ContextKeyExpr.not('config.workbench.editor.showTabs'), ContextKeyExpr.has('groupActiveEditorDirty')),
1000000, // towards the far end
{
id: editorCommands.CLOSE_EDITORS_IN_GROUP_COMMAND_ID,
title: nls.localize('closeAll', "Close All"),
iconClassName: 'codicon-close-all'
icon: { id: 'codicon/close-all' }
}
);
@ -555,7 +549,7 @@ appendEditorToolItem(
{
id: editorCommands.GOTO_PREVIOUS_CHANGE,
title: nls.localize('navigate.prev.label', "Previous Change"),
iconClassName: 'codicon-arrow-up'
icon: { id: 'codicon/arrow-up' }
},
TextCompareEditorActiveContext,
10
@ -566,7 +560,7 @@ appendEditorToolItem(
{
id: editorCommands.GOTO_NEXT_CHANGE,
title: nls.localize('navigate.next.label', "Next Change"),
iconClassName: 'codicon-arrow-down'
icon: { id: 'codicon/arrow-down' }
},
TextCompareEditorActiveContext,
11
@ -577,7 +571,7 @@ appendEditorToolItem(
{
id: editorCommands.TOGGLE_DIFF_IGNORE_TRIM_WHITESPACE,
title: nls.localize('ignoreTrimWhitespace.label', "Ignore Leading/Trailing Whitespace Differences"),
iconClassName: 'codicon-whitespace'
icon: { id: 'codicon/whitespace' }
},
ContextKeyExpr.and(TextCompareEditorActiveContext, ContextKeyExpr.notEquals('config.diffEditor.ignoreTrimWhitespace', true)),
20
@ -588,7 +582,7 @@ appendEditorToolItem(
{
id: editorCommands.TOGGLE_DIFF_IGNORE_TRIM_WHITESPACE,
title: nls.localize('showTrimWhitespace.label', "Show Leading/Trailing Whitespace Differences"),
iconClassName: 'codicon-whitespace disabled'
icon: { id: 'codicon/whitespace~disabled' }
},
ContextKeyExpr.and(TextCompareEditorActiveContext, ContextKeyExpr.notEquals('config.diffEditor.ignoreTrimWhitespace', false)),
20

View file

@ -26,7 +26,7 @@ import { ResourceLabels, IResourceLabel } from 'vs/workbench/browser/labels';
import { ActionBar, IActionViewItemProvider, ActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
import { URI } from 'vs/base/common/uri';
import { dirname, basename } from 'vs/base/common/resources';
import { LIGHT, FileThemeIcon, FolderThemeIcon, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { LIGHT, FileThemeIcon, FolderThemeIcon, registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService';
import { FileKind } from 'vs/platform/files/common/files';
import { WorkbenchAsyncDataTree, TreeResourceNavigator2 } from 'vs/platform/list/browser/listService';
import { ViewletPane, IViewletPaneOptions } from 'vs/workbench/browser/parts/views/paneViewlet';
@ -40,7 +40,7 @@ import { IListVirtualDelegate, IIdentityProvider } from 'vs/base/browser/ui/list
import { ITreeRenderer, ITreeNode, IAsyncDataSource, ITreeContextMenuEvent } from 'vs/base/browser/ui/tree/tree';
import { FuzzyScore, createMatches } from 'vs/base/common/filters';
import { CollapseAllAction } from 'vs/base/browser/ui/tree/treeDefaults';
import { escape, isFalsyOrWhitespace } from 'vs/base/common/strings';
import { isFalsyOrWhitespace } from 'vs/base/common/strings';
import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
export class CustomTreeViewPane extends ViewletPane {
@ -780,7 +780,7 @@ class TreeRenderer extends Disposable implements ITreeRenderer<ITreeItem, FuzzyS
// reset
templateData.actionBar.clear();
if (resource || node.themeIcon) {
if (resource || this.isFileKindThemeIcon(node.themeIcon)) {
const fileDecorations = this.configurationService.getValue<{ colors: boolean, badges: boolean }>('explorer.decorations');
templateData.resourceLabel.setResource({ name: label, description, resource: resource ? resource : URI.parse('missing:_icon_resource') }, { fileKind: this.getFileKind(node), title, hideIcon: !!iconUrl, fileDecorations, extraClasses: ['custom-view-tree-node-item-resourceLabel'], matches: matches ? matches : createMatches(element.filterData) });
} else {
@ -788,25 +788,19 @@ class TreeRenderer extends Disposable implements ITreeRenderer<ITreeItem, FuzzyS
}
templateData.icon.title = title ? title : '';
DOM.toggleClass(templateData.icon, 'custom-view-tree-node-item-icon', !!iconUrl);
let codicon: string | undefined;
if (iconUrl?.scheme === 'vscode-icon' && iconUrl?.authority === 'codicon') {
codicon = `codicon-${escape(iconUrl.path.substr(1))}`;
}
if (iconUrl) {
templateData.icon.className = 'custom-view-tree-node-item-icon';
templateData.icon.style.backgroundImage = DOM.asCSSUrl(iconUrl);
DOM.toggleClass(templateData.icon, 'codicon', !!codicon);
templateData.icon.classList.forEach((cls, i, list) => {
if (cls !== codicon && cls.indexOf('codicon-') === 0) {
list.remove(cls);
} else {
let iconClass: string | undefined;
if (node.themeIcon && !this.isFileKindThemeIcon(node.themeIcon)) {
iconClass = ThemeIcon.asClassName(node.themeIcon);
}
});
if (codicon) {
DOM.addClass(templateData.icon, codicon);
templateData.icon.className = iconClass ? `custom-view-tree-node-item-icon ${iconClass}` : '';
}
templateData.icon.style.backgroundImage = iconUrl && !codicon ? DOM.asCSSUrl(iconUrl) : '';
templateData.actionBar.context = <TreeViewItemHandleArg>{ $treeViewId: this.treeViewId, $treeItemHandle: node.handle };
templateData.actionBar.push(this.menus.getResourceActions(node), { icon: true, label: false });
if (this._actionRunner) {
@ -820,6 +814,14 @@ class TreeRenderer extends Disposable implements ITreeRenderer<ITreeItem, FuzzyS
DOM.toggleClass(container.parentElement!, 'align-icon-with-twisty', this.aligner.alignIconWithTwisty(treeItem));
}
private isFileKindThemeIcon(icon: ThemeIcon | undefined): boolean {
if (icon) {
return icon.id === FileThemeIcon.id || icon.id === FolderThemeIcon.id;
} else {
return false;
}
}
private getFileKind(node: ITreeItem): FileKind {
if (node.themeIcon) {
switch (node.themeIcon.id) {

View file

@ -279,7 +279,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, {
command: {
id: TOGGLE_WORD_WRAP_ID,
title: nls.localize('unwrapMinified', "Disable wrapping for this file"),
iconLocation: {
icon: {
dark: WORD_WRAP_DARK_ICON,
light: WORD_WRAP_LIGHT_ICON
}
@ -296,7 +296,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, {
command: {
id: TOGGLE_WORD_WRAP_ID,
title: nls.localize('wrapMinified', "Enable wrapping for this file"),
iconLocation: {
icon: {
dark: WORD_WRAP_DARK_ICON,
light: WORD_WRAP_LIGHT_ICON
}

View file

@ -49,6 +49,7 @@ import { ClearReplAction, Repl } from 'vs/workbench/contrib/debug/browser/repl';
import { DebugContentProvider } from 'vs/workbench/contrib/debug/common/debugContentProvider';
import { DebugCallStackContribution } from 'vs/workbench/contrib/debug/browser/debugCallStackContribution';
import { StartView } from 'vs/workbench/contrib/debug/browser/startView';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
class OpenDebugViewletAction extends ShowViewletAction {
public static readonly ID = VIEWLET_ID;
@ -284,7 +285,7 @@ Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).regi
// Debug toolbar
const registerDebugToolBarItem = (id: string, title: string, order: number, iconClassName?: string, iconLightUri?: URI, iconDarkUri?: URI, when?: ContextKeyExpr, precondition?: ContextKeyExpr) => {
const registerDebugToolBarItem = (id: string, title: string, order: number, icon: { light?: URI, dark?: URI } | ThemeIcon, when?: ContextKeyExpr, precondition?: ContextKeyExpr) => {
MenuRegistry.appendMenuItem(MenuId.DebugToolBar, {
group: 'navigation',
when,
@ -292,26 +293,22 @@ const registerDebugToolBarItem = (id: string, title: string, order: number, icon
command: {
id,
title,
iconClassName,
iconLocation: {
light: iconLightUri,
dark: iconDarkUri
},
icon,
precondition
}
});
};
registerDebugToolBarItem(CONTINUE_ID, CONTINUE_LABEL, 10, 'codicon-debug-continue', undefined, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
registerDebugToolBarItem(PAUSE_ID, PAUSE_LABEL, 10, 'codicon-debug-pause', undefined, undefined, CONTEXT_DEBUG_STATE.notEqualsTo('stopped'));
registerDebugToolBarItem(STOP_ID, STOP_LABEL, 70, 'codicon-debug-stop', undefined, undefined, CONTEXT_FOCUSED_SESSION_IS_ATTACH.toNegated());
registerDebugToolBarItem(DISCONNECT_ID, DISCONNECT_LABEL, 70, 'codicon-debug-disconnect', undefined, undefined, CONTEXT_FOCUSED_SESSION_IS_ATTACH);
registerDebugToolBarItem(STEP_OVER_ID, STEP_OVER_LABEL, 20, 'codicon-debug-step-over', undefined, undefined, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
registerDebugToolBarItem(STEP_INTO_ID, STEP_INTO_LABEL, 30, 'codicon-debug-step-into', undefined, undefined, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
registerDebugToolBarItem(STEP_OUT_ID, STEP_OUT_LABEL, 40, 'codicon-debug-step-out', undefined, undefined, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
registerDebugToolBarItem(RESTART_SESSION_ID, RESTART_LABEL, 60, 'codicon-debug-restart', undefined, undefined);
registerDebugToolBarItem(STEP_BACK_ID, nls.localize('stepBackDebug', "Step Back"), 50, 'codicon-debug-step-back', undefined, undefined, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
registerDebugToolBarItem(REVERSE_CONTINUE_ID, nls.localize('reverseContinue', "Reverse"), 60, 'codicon-debug-reverse-continue', undefined, undefined, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
registerDebugToolBarItem(CONTINUE_ID, CONTINUE_LABEL, 10, { id: 'codicon/debug-continue' }, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
registerDebugToolBarItem(PAUSE_ID, PAUSE_LABEL, 10, { id: 'codicon/debug-pause' }, CONTEXT_DEBUG_STATE.notEqualsTo('stopped'));
registerDebugToolBarItem(STOP_ID, STOP_LABEL, 70, { id: 'codicon/debug-stop' }, CONTEXT_FOCUSED_SESSION_IS_ATTACH.toNegated());
registerDebugToolBarItem(DISCONNECT_ID, DISCONNECT_LABEL, 70, { id: 'codicon/debug-disconnect' }, CONTEXT_FOCUSED_SESSION_IS_ATTACH);
registerDebugToolBarItem(STEP_OVER_ID, STEP_OVER_LABEL, 20, { id: 'codicon/debug-step-over' }, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
registerDebugToolBarItem(STEP_INTO_ID, STEP_INTO_LABEL, 30, { id: 'codicon/debug-step-into' }, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
registerDebugToolBarItem(STEP_OUT_ID, STEP_OUT_LABEL, 40, { id: 'codicon/debug-step-out' }, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
registerDebugToolBarItem(RESTART_SESSION_ID, RESTART_LABEL, 60, { id: 'codicon/debug-restart' });
registerDebugToolBarItem(STEP_BACK_ID, nls.localize('stepBackDebug', "Step Back"), 50, { id: 'codicon/debug-step-back' }, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
registerDebugToolBarItem(REVERSE_CONTINUE_ID, nls.localize('reverseContinue', "Reverse"), 60, { id: 'codicon/debug-reverse-continue' }, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
// Debug callstack context menu
const registerDebugCallstackItem = (id: string, title: string, order: number, when?: ContextKeyExpr, precondition?: ContextKeyExpr, group = 'navigation') => {
@ -556,7 +553,7 @@ if (isMacintosh) {
command: {
id,
title,
iconLocation: { dark: iconUri }
icon: { dark: iconUri }
},
when,
group: '9_debug',

View file

@ -102,7 +102,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, {
command: {
id: DebugExtensionHostAction.ID,
title: DebugExtensionHostAction.LABEL,
iconLocation: {
icon: {
dark: URI.parse(registerAndGetAmdImageURL(`vs/workbench/contrib/extensions/browser/media/start-dark.svg`)),
light: URI.parse(registerAndGetAmdImageURL(`vs/workbench/contrib/extensions/browser/media/start-light.svg`)),
}
@ -115,7 +115,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, {
command: {
id: StartExtensionHostProfileAction.ID,
title: StartExtensionHostProfileAction.LABEL,
iconLocation: {
icon: {
dark: URI.parse(registerAndGetAmdImageURL(`vs/workbench/contrib/extensions/browser/media/profile-start-dark.svg`)),
light: URI.parse(registerAndGetAmdImageURL(`vs/workbench/contrib/extensions/browser/media/profile-start-light.svg`)),
}
@ -128,7 +128,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, {
command: {
id: StopExtensionHostProfileAction.ID,
title: StopExtensionHostProfileAction.LABEL,
iconLocation: {
icon: {
dark: URI.parse(registerAndGetAmdImageURL(`vs/workbench/contrib/extensions/browser/media/profile-stop-dark.svg`)),
light: URI.parse(registerAndGetAmdImageURL(`vs/workbench/contrib/extensions/browser/media/profile-stop-light.svg`)),
}
@ -141,7 +141,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, {
command: {
id: SaveExtensionHostProfileAction.ID,
title: SaveExtensionHostProfileAction.LABEL,
iconLocation: {
icon: {
dark: URI.parse(registerAndGetAmdImageURL(`vs/workbench/contrib/extensions/browser/media/save-dark.svg`)),
light: URI.parse(registerAndGetAmdImageURL(`vs/workbench/contrib/extensions/browser/media/save-light.svg`)),
},

View file

@ -27,6 +27,7 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation
import { OpenFileFolderAction, OpenFileAction, OpenFolderAction, OpenWorkspaceAction } from 'vs/workbench/browser/actions/workspaceActions';
import { ActiveEditorIsReadonlyContext, DirtyWorkingCopiesContext, ActiveEditorContext } from 'vs/workbench/common/editor';
import { SidebarFocusContext } from 'vs/workbench/common/viewlet';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
// Contribute Global Actions
const category = { value: nls.localize('filesCategory', "File"), original: 'File' };
@ -179,17 +180,17 @@ export function appendEditorTitleContextMenuItem(id: string, title: string, when
}
// Editor Title Menu for Conflict Resolution
appendSaveConflictEditorTitleAction('workbench.files.action.acceptLocalChanges', nls.localize('acceptLocalChanges', "Use your changes and overwrite file contents"), 'codicon-check', -10, acceptLocalChangesCommand);
appendSaveConflictEditorTitleAction('workbench.files.action.revertLocalChanges', nls.localize('revertLocalChanges', "Discard your changes and revert to file contents"), 'codicon-discard', -9, revertLocalChangesCommand);
appendSaveConflictEditorTitleAction('workbench.files.action.acceptLocalChanges', nls.localize('acceptLocalChanges', "Use your changes and overwrite file contents"), { id: 'codicon/check' }, -10, acceptLocalChangesCommand);
appendSaveConflictEditorTitleAction('workbench.files.action.revertLocalChanges', nls.localize('revertLocalChanges', "Discard your changes and revert to file contents"), { id: 'codicon/discard' }, -9, revertLocalChangesCommand);
function appendSaveConflictEditorTitleAction(id: string, title: string, iconClassName: string, order: number, command: ICommandHandler): void {
function appendSaveConflictEditorTitleAction(id: string, title: string, icon: ThemeIcon, order: number, command: ICommandHandler): void {
// Command
CommandsRegistry.registerCommand(id, command);
// Action
MenuRegistry.appendMenuItem(MenuId.EditorTitle, {
command: { id, title, iconClassName },
command: { id, title, icon },
when: ContextKeyExpr.equals(CONFLICT_RESOLUTION_CONTEXT, true),
group: 'navigation',
order

View file

@ -381,7 +381,7 @@ class PreferencesActionsContribution extends Disposable implements IWorkbenchCon
command: {
id: OpenGlobalKeybindingsAction.ID,
title: OpenGlobalKeybindingsAction.LABEL,
iconClassName: 'codicon-go-to-file'
icon: { id: 'codicon/go-to-file' }
},
when: ResourceContextKey.Resource.isEqualTo(environmentService.keybindingsResource.toString()),
group: 'navigation',
@ -394,7 +394,7 @@ class PreferencesActionsContribution extends Disposable implements IWorkbenchCon
command: {
id: commandId,
title: OpenSettings2Action.LABEL,
iconClassName: 'codicon-go-to-file'
icon: { id: 'codicon/go-to-file' }
},
when: ResourceContextKey.Resource.isEqualTo(environmentService.settingsResource.toString()),
group: 'navigation',
@ -432,7 +432,7 @@ class PreferencesActionsContribution extends Disposable implements IWorkbenchCon
command: {
id: commandId,
title: OpenSettings2Action.LABEL,
iconClassName: 'codicon-go-to-file'
icon: { id: 'codicon/go-to-file' }
},
when: ContextKeyExpr.and(ResourceContextKey.Resource.isEqualTo(this.preferencesService.workspaceSettingsResource!.toString()), WorkbenchStateContext.isEqualTo('workspace')),
group: 'navigation',
@ -457,7 +457,7 @@ class PreferencesActionsContribution extends Disposable implements IWorkbenchCon
command: {
id: commandId,
title: OpenSettings2Action.LABEL,
iconClassName: 'codicon-go-to-file'
icon: { id: 'codicon/go-to-file' }
},
when: ContextKeyExpr.and(ResourceContextKey.Resource.isEqualTo(this.preferencesService.getFolderSettingsResource(folder.uri)!.toString())),
group: 'navigation',
@ -521,7 +521,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, {
command: {
id: OpenGlobalKeybindingsFileAction.ID,
title: OpenGlobalKeybindingsFileAction.LABEL,
iconClassName: 'codicon-go-to-file'
icon: { id: 'codicon/go-to-file' }
},
when: ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR),
group: 'navigation',
@ -802,7 +802,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, {
command: {
id: SETTINGS_EDITOR_COMMAND_SWITCH_TO_JSON,
title: nls.localize('openSettingsJson', "Open Settings (JSON)"),
iconClassName: 'codicon-go-to-file'
icon: { id: 'codicon/go-to-file' }
},
group: 'navigation',
order: 1,

View file

@ -684,11 +684,7 @@ MenuRegistry.appendMenuItem(MenuId.TunnelTitle, ({
command: {
id: ForwardPortAction.ID,
title: ForwardPortAction.LABEL,
iconClassName: 'codicon-plus',
iconLocation: {
dark: undefined,
light: undefined
}
icon: { id: 'codicon/plus' }
}
}));
MenuRegistry.appendMenuItem(MenuId.TunnelContext, ({
@ -742,11 +738,7 @@ MenuRegistry.appendMenuItem(MenuId.TunnelInline, ({
command: {
id: OpenPortInBrowserAction.ID,
title: OpenPortInBrowserAction.LABEL,
iconClassName: 'codicon-globe',
iconLocation: {
dark: undefined,
light: undefined
}
icon: { id: 'codicon/globe' }
},
when: ContextKeyExpr.or(TunnelTypeContextKey.isEqualTo(TunnelType.Forwarded), TunnelTypeContextKey.isEqualTo(TunnelType.Published))
}));
@ -755,11 +747,7 @@ MenuRegistry.appendMenuItem(MenuId.TunnelInline, ({
command: {
id: ForwardPortAction.ID,
title: ForwardPortAction.LABEL,
iconClassName: 'codicon-plus',
iconLocation: {
dark: undefined,
light: undefined
}
icon: { id: 'codicon/plus' }
},
when: ContextKeyExpr.or(TunnelTypeContextKey.isEqualTo(TunnelType.Candidate), TunnelTypeContextKey.isEqualTo(TunnelType.Published))
}));
@ -768,11 +756,7 @@ MenuRegistry.appendMenuItem(MenuId.TunnelInline, ({
command: {
id: ClosePortAction.ID,
title: ClosePortAction.LABEL,
iconClassName: 'codicon-x',
iconLocation: {
dark: undefined,
light: undefined
}
icon: { id: 'codicon/x' }
},
when: TunnelCloseableContextKey
}));

View file

@ -371,7 +371,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
command: {
id: continueSyncCommandId,
title: localize('continue sync', "Sync: Continue"),
iconLocation: {
icon: {
light: SYNC_PUSH_LIGHT_ICON_URI,
dark: SYNC_PUSH_DARK_ICON_URI
}

View file

@ -8,7 +8,7 @@ import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileE
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { join } from 'vs/base/common/path';
import * as resources from 'vs/base/common/resources';
import { URI, UriComponents } from 'vs/base/common/uri';
import { URI } from 'vs/base/common/uri';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
import { IEditorInputWithOptions, CloseDirection, IEditorIdentifier, IUntitledTextResourceInput, IResourceDiffInput, IResourceSideBySideInput, IEditorInput, IEditor, IEditorCloseEvent, IEditorPartOptions, IRevertOptions } from 'vs/workbench/common/editor';
@ -1391,7 +1391,7 @@ export class TestElectronService implements IElectronService {
async setRepresentedFilename(path: string): Promise<void> { }
async setDocumentEdited(edited: boolean): Promise<void> { }
async openExternal(url: string): Promise<boolean> { return false; }
async updateTouchBar(items: { id: string; title: string | { value: string; original: string; }; category?: string | { value: string; original: string; } | undefined; iconLocation?: { dark?: UriComponents; light?: { readonly scheme: string; readonly authority: string; readonly path: string; readonly query: string; readonly fragment: string; readonly fsPath: string; with: {}; toString: {}; toJSON: {}; } | undefined; } | undefined; precondition?: { getType: {}; equals: {}; evaluate: {}; serialize: {}; keys: {}; map: {}; negate: {}; } | undefined; toggled?: { getType: {}; equals: {}; evaluate: {}; serialize: {}; keys: {}; map: {}; negate: {}; } | undefined; }[][]): Promise<void> { }
async updateTouchBar(): Promise<void> { }
async newWindowTab(): Promise<void> { }
async showPreviousWindowTab(): Promise<void> { }
async showNextWindowTab(): Promise<void> { }