src/vs/platform/theme/common/themeService.ts
261 LOC · 223 covered · 38 uncovered · 14 ranges · 1739 concepts · 2 introducers · 875 tests
File neighbourhood
The centred file is linked to every concept that introduces one of its ranges, every test that runs code from the file, and the gray connector concepts standing between those tests and the file's own introducer concepts. Undirected links join concepts to every file where they introduce source and concepts to the tests they introduce; arrows show specialization between the displayed concepts and bridge only concepts omitted from this view. Concept colors match the source ranges below; connector concepts have no source color and are shown in gray.
Focused file, its introducer and connector concepts, their introduced files, and tests that run code from the file
In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the related-file, concept, and source links on this page.
Graph controls are ready.
Interactive rendering requires JavaScript and WebGL. Use the related-file, concept, and source links on this page while the interactive map is unavailable.
/*---------------------------------------------------------------------------------------------
colorUtils.ts ×16
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Codicon } from '../../../base/common/codicons.js';
import { Color } from '../../../base/common/color.js';
import { Emitter, Event } from '../../../base/common/event.js';
import { Disposable, IDisposable, toDisposable } from '../../../base/common/lifecycle.js';
import { IEnvironmentService } from '../../environment/common/environment.js';
import { createDecorator } from '../../instantiation/common/instantiation.js';
import * as platform from '../../registry/common/platform.js';
import { ColorIdentifier } from './colorRegistry.js';
import { IconContribution, IconDefinition } from './iconRegistry.js';
import { ColorScheme, ThemeTypeSelector } from './theme.js';
export const IThemeService = createDecorator<IThemeService>('themeService');
export function themeColorFromId(id: ColorIdentifier) {
return { id };
}
export const FileThemeIcon = Codicon.file;
export const FolderThemeIcon = Codicon.folder;
export function getThemeTypeSelector(type: ColorScheme): ThemeTypeSelector {
switch (type) {
case ColorScheme.DARK: return ThemeTypeSelector.VS_DARK;
case ColorScheme.HIGH_CONTRAST_DARK: return ThemeTypeSelector.HC_BLACK;
case ColorScheme.HIGH_CONTRAST_LIGHT: return ThemeTypeSelector.HC_LIGHT;
default: return ThemeTypeSelector.VS;
}
}
export interface ITokenStyle {
readonly foreground: number | undefined;
readonly bold: boolean | undefined;
readonly underline: boolean | undefined;
readonly strikethrough: boolean | undefined;
readonly italic: boolean | undefined;
}
export interface IColorTheme {
readonly type: ColorScheme;
readonly label: string;
/**
* Resolves the color of the given color identifier. If the theme does not
* specify the color, the default color is returned unless <code>useDefault</code> is set to false.
* @param color the id of the color
* @param useDefault specifies if the default color should be used. If not set, the default is used.
*/
getColor(color: ColorIdentifier, useDefault?: boolean): Color | undefined;
/**
* Returns whether the theme defines a value for the color. If not, that means the
* default color will be used.
*/
defines(color: ColorIdentifier): boolean;
/**
* Returns the token style for a given classification. The result uses the <code>MetadataConsts</code> format
*/
getTokenStyleMetadata(type: string, modifiers: string[], modelLanguage: string): ITokenStyle | undefined;
/**
* List of all colors used with tokens. <code>getTokenStyleMetadata</code> references the colors by index into this list.
*/
readonly tokenColorMap: string[];
/**
* List of all the fonts used with tokens.
*/
readonly tokenFontMap: IFontTokenOptions[];
/**
* Defines whether semantic highlighting should be enabled for the theme.
*/
readonly semanticHighlighting: boolean;
}
export class IFontTokenOptions {
fontFamily?: string;
fontSizeMultiplier?: number;
lineHeightMultiplier?: number;
}
export interface IFileIconTheme {
readonly hasFileIcons: boolean;
readonly hasFolderIcons: boolean;
readonly hidesExplorerArrows: boolean;
}
export interface IProductIconTheme {
/**
* Resolves the definition for the given icon as defined by the theme.
*
* @param iconContribution The icon
*/
getIcon(iconContribution: IconContribution): IconDefinition | undefined;
}
export interface ICssStyleCollector {
addRule(rule: string): void;
}
export interface IThemingParticipant {
(theme: IColorTheme, collector: ICssStyleCollector, environment: IEnvironmentService): void;
}
export interface IThemeService {
readonly _serviceBrand: undefined;
getColorTheme(): IColorTheme;
readonly onDidColorThemeChange: Event<IColorTheme>;
getFileIconTheme(): IFileIconTheme;
readonly onDidFileIconThemeChange: Event<IFileIconTheme>;
getProductIconTheme(): IProductIconTheme;
readonly onDidProductIconThemeChange: Event<IProductIconTheme>;
}
// static theming participant
export const Extensions = {
ThemingContribution: 'base.contributions.theming'
};
export interface IThemingRegistry {
/**
* Register a theming participant that is invoked on every theme change.
*/
onColorThemeChange(participant: IThemingParticipant): IDisposable;
getThemingParticipants(): IThemingParticipant[];
readonly onThemingParticipantAdded: Event<IThemingParticipant>;
}
class ThemingRegistry extends Disposable implements IThemingRegistry {
private themingParticipants: IThemingParticipant[] = [];
private readonly onThemingParticipantAddedEmitter: Emitter<IThemingParticipant>;
constructor() {
super();
this.themingParticipants = [];
this.onThemingParticipantAddedEmitter = this._register(new Emitter<IThemingParticipant>());
}
public onColorThemeChange(participant: IThemingParticipant): IDisposable {
this.onThemingParticipantAddedEmitter.fire(participant);
return toDisposable(() => {
const idx = this.themingParticipants.indexOf(participant);
this.themingParticipants.splice(idx, 1);
}
public get onThemingParticipantAdded(): Event<IThemingParticipant> {
return this.onThemingParticipantAddedEmitter.event;
}
public getThemingParticipants(): IThemingParticipant[] {
return this.themingParticipants;
}
const themingRegistry = new ThemingRegistry();
platform.Registry.add(Extensions.ThemingContribution, themingRegistry);
export function registerThemingParticipant(participant: IThemingParticipant): IDisposable {
}
/**
* Utility base class for all themable components.
*/
export class Themable extends Disposable {
protected theme: IColorTheme;
constructor(
protected themeService: IThemeService
) {
super();
this.theme = themeService.getColorTheme();
// Hook up to theme changes
this._register(this.themeService.onDidColorThemeChange(theme => this.onThemeChange(theme)));
}
protected onThemeChange(theme: IColorTheme): void {
this.theme = theme;
this.updateStyles();
}
updateStyles(): void {
// Subclasses to override
}
protected getColor(id: string, modify?: (color: Color, theme: IColorTheme) => Color): string | null {
let color = this.theme.getColor(id);
if (color && modify) {
color = modify(color, this.theme);
}
return color ? color.toString() : null;
}
export interface IPartsSplash {
zoomLevel: number | undefined;
baseTheme: ThemeTypeSelector;
colorInfo: {
background: string;
foreground: string | undefined;
editorBackground: string | undefined;
titleBarBackground: string | undefined;
titleBarBorder: string | undefined;
activityBarBackground: string | undefined;
activityBarBorder: string | undefined;
sideBarBackground: string | undefined;
sideBarBorder: string | undefined;
panelBackground: string | undefined;
editorGroupBorder: string | undefined;
agentsPanelBackground: string | undefined;
agentsPanelBorder: string | undefined;
statusBarBackground: string | undefined;
statusBarBorder: string | undefined;
statusBarNoFolderBackground: string | undefined;
windowBorder: string | undefined;
};
layoutInfo: {
sideBarSide: string;
editorPartMinWidth: number;
titleBarHeight: number;
activityBarWidth: number;
sideBarWidth: number;
auxiliaryBarWidth: number;
statusBarHeight: number;
windowBorder: boolean;
windowBorderRadius: string | undefined;
modernUI: boolean;
partBounds: {
sideBar: { top: number; left: number; width: number; height: number } | undefined;
auxiliaryBar: { top: number; left: number; width: number; height: number } | undefined;
panel: { top: number; left: number; width: number; height: number } | undefined;
editor: { top: number; left: number; width: number; height: number } | undefined;
} | undefined;
} | undefined;
}