diff --git a/src/vs/platform/theme/common/themeService.ts b/src/vs/platform/theme/common/themeService.ts index 9867c464ae3..1c2ac9a516f 100644 --- a/src/vs/platform/theme/common/themeService.ts +++ b/src/vs/platform/theme/common/themeService.ts @@ -67,8 +67,8 @@ export namespace ThemeIcon { return ti1.id === ti2.id && ti1.color?.id === ti2.color?.id; } - export function asThemeIcon(codicon: Codicon): ThemeIcon { - return { id: codicon.id }; + export function asThemeIcon(codicon: Codicon, color?: string): ThemeIcon { + return { id: codicon.id, color: color ? themeColorFromId(color) : undefined }; } export const asClassNameArray: (icon: ThemeIcon) => string[] = CSSIcon.asClassNameArray; diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 2faab9d2968..810f3b1d568 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -12328,7 +12328,7 @@ declare module 'vscode' { * The icon path for a specific * {@link SourceControlResourceState source control resource state}. */ - readonly iconPath?: string | Uri; + readonly iconPath?: string | Uri | ThemeIcon; } /** diff --git a/src/vs/workbench/api/browser/mainThreadSCM.ts b/src/vs/workbench/api/browser/mainThreadSCM.ts index 249f4d973c6..0c743301f10 100644 --- a/src/vs/workbench/api/browser/mainThreadSCM.ts +++ b/src/vs/workbench/api/browser/mainThreadSCM.ts @@ -13,6 +13,7 @@ import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; import { ISplice, Sequence } from 'vs/base/common/sequence'; import { CancellationToken } from 'vs/base/common/cancellation'; import { MarshalledId } from 'vs/base/common/marshalling'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; class MainThreadSCMResourceGroup implements ISCMResourceGroup { @@ -204,11 +205,14 @@ class MainThreadSCMProvider implements ISCMProvider { for (const [start, deleteCount, rawResources] of groupSlices) { const resources = rawResources.map(rawResource => { const [handle, sourceUri, icons, tooltip, strikeThrough, faded, contextValue, command] = rawResource; - const icon = icons[0]; - const iconDark = icons[1] || icon; + + const [light, dark] = icons; + const icon = ThemeIcon.isThemeIcon(light) ? light : URI.revive(light); + const iconDark = (ThemeIcon.isThemeIcon(dark) ? dark : URI.revive(dark)) || icon; + const decorations = { - icon: icon ? URI.revive(icon) : undefined, - iconDark: iconDark ? URI.revive(iconDark) : undefined, + icon: icon, + iconDark: iconDark, tooltip, strikeThrough, faded diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 742227bf7a2..ebd88795f41 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -1039,7 +1039,7 @@ export interface SCMGroupFeatures { export type SCMRawResource = [ number /*handle*/, UriComponents /*resourceUri*/, - UriComponents[] /*icons: light, dark*/, + [UriComponents | ThemeIcon | undefined, UriComponents | ThemeIcon | undefined] /*icons: light, dark*/, string /*tooltip*/, boolean /*strike through*/, boolean /*faded*/, diff --git a/src/vs/workbench/api/common/extHostSCM.ts b/src/vs/workbench/api/common/extHostSCM.ts index 3705d6a4f78..142000651bd 100644 --- a/src/vs/workbench/api/common/extHostSCM.ts +++ b/src/vs/workbench/api/common/extHostSCM.ts @@ -19,18 +19,23 @@ import { CancellationToken } from 'vs/base/common/cancellation'; import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import { checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions'; import { MarshalledId } from 'vs/base/common/marshalling'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; type ProviderHandle = number; type GroupHandle = number; type ResourceStateHandle = number; -function getIconResource(decorations?: vscode.SourceControlResourceThemableDecorations): vscode.Uri | undefined { +function getIconResource(decorations?: vscode.SourceControlResourceThemableDecorations): UriComponents | ThemeIcon | undefined { if (!decorations) { return undefined; } else if (typeof decorations.iconPath === 'string') { return URI.file(decorations.iconPath); - } else { + } else if (URI.isUri(decorations.iconPath)) { return decorations.iconPath; + } else if (ThemeIcon.isThemeIcon(decorations.iconPath)) { + return decorations.iconPath; + } else { + return undefined; } } @@ -43,8 +48,8 @@ function compareResourceThemableDecorations(a: vscode.SourceControlResourceThema return 1; } - const aPath = typeof a.iconPath === 'string' ? a.iconPath : a.iconPath.fsPath; - const bPath = typeof b.iconPath === 'string' ? b.iconPath : b.iconPath.fsPath; + const aPath = typeof a.iconPath === 'string' ? a.iconPath : URI.isUri(a.iconPath) ? a.iconPath.fsPath : (a.iconPath as vscode.ThemeIcon).id; + const bPath = typeof b.iconPath === 'string' ? b.iconPath : URI.isUri(b.iconPath) ? b.iconPath.fsPath : (b.iconPath as vscode.ThemeIcon).id; return comparePaths(aPath, bPath); } @@ -368,12 +373,8 @@ class ExtHostSourceControlResourceGroup implements vscode.SourceControlResourceG this._resourceStatesMap.set(handle, r); const sourceUri = r.resourceUri; - const iconUri = getIconResource(r.decorations); - const lightIconUri = r.decorations && getIconResource(r.decorations.light) || iconUri; - const darkIconUri = r.decorations && getIconResource(r.decorations.dark) || iconUri; - const icons: UriComponents[] = []; - let command: ICommandDto | undefined; + let command: ICommandDto | undefined; if (r.command) { if (r.command.command === 'vscode.open' || r.command.command === 'vscode.diff') { const disposables = new DisposableStore(); @@ -384,13 +385,10 @@ class ExtHostSourceControlResourceGroup implements vscode.SourceControlResourceG } } - if (lightIconUri) { - icons.push(lightIconUri); - } - - if (darkIconUri && (darkIconUri.toString() !== lightIconUri?.toString())) { - icons.push(darkIconUri); - } + const icon = getIconResource(r.decorations); + const lightIcon = r.decorations && getIconResource(r.decorations.light) || icon; + const darkIcon = r.decorations && getIconResource(r.decorations.dark) || icon; + const icons: SCMRawResource[2] = [lightIcon, darkIcon]; const tooltip = (r.decorations && r.decorations.tooltip) || ''; const strikeThrough = r.decorations && !!r.decorations.strikeThrough; diff --git a/src/vs/workbench/contrib/scm/browser/media/scm.css b/src/vs/workbench/contrib/scm/browser/media/scm.css index 3cb3338eed9..91599dea2da 100644 --- a/src/vs/workbench/contrib/scm/browser/media/scm.css +++ b/src/vs/workbench/contrib/scm/browser/media/scm.css @@ -144,6 +144,11 @@ margin-right: 8px; } +.scm-view .monaco-list-row .resource > .decoration-icon.codicon { + margin-right: 0; + margin-top: 3px; +} + .scm-view .monaco-list .monaco-list-row .resource > .name > .monaco-icon-label > .actions { flex-grow: 100; } diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index bd168d97928..a65c7d9df3d 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -22,7 +22,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { MenuItemAction, IMenuService, registerAction2, MenuId, IAction2Options, MenuRegistry, Action2 } from 'vs/platform/actions/common/actions'; import { IAction, ActionRunner } from 'vs/base/common/actions'; import { ActionBar, IActionViewItemProvider } from 'vs/base/browser/ui/actionbar/actionbar'; -import { IThemeService, registerThemingParticipant, IFileIconTheme } from 'vs/platform/theme/common/themeService'; +import { IThemeService, registerThemingParticipant, IFileIconTheme, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { isSCMResource, isSCMResourceGroup, connectPrimaryMenuToInlineActionBar, isSCMRepository, isSCMInput, collectContextMenuActions, getActionViewItemProvider } from './util'; import { attachBadgeStyler } from 'vs/platform/theme/common/styler'; import { WorkbenchCompressibleObjectTree, IOpenEvent } from 'vs/platform/list/browser/listService'; @@ -395,10 +395,23 @@ class ResourceRenderer implements ICompressibleTreeRenderer('scm'); export interface ISCMResourceDecorations { - icon?: URI; - iconDark?: URI; + icon?: URI | ThemeIcon; + iconDark?: URI | ThemeIcon; tooltip?: string; strikeThrough?: boolean; faded?: boolean;