diff --git a/src/vs/platform/theme/common/themeService.ts b/src/vs/platform/theme/common/themeService.ts index 0ae9c30fe60..4ea8b3978e0 100644 --- a/src/vs/platform/theme/common/themeService.ts +++ b/src/vs/platform/theme/common/themeService.ts @@ -11,6 +11,7 @@ import { ColorIdentifier } from 'vs/platform/theme/common/colorRegistry'; import { Event, Emitter } from 'vs/base/common/event'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ColorScheme } from 'vs/platform/theme/common/theme'; +import { Codicon } from 'vs/base/common/codicons'; export const IThemeService = createDecorator('themeService'); @@ -18,6 +19,12 @@ export interface ThemeColor { id: string; } +export namespace ThemeColor { + export function isThemeColor(obj: any): obj is ThemeColor { + return obj && typeof obj === 'object' && typeof (obj).id === 'string'; + } +} + export function themeColorFromId(id: ColorIdentifier) { return { id }; } @@ -29,8 +36,8 @@ export interface ThemeIcon { } export namespace ThemeIcon { - export function isThemeIcon(obj: any): obj is ThemeIcon | { id: string } { - return obj && typeof obj === 'object' && typeof (obj).id === 'string'; + export function isThemeIcon(obj: any): obj is ThemeIcon { + return obj && typeof obj === 'object' && typeof (obj).id === 'string' && (typeof (obj).color === 'undefined' || ThemeColor.isThemeColor((obj).color)); } const _regexFromString = /^\$\(([a-z.]+\/)?([a-z-~]+)\)$/i; @@ -47,6 +54,15 @@ export namespace ThemeIcon { return { id: owner + name }; } + export function fromCodicon(codicon: Codicon): ThemeIcon { + return { id: codicon.id }; + } + + + export function isEqual(ti1: ThemeIcon, ti2: ThemeIcon): boolean { + return ti1.id === ti2.id && ti1.color?.id === ti2.color?.id; + } + const _regexAsClassName = /^(codicon\/)?([a-z-]+)(~[a-z]+)?$/i; export function asClassName(icon: ThemeIcon): string | undefined { @@ -62,6 +78,13 @@ export namespace ThemeIcon { } return className; } + + export function revive(icon: any): ThemeIcon | undefined { + if (ThemeIcon.isThemeIcon(icon)) { + return { id: icon.id, color: icon.color ? { id: icon.color.id } : undefined }; + } + return undefined; + } } export const FileThemeIcon = { id: 'file' }; diff --git a/src/vs/workbench/api/browser/mainThreadComments.ts b/src/vs/workbench/api/browser/mainThreadComments.ts index b6b32841290..80c9a3948c7 100644 --- a/src/vs/workbench/api/browser/mainThreadComments.ts +++ b/src/vs/workbench/api/browser/mainThreadComments.ts @@ -20,7 +20,9 @@ import { COMMENTS_VIEW_ID, COMMENTS_VIEW_TITLE } from 'vs/workbench/contrib/comm import { ViewContainer, IViewContainersRegistry, Extensions as ViewExtensions, ViewContainerLocation, IViewsRegistry, IViewsService, IViewDescriptorService } from 'vs/workbench/common/views'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; -import { Codicon } from 'vs/base/common/codicons'; +import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { localize } from 'vs/nls'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; export class MainThreadCommentThread implements modes.CommentThread { @@ -351,6 +353,9 @@ export class MainThreadCommentController { } } + +const commentsViewIcon = registerIcon('comments-view-icon', Codicon.commentDiscussion, localize('commentsViewIcon', 'View icon of the comments view.')); + @extHostNamedCustomer(MainContext.MainThreadComments) export class MainThreadComments extends Disposable implements MainThreadCommentsShape { private readonly _proxy: ExtHostCommentsShape; @@ -472,7 +477,7 @@ export class MainThreadComments extends Disposable implements MainThreadComments ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [COMMENTS_VIEW_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]), storageId: COMMENTS_VIEW_TITLE, hideIfEmpty: true, - icon: Codicon.commentDiscussion.classNames, + icon: ThemeIcon.fromCodicon(commentsViewIcon), order: 10, }, ViewContainerLocation.Panel); @@ -482,7 +487,7 @@ export class MainThreadComments extends Disposable implements MainThreadComments canToggleVisibility: false, ctorDescriptor: new SyncDescriptor(CommentsPanel), canMoveView: true, - containerIcon: Codicon.commentDiscussion.classNames, + containerIcon: ThemeIcon.fromCodicon(commentsViewIcon), focusCommand: { id: 'workbench.action.focusCommentsPanel' } diff --git a/src/vs/workbench/api/browser/viewsExtensionPoint.ts b/src/vs/workbench/api/browser/viewsExtensionPoint.ts index b46dc66f486..611a5b121c8 100644 --- a/src/vs/workbench/api/browser/viewsExtensionPoint.ts +++ b/src/vs/workbench/api/browser/viewsExtensionPoint.ts @@ -8,7 +8,7 @@ import { forEach } from 'vs/base/common/collections'; import { IJSONSchema } from 'vs/base/common/jsonSchema'; import * as resources from 'vs/base/common/resources'; import { ExtensionMessageCollector, ExtensionsRegistry, IExtensionPoint, IExtensionPointUser } from 'vs/workbench/services/extensions/common/extensionsRegistry'; -import { ViewContainer, IViewsRegistry, ITreeViewDescriptor, IViewContainersRegistry, Extensions as ViewContainerExtensions, TEST_VIEW_CONTAINER_ID, IViewDescriptor, ViewContainerLocation } from 'vs/workbench/common/views'; +import { ViewContainer, IViewsRegistry, ITreeViewDescriptor, IViewContainersRegistry, Extensions as ViewContainerExtensions, TEST_VIEW_CONTAINER_ID, IViewDescriptor, ViewContainerLocation, testViewIcon } from 'vs/workbench/common/views'; import { CustomTreeView, TreeViewPane } from 'vs/workbench/browser/parts/views/treeView'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { coalesce, } from 'vs/base/common/arrays'; @@ -30,7 +30,6 @@ import { IWorkbenchActionRegistry, Extensions as ActionExtensions, CATEGORIES } import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; -import { Codicon } from 'vs/base/common/codicons'; import { WebviewViewPane } from 'vs/workbench/contrib/webviewView/browser/webviewViewPane'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; @@ -321,7 +320,7 @@ class ViewsExtensionHandler implements IWorkbenchContribution { private registerTestViewContainer(): void { const title = localize('test', "Test"); - const icon = Codicon.beaker.classNames; + const icon = ThemeIcon.fromCodicon(testViewIcon); this.registerCustomViewContainer(TEST_VIEW_CONTAINER_ID, title, icon, TEST_VIEW_CONTAINER_ORDER, undefined, ViewContainerLocation.Sidebar); } @@ -357,8 +356,8 @@ class ViewsExtensionHandler implements IWorkbenchContribution { private registerCustomViewContainers(containers: IUserFriendlyViewsContainerDescriptor[], extension: IExtensionDescription, order: number, existingViewContainers: ViewContainer[], location: ViewContainerLocation): number { containers.forEach(descriptor => { const themeIcon = ThemeIcon.fromString(descriptor.icon); - const className = themeIcon ? ThemeIcon.asClassName(themeIcon) : undefined; - const icon = className || resources.joinPath(extension.extensionLocation, descriptor.icon); + + const icon = themeIcon || resources.joinPath(extension.extensionLocation, descriptor.icon); const id = `workbench.view.extension.${descriptor.id}`; const viewContainer = this.registerCustomViewContainer(id, descriptor.title, icon, order++, extension.identifier, location); @@ -378,7 +377,7 @@ class ViewsExtensionHandler implements IWorkbenchContribution { return order; } - private registerCustomViewContainer(id: string, title: string, icon: URI | string, order: number, extensionId: ExtensionIdentifier | undefined, location: ViewContainerLocation): ViewContainer { + private registerCustomViewContainer(id: string, title: string, icon: URI | ThemeIcon, order: number, extensionId: ExtensionIdentifier | undefined, location: ViewContainerLocation): ViewContainer { let viewContainer = this.viewContainersRegistry.get(id); if (!viewContainer) { diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 12a44078831..c7286d2c661 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -14,7 +14,7 @@ import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/bro import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IDisposable, toDisposable, DisposableStore, Disposable } from 'vs/base/common/lifecycle'; import { ToggleActivityBarVisibilityAction, ToggleMenuBarAction, ToggleSidebarPositionAction } from 'vs/workbench/browser/actions/layoutActions'; -import { IThemeService, IColorTheme } from 'vs/platform/theme/common/themeService'; +import { IThemeService, IColorTheme, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { ACTIVITY_BAR_BACKGROUND, ACTIVITY_BAR_BORDER, ACTIVITY_BAR_FOREGROUND, ACTIVITY_BAR_ACTIVE_BORDER, ACTIVITY_BAR_BADGE_BACKGROUND, ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_INACTIVE_FOREGROUND, ACTIVITY_BAR_ACTIVE_BACKGROUND, ACTIVITY_BAR_DRAG_AND_DROP_BORDER } from 'vs/workbench/common/theme'; import { contrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { CompositeBar, ICompositeBarItem, CompositeDragAndDrop } from 'vs/workbench/browser/parts/compositeBar'; @@ -25,7 +25,7 @@ import { URI, UriComponents } from 'vs/base/common/uri'; import { ToggleCompositePinnedAction, ICompositeBarColors, ActivityAction, ICompositeActivity } from 'vs/workbench/browser/parts/compositeBarActions'; import { IViewDescriptorService, ViewContainer, TEST_VIEW_CONTAINER_ID, IViewContainerModel, ViewContainerLocation, IViewsService } from 'vs/workbench/common/views'; import { IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { isUndefinedOrNull, assertIsDefined, isString } from 'vs/base/common/types'; +import { isUndefinedOrNull, assertIsDefined } from 'vs/base/common/types'; import { IActivityBarService } from 'vs/workbench/services/activityBar/browser/activityBarService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { Schemas } from 'vs/base/common/network'; @@ -47,7 +47,7 @@ interface IPlaceholderViewContainer { id: string; name?: string; iconUrl?: UriComponents; - iconCSS?: string; + themeIcon?: ThemeIcon; views?: { when?: string }[]; } @@ -61,7 +61,7 @@ interface IPinnedViewContainer { interface ICachedViewContainer { id: string; name?: string; - icon?: URI | string; + icon?: URI | ThemeIcon; pinned: boolean; order?: number; visible: boolean; @@ -717,7 +717,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { return ActivitybarPart.toActivity(id, name, icon, focusCommand?.id || id); } - private static toActivity(id: string, name: string, icon: URI | string | undefined, keybindingId: string | undefined): IActivity { + private static toActivity(id: string, name: string, icon: URI | ThemeIcon | undefined, keybindingId: string | undefined): IActivity { let cssClass: string | undefined = undefined; let iconUrl: URI | undefined = undefined; if (URI.isUri(icon)) { @@ -730,8 +730,8 @@ export class ActivitybarPart extends Part implements IActivityBarService { -webkit-mask: ${asCSSUrl(icon)} no-repeat 50% 50%; -webkit-mask-size: 24px; `); - } else if (isString(icon)) { - cssClass = icon; + } else if (ThemeIcon.isThemeIcon(icon)) { + cssClass = ThemeIcon.asClassName(icon); } return { id, name, cssClass, iconUrl, keybindingId }; } @@ -911,7 +911,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { const cachedViewContainer = this._cachedViewContainers.filter(cached => cached.id === placeholderViewContainer.id)[0]; if (cachedViewContainer) { cachedViewContainer.name = placeholderViewContainer.name; - cachedViewContainer.icon = placeholderViewContainer.iconCSS ? placeholderViewContainer.iconCSS : + cachedViewContainer.icon = placeholderViewContainer.themeIcon ? ThemeIcon.revive(placeholderViewContainer.themeIcon) : placeholderViewContainer.iconUrl ? URI.revive(placeholderViewContainer.iconUrl) : undefined; cachedViewContainer.views = placeholderViewContainer.views; } @@ -930,7 +930,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { this.setPlaceholderViewContainers(cachedViewContainers.map(({ id, icon, name, views }) => ({ id, iconUrl: URI.isUri(icon) ? icon : undefined, - iconCSS: isString(icon) ? icon : undefined, + themeIcon: ThemeIcon.isThemeIcon(icon) ? icon : undefined, name, views }))); diff --git a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts index e04b9594386..a5e4e36b614 100644 --- a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts +++ b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts @@ -18,12 +18,12 @@ import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IThemeService, Themable } from 'vs/platform/theme/common/themeService'; +import { IThemeService, Themable, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { PaneView, IPaneViewOptions, IPaneOptions, Pane, IPaneStyles } from 'vs/base/browser/ui/splitview/paneview'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IWorkbenchLayoutService, Position } from 'vs/workbench/services/layout/browser/layoutService'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; -import { Extensions as ViewContainerExtensions, IView, FocusedViewContext, IViewDescriptor, ViewContainer, IViewDescriptorService, ViewContainerLocation, IViewPaneContainer, IViewsRegistry, IViewContentDescriptor, IAddedViewDescriptorRef, IViewDescriptorRef, IViewContainerModel } from 'vs/workbench/common/views'; +import { Extensions as ViewContainerExtensions, IView, FocusedViewContext, IViewDescriptor, ViewContainer, IViewDescriptorService, ViewContainerLocation, IViewPaneContainer, IViewsRegistry, IViewContentDescriptor, IAddedViewDescriptorRef, IViewDescriptorRef, IViewContainerModel, defaultViewIcon } from 'vs/workbench/common/views'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { assertIsDefined, isString } from 'vs/base/common/types'; @@ -338,8 +338,8 @@ export abstract class ViewPane extends Pane implements IView { } } - private getIcon(): string | URI { - return this.viewDescriptorService.getViewDescriptorById(this.id)?.containerIcon || 'codicon-window'; + private getIcon(): ThemeIcon | URI { + return this.viewDescriptorService.getViewDescriptorById(this.id)?.containerIcon || ThemeIcon.fromCodicon(defaultViewIcon); } protected renderHeaderTitle(container: HTMLElement, title: string): void { diff --git a/src/vs/workbench/common/views.ts b/src/vs/workbench/common/views.ts index 24f43b1d740..95d534a587e 100644 --- a/src/vs/workbench/common/views.ts +++ b/src/vs/workbench/common/views.ts @@ -25,8 +25,12 @@ import { IPaneComposite } from 'vs/workbench/common/panecomposite'; import { IAccessibilityInformation } from 'vs/platform/accessibility/common/accessibility'; import { IMarkdownString } from 'vs/base/common/htmlContent'; import { mixin } from 'vs/base/common/objects'; +import { Codicon, registerIcon } from 'vs/base/common/codicons'; export const TEST_VIEW_CONTAINER_ID = 'workbench.view.extension.test'; +export const testViewIcon = registerIcon('test-view-icon', Codicon.beaker, localize('testViewIcon', 'View icon of the test view.')); + +export const defaultViewIcon = registerIcon('default-view-icon', Codicon.window, localize('defaultViewIcon', 'Default view icon.')); export namespace Extensions { export const ViewContainersRegistry = 'workbench.registry.view.containers'; @@ -48,7 +52,7 @@ export interface IViewContainerDescriptor { readonly storageId?: string; - readonly icon?: string | URI; + readonly icon?: ThemeIcon | URI; readonly alwaysUseContainerInfo?: boolean; @@ -216,7 +220,7 @@ export interface IViewDescriptor { readonly canMoveView?: boolean; - readonly containerIcon?: string | URI; + readonly containerIcon?: ThemeIcon | URI; readonly containerTitle?: string; @@ -252,7 +256,7 @@ export interface IAddedViewDescriptorState { export interface IViewContainerModel { readonly title: string; - readonly icon: string | URI | undefined; + readonly icon: ThemeIcon | URI | undefined; readonly onDidChangeContainerInfo: Event<{ title?: boolean, icon?: boolean }>; readonly allViewDescriptors: ReadonlyArray; diff --git a/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEdit.contribution.ts b/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEdit.contribution.ts index 139ee6ddbc3..5177edd043a 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEdit.contribution.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEdit.contribution.ts @@ -27,7 +27,8 @@ import type { ServicesAccessor } from 'vs/platform/instantiation/common/instanti import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import Severity from 'vs/base/common/severity'; -import { Codicon } from 'vs/base/common/codicons'; +import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; async function getBulkEditPane(viewsService: IViewsService): Promise { const view = await viewsService.openView(BulkEditPane.ID, true); @@ -341,6 +342,8 @@ Registry.as(WorkbenchExtensions.Workbench).regi BulkEditPreviewContribution, LifecyclePhase.Ready ); +const refactorPreviewViewIcon = registerIcon('refactor-preview-view-icon', Codicon.lightbulb, localize('refactorPreviewViewIcon', 'View icon of the refactor preview view.')); + const container = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({ id: BulkEditPane.ID, name: localize('panel', "Refactor Preview"), @@ -349,7 +352,7 @@ const container = Registry.as(ViewContainerExtensions.V ViewPaneContainer, [BulkEditPane.ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }] ), - icon: Codicon.lightbulb.classNames, + icon: ThemeIcon.fromCodicon(refactorPreviewViewIcon), storageId: BulkEditPane.ID }, ViewContainerLocation.Panel); @@ -358,5 +361,5 @@ Registry.as(ViewContainerExtensions.ViewsRegistry).registerViews name: localize('panel', "Refactor Preview"), when: BulkEditPreviewContribution.ctxEnabled, ctorDescriptor: new SyncDescriptor(BulkEditPane), - containerIcon: Codicon.lightbulb.classNames, + containerIcon: ThemeIcon.fromCodicon(refactorPreviewViewIcon), }], container); diff --git a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts index a26cea18ba4..fff513dedcb 100644 --- a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts @@ -49,10 +49,10 @@ import { IQuickAccessRegistry, Extensions as QuickAccessExtensions } from 'vs/pl import { StartDebugQuickAccessProvider } from 'vs/workbench/contrib/debug/browser/debugQuickAccess'; import { DebugProgressContribution } from 'vs/workbench/contrib/debug/browser/debugProgress'; import { DebugTitleContribution } from 'vs/workbench/contrib/debug/browser/debugTitle'; -import { Codicon } from 'vs/base/common/codicons'; import { registerColors } from 'vs/workbench/contrib/debug/browser/debugColors'; import { DebugEditorContribution } from 'vs/workbench/contrib/debug/browser/debugEditorContribution'; import { FileAccess } from 'vs/base/common/network'; +import { breakpointsViewIcon, callStackViewIcon, debugConsoleViewIcon, loadedScriptsViewIcon, runViewIcon, variablesViewIcon, watchViewIcon } from 'vs/workbench/contrib/debug/browser/debugIcons'; const registry = Registry.as(WorkbenchActionRegistryExtensions.WorkbenchActions); const debugCategory = nls.localize('debugCategory', "Debug"); @@ -460,7 +460,7 @@ function registerDebugPanel(): void { const VIEW_CONTAINER: ViewContainer = Registry.as(ViewExtensions.ViewContainersRegistry).registerViewContainer({ id: DEBUG_PANEL_ID, name: nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugPanel' }, 'Debug Console'), - icon: Codicon.debugConsole.classNames, + icon: ThemeIcon.fromCodicon(debugConsoleViewIcon), ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [DEBUG_PANEL_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]), storageId: DEBUG_PANEL_ID, focusCommand: { id: OpenDebugConsoleAction.ID }, @@ -471,7 +471,7 @@ function registerDebugPanel(): void { Registry.as(ViewExtensions.ViewsRegistry).registerViews([{ id: REPL_VIEW_ID, name: nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugPanel' }, 'Debug Console'), - containerIcon: Codicon.debugConsole.classNames, + containerIcon: ThemeIcon.fromCodicon(debugConsoleViewIcon), canToggleVisibility: false, canMoveView: true, when: CONTEXT_DEBUGGERS_AVAILABLE, @@ -481,12 +481,13 @@ function registerDebugPanel(): void { registry.registerWorkbenchAction(SyncActionDescriptor.from(OpenDebugConsoleAction, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_Y }), 'View: Debug Console', CATEGORIES.View.value, CONTEXT_DEBUGGERS_AVAILABLE); } + function registerDebugView(): void { const viewContainer = Registry.as(ViewExtensions.ViewContainersRegistry).registerViewContainer({ id: VIEWLET_ID, name: nls.localize('run', "Run"), ctorDescriptor: new SyncDescriptor(DebugViewPaneContainer), - icon: Codicon.debugAlt.classNames, + icon: ThemeIcon.fromCodicon(runViewIcon), alwaysUseContainerInfo: true, order: 2 }, ViewContainerLocation.Sidebar); @@ -494,12 +495,12 @@ function registerDebugView(): void { // Register default debug views const viewsRegistry = Registry.as(ViewExtensions.ViewsRegistry); - viewsRegistry.registerViews([{ id: VARIABLES_VIEW_ID, name: nls.localize('variables', "Variables"), containerIcon: Codicon.debugAlt.classNames, ctorDescriptor: new SyncDescriptor(VariablesView), order: 10, weight: 40, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusVariablesView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer); - viewsRegistry.registerViews([{ id: WATCH_VIEW_ID, name: nls.localize('watch', "Watch"), containerIcon: Codicon.debugAlt.classNames, ctorDescriptor: new SyncDescriptor(WatchExpressionsView), order: 20, weight: 10, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusWatchView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer); - viewsRegistry.registerViews([{ id: CALLSTACK_VIEW_ID, name: nls.localize('callStack', "Call Stack"), containerIcon: Codicon.debugAlt.classNames, ctorDescriptor: new SyncDescriptor(CallStackView), order: 30, weight: 30, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusCallStackView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer); - viewsRegistry.registerViews([{ id: BREAKPOINTS_VIEW_ID, name: nls.localize('breakpoints', "Breakpoints"), containerIcon: Codicon.debugAlt.classNames, ctorDescriptor: new SyncDescriptor(BreakpointsView), order: 40, weight: 20, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusBreakpointsView' }, when: ContextKeyExpr.or(CONTEXT_BREAKPOINTS_EXIST, CONTEXT_DEBUG_UX.isEqualTo('default')) }], viewContainer); - viewsRegistry.registerViews([{ id: WelcomeView.ID, name: WelcomeView.LABEL, containerIcon: Codicon.debugAlt.classNames, ctorDescriptor: new SyncDescriptor(WelcomeView), order: 1, weight: 40, canToggleVisibility: true, when: CONTEXT_DEBUG_UX.isEqualTo('simple') }], viewContainer); - viewsRegistry.registerViews([{ id: LOADED_SCRIPTS_VIEW_ID, name: nls.localize('loadedScripts', "Loaded Scripts"), containerIcon: Codicon.debugAlt.classNames, ctorDescriptor: new SyncDescriptor(LoadedScriptsView), order: 35, weight: 5, canToggleVisibility: true, canMoveView: true, collapsed: true, when: ContextKeyExpr.and(CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_DEBUG_UX.isEqualTo('default')) }], viewContainer); + viewsRegistry.registerViews([{ id: VARIABLES_VIEW_ID, name: nls.localize('variables', "Variables"), containerIcon: ThemeIcon.fromCodicon(variablesViewIcon), ctorDescriptor: new SyncDescriptor(VariablesView), order: 10, weight: 40, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusVariablesView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer); + viewsRegistry.registerViews([{ id: WATCH_VIEW_ID, name: nls.localize('watch', "Watch"), containerIcon: ThemeIcon.fromCodicon(watchViewIcon), ctorDescriptor: new SyncDescriptor(WatchExpressionsView), order: 20, weight: 10, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusWatchView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer); + viewsRegistry.registerViews([{ id: CALLSTACK_VIEW_ID, name: nls.localize('callStack', "Call Stack"), containerIcon: ThemeIcon.fromCodicon(callStackViewIcon), ctorDescriptor: new SyncDescriptor(CallStackView), order: 30, weight: 30, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusCallStackView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer); + viewsRegistry.registerViews([{ id: BREAKPOINTS_VIEW_ID, name: nls.localize('breakpoints', "Breakpoints"), containerIcon: ThemeIcon.fromCodicon(breakpointsViewIcon), ctorDescriptor: new SyncDescriptor(BreakpointsView), order: 40, weight: 20, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusBreakpointsView' }, when: ContextKeyExpr.or(CONTEXT_BREAKPOINTS_EXIST, CONTEXT_DEBUG_UX.isEqualTo('default')) }], viewContainer); + viewsRegistry.registerViews([{ id: WelcomeView.ID, name: WelcomeView.LABEL, containerIcon: ThemeIcon.fromCodicon(runViewIcon), ctorDescriptor: new SyncDescriptor(WelcomeView), order: 1, weight: 40, canToggleVisibility: true, when: CONTEXT_DEBUG_UX.isEqualTo('simple') }], viewContainer); + viewsRegistry.registerViews([{ id: LOADED_SCRIPTS_VIEW_ID, name: nls.localize('loadedScripts', "Loaded Scripts"), containerIcon: ThemeIcon.fromCodicon(loadedScriptsViewIcon), ctorDescriptor: new SyncDescriptor(LoadedScriptsView), order: 35, weight: 5, canToggleVisibility: true, canMoveView: true, collapsed: true, when: ContextKeyExpr.and(CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_DEBUG_UX.isEqualTo('default')) }], viewContainer); } function registerConfiguration(): void { diff --git a/src/vs/workbench/contrib/debug/browser/debugIcons.ts b/src/vs/workbench/contrib/debug/browser/debugIcons.ts new file mode 100644 index 00000000000..4c5923d9694 --- /dev/null +++ b/src/vs/workbench/contrib/debug/browser/debugIcons.ts @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { localize } from 'vs/nls'; + +export const debugConsoleViewIcon = registerIcon('debug-console-view-icon', Codicon.debugConsole, localize('debugConsoleViewIcon', 'View icon of the debug console view.')); +export const runViewIcon = registerIcon('run-view-icon', Codicon.debugAlt, localize('runViewIcon', 'View icon of the run view.')); +export const variablesViewIcon = registerIcon('variables-view-icon', Codicon.debugAlt, localize('variablesViewIcon', 'View icon of the variables view.')); +export const watchViewIcon = registerIcon('watch-view-icon', Codicon.debugAlt, localize('watchViewIcon', 'View icon of the watch view.')); +export const callStackViewIcon = registerIcon('callstack-view-icon', Codicon.debugAlt, localize('callStackViewIcon', 'View icon of the call stack view.')); +export const breakpointsViewIcon = registerIcon('breakpoints-view-icon', Codicon.debugAlt, localize('breakpointsViewIcon', 'View icon of the breakpoints view.')); +export const loadedScriptsViewIcon = registerIcon('loaded-scripts-view-icon', Codicon.debugAlt, localize('loadedScriptsViewIcon', 'View icon of the loaded scripts view.')); diff --git a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts index 6a3d5c45faf..0354706380a 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts @@ -64,6 +64,8 @@ import { ResourceContextKey } from 'vs/workbench/common/resources'; import { IAction } from 'vs/base/common/actions'; import { IWorkpsaceExtensionsConfigService } from 'vs/workbench/services/extensionRecommendations/common/workspaceExtensionsConfig'; import { Schemas } from 'vs/base/common/network'; +import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; // Singletons registerSingleton(IExtensionsWorkbenchService, ExtensionsWorkbenchService); @@ -102,12 +104,14 @@ Registry.as(EditorExtensions.Editors).registerEditor( new SyncDescriptor(ExtensionsInput) ]); +const extensionsViewIcon = registerIcon('extensions-view-icon', Codicon.extensions, localize('extensionsViewIcon', 'View icon of the extensions view.')); + Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer( { id: VIEWLET_ID, name: localize('extensions', "Extensions"), ctorDescriptor: new SyncDescriptor(ExtensionsViewPaneContainer), - icon: 'codicon-extensions', + icon: ThemeIcon.fromCodicon(extensionsViewIcon), order: 4, rejectAddedViews: true, alwaysUseContainerInfo: true diff --git a/src/vs/workbench/contrib/files/browser/explorerViewlet.ts b/src/vs/workbench/contrib/files/browser/explorerViewlet.ts index 54912b106eb..313ba7adc97 100644 --- a/src/vs/workbench/contrib/files/browser/explorerViewlet.ts +++ b/src/vs/workbench/contrib/files/browser/explorerViewlet.ts @@ -18,7 +18,7 @@ import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { IContextKeyService, IContextKey, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { IViewsRegistry, IViewDescriptor, Extensions, ViewContainer, IViewContainersRegistry, ViewContainerLocation, IViewDescriptorService, ViewContentGroups } from 'vs/workbench/common/views'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { Disposable } from 'vs/base/common/lifecycle'; @@ -37,7 +37,9 @@ import { WorkbenchStateContext, RemoteNameContext } from 'vs/workbench/browser/c import { IsWebContext } from 'vs/platform/contextkey/common/contextkeys'; import { AddRootFolderAction, OpenFolderAction, OpenFileFolderAction } from 'vs/workbench/browser/actions/workspaceActions'; import { isMacintosh } from 'vs/base/common/platform'; -import { Codicon } from 'vs/base/common/codicons'; +import { Codicon, registerIcon } from 'vs/base/common/codicons'; + +const explorerViewIcon = registerIcon('explorer-view-icon', Codicon.files, localize('explorerViewIcon', 'View icon of the explorer view.')); export class ExplorerViewletViewsContribution extends Disposable implements IWorkbenchContribution { @@ -108,7 +110,7 @@ export class ExplorerViewletViewsContribution extends Disposable implements IWor id: OpenEditorsView.ID, name: OpenEditorsView.NAME, ctorDescriptor: new SyncDescriptor(OpenEditorsView), - containerIcon: 'codicon-files', + containerIcon: ThemeIcon.fromCodicon(explorerViewIcon), order: 0, when: OpenEditorsVisibleContext, canToggleVisibility: true, @@ -125,7 +127,7 @@ export class ExplorerViewletViewsContribution extends Disposable implements IWor return { id: EmptyView.ID, name: EmptyView.NAME, - containerIcon: Codicon.files.classNames, + containerIcon: ThemeIcon.fromCodicon(explorerViewIcon), ctorDescriptor: new SyncDescriptor(EmptyView), order: 1, canToggleVisibility: true, @@ -139,7 +141,7 @@ export class ExplorerViewletViewsContribution extends Disposable implements IWor return { id: VIEW_ID, name: localize('folders', "Folders"), - containerIcon: Codicon.files.classNames, + containerIcon: ThemeIcon.fromCodicon(explorerViewIcon), ctorDescriptor: new SyncDescriptor(ExplorerView), order: 1, canToggleVisibility: false, @@ -267,7 +269,7 @@ export const VIEW_CONTAINER: ViewContainer = viewContainerRegistry.registerViewC name: localize('explore', "Explorer"), ctorDescriptor: new SyncDescriptor(ExplorerViewPaneContainer), storageId: 'workbench.explorer.views.state', - icon: Codicon.files.classNames, + icon: ThemeIcon.fromCodicon(explorerViewIcon), alwaysUseContainerInfo: true, order: 0 }, ViewContainerLocation.Sidebar, true); diff --git a/src/vs/workbench/contrib/markers/browser/markers.contribution.ts b/src/vs/workbench/contrib/markers/browser/markers.contribution.ts index e046732264e..ac6c5837298 100644 --- a/src/vs/workbench/contrib/markers/browser/markers.contribution.ts +++ b/src/vs/workbench/contrib/markers/browser/markers.contribution.ts @@ -32,7 +32,8 @@ import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/la import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import type { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ToggleViewAction } from 'vs/workbench/browser/actions/layoutActions'; -import { Codicon } from 'vs/base/common/codicons'; +import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; registerSingleton(IMarkersWorkbenchService, MarkersWorkbenchService, false); @@ -124,11 +125,13 @@ class ToggleMarkersPanelAction extends ToggleViewAction { } } +const markersViewIcon = registerIcon('markers-view-icon', Codicon.warning, localize('markersViewIcon', 'View icon of the markers view.')); + // markers view container const VIEW_CONTAINER: ViewContainer = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({ id: Constants.MARKERS_CONTAINER_ID, name: Messages.MARKERS_PANEL_TITLE_PROBLEMS, - icon: Codicon.warning.classNames, + icon: ThemeIcon.fromCodicon(markersViewIcon), hideIfEmpty: true, order: 0, ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [Constants.MARKERS_CONTAINER_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]), @@ -142,7 +145,7 @@ const VIEW_CONTAINER: ViewContainer = Registry.as(ViewC Registry.as(ViewContainerExtensions.ViewsRegistry).registerViews([{ id: Constants.MARKERS_VIEW_ID, - containerIcon: Codicon.warning.classNames, + containerIcon: ThemeIcon.fromCodicon(markersViewIcon), name: Messages.MARKERS_PANEL_TITLE_PROBLEMS, canToggleVisibility: false, canMoveView: true, diff --git a/src/vs/workbench/contrib/outline/browser/outline.contribution.ts b/src/vs/workbench/contrib/outline/browser/outline.contribution.ts index 3dc1cf7fb70..5fb485fa404 100644 --- a/src/vs/workbench/contrib/outline/browser/outline.contribution.ts +++ b/src/vs/workbench/contrib/outline/browser/outline.contribution.ts @@ -11,13 +11,17 @@ import { IConfigurationRegistry, Extensions as ConfigurationExtensions, Configur import { OutlineConfigKeys, OutlineViewId } from 'vs/editor/contrib/documentSymbols/outline'; import { VIEW_CONTAINER } from 'vs/workbench/contrib/files/browser/explorerViewlet'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; +import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; export const PANEL_ID = 'panel.view.outline'; +const outlineViewIcon = registerIcon('outline-view-icon', Codicon.symbolClass, localize('outlineViewIcon', 'View icon of the outline view.')); + const _outlineDesc = { id: OutlineViewId, name: localize('name', "Outline"), - containerIcon: 'codicon-symbol-class', + containerIcon: ThemeIcon.fromCodicon(outlineViewIcon), ctorDescriptor: new SyncDescriptor(OutlinePane), canToggleVisibility: true, canMoveView: true, diff --git a/src/vs/workbench/contrib/output/browser/output.contribution.ts b/src/vs/workbench/contrib/output/browser/output.contribution.ts index 04d655a94e6..058a20f3483 100644 --- a/src/vs/workbench/contrib/output/browser/output.contribution.ts +++ b/src/vs/workbench/contrib/output/browser/output.contribution.ts @@ -32,8 +32,9 @@ import { assertIsDefined } from 'vs/base/common/types'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; import { ContextKeyEqualsExpr, ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { ToggleViewAction } from 'vs/workbench/browser/actions/layoutActions'; -import { Codicon } from 'vs/base/common/codicons'; +import { Codicon, registerIcon } from 'vs/base/common/codicons'; import { CATEGORIES } from 'vs/workbench/common/actions'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; // Register Service registerSingleton(IOutputService, OutputService); @@ -60,10 +61,13 @@ const toggleOutputActionKeybindings = { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_H) // On Ubuntu Ctrl+Shift+U is taken by some global OS command } }; + +const outputViewIcon = registerIcon('output-view-icon', Codicon.output, nls.localize('outputViewIcon', 'View icon of the output view.')); + const VIEW_CONTAINER: ViewContainer = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({ id: OUTPUT_VIEW_ID, name: nls.localize('output', "Output"), - icon: Codicon.output.classNames, + icon: ThemeIcon.fromCodicon(outputViewIcon), order: 1, ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [OUTPUT_VIEW_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]), storageId: OUTPUT_VIEW_ID, @@ -74,7 +78,7 @@ const VIEW_CONTAINER: ViewContainer = Registry.as(ViewC Registry.as(ViewContainerExtensions.ViewsRegistry).registerViews([{ id: OUTPUT_VIEW_ID, name: nls.localize('output', "Output"), - containerIcon: Codicon.output.classNames, + containerIcon: ThemeIcon.fromCodicon(outputViewIcon), canMoveView: true, canToggleVisibility: false, ctorDescriptor: new SyncDescriptor(OutputViewPane), diff --git a/src/vs/workbench/contrib/remote/browser/remote.ts b/src/vs/workbench/contrib/remote/browser/remote.ts index 6db1f59653b..bf67431a503 100644 --- a/src/vs/workbench/contrib/remote/browser/remote.ts +++ b/src/vs/workbench/contrib/remote/browser/remote.ts @@ -13,7 +13,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace import { IStorageService } from 'vs/platform/storage/common/storage'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { FilterViewPaneContainer } from 'vs/workbench/browser/parts/views/viewsViewlet'; @@ -552,6 +552,8 @@ export class RemoteViewPaneContainer extends FilterViewPaneContainer implements } +const remoteExplorerViewIcon = registerIcon('remote-explorer-view-icon', Codicon.remoteExplorer, nls.localize('remoteExplorerViewIcon', 'View icon of the remote explorer view.')); + Registry.as(Extensions.ViewContainersRegistry).registerViewContainer( { id: VIEWLET_ID, @@ -583,7 +585,7 @@ Registry.as(Extensions.ViewContainersRegistry).register return; } }, - icon: 'codicon-remote-explorer', + icon: ThemeIcon.fromCodicon(remoteExplorerViewIcon), order: 4 }, ViewContainerLocation.Sidebar); diff --git a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts index 5a8ede45558..3358221ade6 100644 --- a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts +++ b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts @@ -22,12 +22,13 @@ import { IViewContainersRegistry, ViewContainerLocation, Extensions as ViewConta import { SCMViewPaneContainer } from 'vs/workbench/contrib/scm/browser/scmViewPaneContainer'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { ModesRegistry } from 'vs/editor/common/modes/modesRegistry'; -import { Codicon } from 'vs/base/common/codicons'; +import { Codicon, registerIcon } from 'vs/base/common/codicons'; import { SCMViewPane } from 'vs/workbench/contrib/scm/browser/scmViewPane'; import { SCMViewService } from 'vs/workbench/contrib/scm/browser/scmViewService'; import { SCMRepositoriesViewPane } from 'vs/workbench/contrib/scm/browser/scmRepositoriesViewPane'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { Context as SuggestContext } from 'vs/editor/contrib/suggest/suggest'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; ModesRegistry.registerLanguage({ id: 'scminput', @@ -38,12 +39,14 @@ ModesRegistry.registerLanguage({ Registry.as(WorkbenchExtensions.Workbench) .registerWorkbenchContribution(DirtyDiffWorkbenchController, LifecyclePhase.Restored); +const sourceControlViewIcon = registerIcon('source-control-view-icon', Codicon.sourceControl, localize('sourceControlViewIcon', 'View icon of the source control view.')); + const viewContainer = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({ id: VIEWLET_ID, name: localize('source control', "Source Control"), ctorDescriptor: new SyncDescriptor(SCMViewPaneContainer), storageId: 'workbench.scm.views.state', - icon: Codicon.sourceControl.classNames, + icon: ThemeIcon.fromCodicon(sourceControlViewIcon), alwaysUseContainerInfo: true, order: 2, hideIfEmpty: true @@ -65,7 +68,7 @@ viewsRegistry.registerViews([{ canMoveView: true, weight: 80, order: -999, - containerIcon: Codicon.sourceControl.classNames + containerIcon: ThemeIcon.fromCodicon(sourceControlViewIcon) }], viewContainer); viewsRegistry.registerViews([{ @@ -80,7 +83,7 @@ viewsRegistry.registerViews([{ order: -1000, when: ContextKeyExpr.and(ContextKeyExpr.has('scm.providerCount'), ContextKeyExpr.notEquals('scm.providerCount', 0)), // readonly when = ContextKeyExpr.or(ContextKeyExpr.equals('config.scm.alwaysShowProviders', true), ContextKeyExpr.and(ContextKeyExpr.notEquals('scm.providerCount', 0), ContextKeyExpr.notEquals('scm.providerCount', 1))); - containerIcon: Codicon.sourceControl.classNames + containerIcon: ThemeIcon.fromCodicon(sourceControlViewIcon) }], viewContainer); Registry.as(WorkbenchExtensions.Workbench) diff --git a/src/vs/workbench/contrib/search/browser/search.contribution.ts b/src/vs/workbench/contrib/search/browser/search.contribution.ts index cf0f24f260e..84ecac2c414 100644 --- a/src/vs/workbench/contrib/search/browser/search.contribution.ts +++ b/src/vs/workbench/contrib/search/browser/search.contribution.ts @@ -55,6 +55,7 @@ import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { AbstractGotoLineQuickAccessProvider } from 'vs/editor/contrib/quickAccess/gotoLineQuickAccess'; import { GotoSymbolQuickAccessProvider } from 'vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess'; import { searchViewIcon } from 'vs/workbench/contrib/search/browser/searchIcons'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; registerSingleton(ISearchWorkbenchService, SearchWorkbenchService, true); registerSingleton(ISearchHistoryService, SearchHistoryService, true); @@ -509,11 +510,11 @@ const viewContainer = Registry.as(ViewExtensions.ViewCo name: nls.localize('name', "Search"), ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [VIEWLET_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]), hideIfEmpty: true, - icon: searchViewIcon.classNames, + icon: ThemeIcon.fromCodicon(searchViewIcon), order: 1 }, ViewContainerLocation.Sidebar); -const viewDescriptor = { id: VIEW_ID, containerIcon: 'codicon-search', name: nls.localize('search', "Search"), ctorDescriptor: new SyncDescriptor(SearchView), canToggleVisibility: false, canMoveView: true }; +const viewDescriptor = { id: VIEW_ID, containerIcon: ThemeIcon.fromCodicon(searchViewIcon), name: nls.localize('search', "Search"), ctorDescriptor: new SyncDescriptor(SearchView), canToggleVisibility: false, canMoveView: true }; // Register search default location to sidebar Registry.as(ViewExtensions.ViewsRegistry).registerViews([viewDescriptor], viewContainer); diff --git a/src/vs/workbench/contrib/search/browser/searchIcons.ts b/src/vs/workbench/contrib/search/browser/searchIcons.ts index 2138fbaa30f..2c264dbf1e4 100644 --- a/src/vs/workbench/contrib/search/browser/searchIcons.ts +++ b/src/vs/workbench/contrib/search/browser/searchIcons.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { localize } from 'vs/nls'; export const searchDetailsIcon = registerIcon('search-details', Codicon.ellipsis); @@ -20,7 +21,7 @@ export const searchExpandAllIcon = registerIcon('search-expand-results', Codicon export const searchClearIcon = registerIcon('search-clear-results', Codicon.clearAll); export const searchStopIcon = Codicon.searchStop; -export const searchViewIcon = Codicon.search; +export const searchViewIcon = registerIcon('search-view-icon', Codicon.search, localize('searchViewIcon', 'View icon of the search view.')); export const searchNewEditorIcon = registerIcon('search-new-editor', Codicon.newFile); export const searchGotoFileIcon = registerIcon('search-goto-file', Codicon.goToFile); diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts index 807c77c271a..67ad70e5ec0 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts @@ -36,6 +36,8 @@ import { IQuickAccessRegistry, Extensions as QuickAccessExtensions } from 'vs/pl import { TerminalQuickAccessProvider } from 'vs/workbench/contrib/terminal/browser/terminalQuickAccess'; import { terminalConfiguration } from 'vs/workbench/contrib/terminal/common/terminalConfiguration'; import { CONTEXT_ACCESSIBILITY_MODE_ENABLED } from 'vs/platform/accessibility/common/accessibility'; +import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; // Register services registerSingleton(ITerminalService, TerminalService, true); @@ -59,11 +61,13 @@ CommandsRegistry.registerCommand({ id: quickAccessNavigatePreviousInTerminalPick const configurationRegistry = Registry.as(Extensions.Configuration); configurationRegistry.registerConfiguration(terminalConfiguration); +const terminalViewIcon = registerIcon('terminal-view-icon', Codicon.terminal, nls.localize('terminalViewIcon', 'View icon of the terminal view.')); + // Register views const VIEW_CONTAINER = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({ id: TERMINAL_VIEW_ID, name: nls.localize('terminal', "Terminal"), - icon: 'codicon-terminal', + icon: ThemeIcon.fromCodicon(terminalViewIcon), ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [TERMINAL_VIEW_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]), storageId: TERMINAL_VIEW_ID, focusCommand: { id: TERMINAL_COMMAND_ID.FOCUS }, @@ -74,7 +78,7 @@ Registry.as(panel.Extensions.Panels).setDefaultPanelId(TERM Registry.as(ViewContainerExtensions.ViewsRegistry).registerViews([{ id: TERMINAL_VIEW_ID, name: nls.localize('terminal', "Terminal"), - containerIcon: 'codicon-terminal', + containerIcon: ThemeIcon.fromCodicon(terminalViewIcon), canToggleVisibility: false, canMoveView: true, ctorDescriptor: new SyncDescriptor(TerminalViewPane) diff --git a/src/vs/workbench/contrib/timeline/browser/timeline.contribution.ts b/src/vs/workbench/contrib/timeline/browser/timeline.contribution.ts index b7ca9dbb216..4caef263d11 100644 --- a/src/vs/workbench/contrib/timeline/browser/timeline.contribution.ts +++ b/src/vs/workbench/contrib/timeline/browser/timeline.contribution.ts @@ -18,11 +18,16 @@ import { MenuId, MenuRegistry } from 'vs/platform/actions/common/actions'; import { ICommandHandler, CommandsRegistry } from 'vs/platform/commands/common/commands'; import { ExplorerFolderContext } from 'vs/workbench/contrib/files/common/files'; import { ResourceContextKey } from 'vs/workbench/common/resources'; +import { Codicon, registerIcon } from 'vs/base/common/codicons'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; + + +const timelineViewIcon = registerIcon('timeline-view-icon', Codicon.history, localize('timelineViewIcon', 'View icon of the timeline view.')); export class TimelinePaneDescriptor implements IViewDescriptor { readonly id = TimelinePaneId; readonly name = TimelinePane.TITLE; - readonly containerIcon = 'codicon-history'; + readonly containerIcon = ThemeIcon.fromCodicon(timelineViewIcon); readonly ctorDescriptor = new SyncDescriptor(TimelinePane); readonly order = 2; readonly weight = 30; diff --git a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts index 0c6f5ad1695..206d8500858 100644 --- a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts +++ b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts @@ -50,10 +50,10 @@ import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IAuthenticationService } from 'vs/workbench/services/authentication/browser/authenticationService'; import { Registry } from 'vs/platform/registry/common/platform'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; -import { Codicon } from 'vs/base/common/codicons'; import { ViewContainerLocation, IViewContainersRegistry, Extensions, ViewContainer } from 'vs/workbench/common/views'; import { UserDataSyncViewPaneContainer, UserDataSyncDataViews } from 'vs/workbench/contrib/userDataSync/browser/userDataSyncViews'; -import { IUserDataSyncWorkbenchService, getSyncAreaLabel, AccountStatus, CONTEXT_SYNC_STATE, CONTEXT_SYNC_ENABLEMENT, CONTEXT_ACCOUNT_STATE, CONFIGURE_SYNC_COMMAND_ID, SHOW_SYNC_LOG_COMMAND_ID, SYNC_VIEW_CONTAINER_ID, SYNC_TITLE } from 'vs/workbench/services/userDataSync/common/userDataSync'; +import { IUserDataSyncWorkbenchService, getSyncAreaLabel, AccountStatus, CONTEXT_SYNC_STATE, CONTEXT_SYNC_ENABLEMENT, CONTEXT_ACCOUNT_STATE, CONFIGURE_SYNC_COMMAND_ID, SHOW_SYNC_LOG_COMMAND_ID, SYNC_VIEW_CONTAINER_ID, SYNC_TITLE, SYNC_VIEW_ICON } from 'vs/workbench/services/userDataSync/common/userDataSync'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; const CONTEXT_CONFLICTS_SOURCES = new RawContextKey('conflictsSources', ''); @@ -1125,7 +1125,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo UserDataSyncViewPaneContainer, [SYNC_VIEW_CONTAINER_ID] ), - icon: Codicon.sync.classNames, + icon: ThemeIcon.fromCodicon(SYNC_VIEW_ICON), hideIfEmpty: true, }, ViewContainerLocation.Sidebar); } diff --git a/src/vs/workbench/services/userDataSync/common/userDataSync.ts b/src/vs/workbench/services/userDataSync/common/userDataSync.ts index 4e0e54f6252..bf587f2544b 100644 --- a/src/vs/workbench/services/userDataSync/common/userDataSync.ts +++ b/src/vs/workbench/services/userDataSync/common/userDataSync.ts @@ -9,6 +9,7 @@ import { Event } from 'vs/base/common/event'; import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { localize } from 'vs/nls'; import { URI } from 'vs/base/common/uri'; +import { Codicon, registerIcon } from 'vs/base/common/codicons'; export interface IUserDataSyncAccount { readonly authenticationProviderId: string; @@ -81,6 +82,8 @@ export const enum AccountStatus { export const SYNC_TITLE = localize('sync category', "Settings Sync"); +export const SYNC_VIEW_ICON = registerIcon('settings-sync-view-icon', Codicon.sync, localize('syncViewIcon', 'View icon of the settings sync view.')); + // Contexts export const CONTEXT_SYNC_STATE = new RawContextKey('syncStatus', SyncStatus.Uninitialized); export const CONTEXT_SYNC_ENABLEMENT = new RawContextKey('syncEnabled', false); diff --git a/src/vs/workbench/services/views/browser/viewDescriptorService.ts b/src/vs/workbench/services/views/browser/viewDescriptorService.ts index 9d15e838755..d9d2bf79326 100644 --- a/src/vs/workbench/services/views/browser/viewDescriptorService.ts +++ b/src/vs/workbench/services/views/browser/viewDescriptorService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ViewContainerLocation, IViewDescriptorService, ViewContainer, IViewsRegistry, IViewContainersRegistry, IViewDescriptor, Extensions as ViewExtensions, ViewVisibilityState } from 'vs/workbench/common/views'; +import { ViewContainerLocation, IViewDescriptorService, ViewContainer, IViewsRegistry, IViewContainersRegistry, IViewDescriptor, Extensions as ViewExtensions, ViewVisibilityState, defaultViewIcon } from 'vs/workbench/common/views'; import { IContextKey, RawContextKey, IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { IStorageService, StorageScope, IStorageValueChangeEvent, StorageTarget } from 'vs/platform/storage/common/storage'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; @@ -19,6 +19,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { getViewsStateStorageId, ViewContainerModel } from 'vs/workbench/services/views/common/viewContainerModel'; import { registerAction2, Action2, MenuId } from 'vs/platform/actions/common/actions'; import { localize } from 'vs/nls'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; interface ICachedViewContainerInfo { containerId: string; @@ -460,7 +461,7 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor id, ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [id, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]), name: 'Custom Views', // we don't want to see this, so no need to localize - icon: location === ViewContainerLocation.Sidebar ? 'codicon-window' : undefined, + icon: location === ViewContainerLocation.Sidebar ? ThemeIcon.fromCodicon(defaultViewIcon) : undefined, storageId: getViewContainerStorageId(id), hideIfEmpty: true }, location); diff --git a/src/vs/workbench/services/views/common/viewContainerModel.ts b/src/vs/workbench/services/views/common/viewContainerModel.ts index 524d938e4c1..d736bc82ff0 100644 --- a/src/vs/workbench/services/views/common/viewContainerModel.ts +++ b/src/vs/workbench/services/views/common/viewContainerModel.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ViewContainer, IViewsRegistry, IViewDescriptor, Extensions as ViewExtensions, IViewContainerModel, IAddedViewDescriptorRef, IViewDescriptorRef, IAddedViewDescriptorState } from 'vs/workbench/common/views'; +import { ViewContainer, IViewsRegistry, IViewDescriptor, Extensions as ViewExtensions, IViewContainerModel, IAddedViewDescriptorRef, IViewDescriptorRef, IAddedViewDescriptorState, defaultViewIcon } from 'vs/workbench/common/views'; import { IContextKeyService, IReadableSet } from 'vs/platform/contextkey/common/contextkey'; import { IStorageService, StorageScope, IStorageValueChangeEvent, StorageTarget } from 'vs/platform/storage/common/storage'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -14,6 +14,7 @@ import { URI } from 'vs/base/common/uri'; import { move } from 'vs/base/common/arrays'; import { isUndefined, isUndefinedOrNull } from 'vs/base/common/types'; import { isEqual } from 'vs/base/common/resources'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; export function getViewsStateStorageId(viewContainerStorageId: string): string { return `${viewContainerStorageId}.hidden`; } @@ -286,8 +287,8 @@ export class ViewContainerModel extends Disposable implements IViewContainerMode // Container Info private _title!: string; get title(): string { return this._title; } - private _icon: URI | string | undefined; - get icon(): URI | string | undefined { return this._icon; } + private _icon: URI | ThemeIcon | undefined; + get icon(): URI | ThemeIcon | undefined { return this._icon; } private _onDidChangeContainerInfo = this._register(new Emitter<{ title?: boolean, icon?: boolean }>()); readonly onDidChangeContainerInfo = this._onDidChangeContainerInfo.event; @@ -347,9 +348,9 @@ export class ViewContainerModel extends Disposable implements IViewContainerMode titleChanged = true; } - const icon = useDefaultContainerInfo ? this.container.icon : this.visibleViewDescriptors[0]?.containerIcon || 'codicon-window'; + const icon = useDefaultContainerInfo ? this.container.icon : this.visibleViewDescriptors[0]?.containerIcon || ThemeIcon.fromCodicon(defaultViewIcon); let iconChanged: boolean = false; - if (URI.isUri(icon) && URI.isUri(this._icon) ? isEqual(icon, this._icon) : this._icon !== icon) { + if (!this.isEqualIcon(icon)) { this._icon = icon; iconChanged = true; } @@ -359,6 +360,15 @@ export class ViewContainerModel extends Disposable implements IViewContainerMode } } + private isEqualIcon(icon: URI | ThemeIcon | undefined): boolean { + if (URI.isUri(icon)) { + return URI.isUri(this._icon) && isEqual(icon, this._icon); + } else if (ThemeIcon.isThemeIcon(icon)) { + return ThemeIcon.isThemeIcon(this._icon) && ThemeIcon.isEqual(icon, this._icon); + } + return icon === this._icon; + } + isVisible(id: string): boolean { const viewDescriptorItem = this.viewDescriptorItems.filter(v => v.viewDescriptor.id === id)[0]; if (!viewDescriptorItem) {