mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 13:00:58 +00:00
Merge pull request #85814 from microsoft/joh/themeicons
Allow ThemeIcon for menu items
This commit is contained in:
commit
614f3651cd
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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' };
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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`)),
|
||||
},
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}));
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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> { }
|
||||
|
|
Loading…
Reference in a new issue