iconRegistry.ts ×15

Frontier kind: Code frontier

unlabeled · c_1872c377b483

608 tests · 11611 LOC · 47 files · introduces 0 tests · 257 LOC · 3 files

Introduces — evidence that enters the hierarchy at this concept

Code
18 ranges257 lines · 3 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
1518 ranges11611 lines · 47 files · Browse complete extent
All tests (intent)
608 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

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 native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

3 files ranked by introduced lines: 257 introduced LOC across 18 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/platform/theme/common/iconRegistry.ts 247 introduced LOC · 15 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- iconRegistry.ts
2 > * Copyright (c) Microsoft Corporation. All rights reserved.
3 > * Licensed under the MIT License. See License.txt in the project root for license information.
4 > *--------------------------------------------------------------------------------------------*/
5 >
6 > import { RunOnceScheduler } from '../../../base/common/async.js';
7 > import { Codicon } from '../../../base/common/codicons.js';
8 > import { getCodiconFontCharacters } from '../../../base/common/codiconsUtil.js';
9 > import { ThemeIcon, IconIdentifier } from '../../../base/common/themables.js';
10 > import { Emitter, Event } from '../../../base/common/event.js';
11 > import { IJSONSchema, IJSONSchemaMap } from '../../../base/common/jsonSchema.js';
12 > import { isString } from '../../../base/common/types.js';
13 > import { URI } from '../../../base/common/uri.js';
14 > import { localize } from '../../../nls.js';
15 > import { Extensions as JSONExtensions, IJSONContributionRegistry } from '../../jsonschemas/common/jsonContributionRegistry.js';
16 > import * as platform from '../../registry/common/platform.js';
17 > import { Disposable } from '../../../base/common/lifecycle.js';
18 >
19 > // ------ API types
20 >
21 >
22 > // icon registry
23 > export const Extensions = {
24 > IconContribution: 'base.contributions.icons'
25 > };
26 >
27 > export type IconDefaults = ThemeIcon | IconDefinition;
28 >
29 > export interface IconDefinition {
30 > readonly font?: IconFontContribution; // undefined for the default font (codicon)
31 > readonly fontCharacter: string;
32 > }
33 >
34 >
35 > export interface IconContribution {
36 > readonly id: string;
37 > description: string | undefined;
38 > readonly deprecationMessage?: string;
39 > readonly defaults: IconDefaults;
40 > }
41 >
42 > export namespace IconContribution {
43 > export function getDefinition(contribution: IconContribution, registry: IIconRegistry): IconDefinition | undefined {
44 let definition = contribution.defaults;
45 while (ThemeIcon.isThemeIcon(definition)) {
52 return definition;
53 }
55 >
56 > export interface IconFontContribution {
57 > readonly id: string;
58 > readonly definition: IconFontDefinition;
59 > }
60 >
61 > export interface IconFontDefinition {
62 > readonly weight?: string;
63 > readonly style?: string;
64 > readonly src: IconFontSource[];
65 > }
66 >
67 > export namespace IconFontDefinition {
68 > export function toJSONObject(iconFont: IconFontDefinition): any {
69 return {
70 weight: iconFont.weight,
73 };
74 }
75 > export function fromJSONObject(json: any): IconFontDefinition | undefined { iconRegistry.ts
76 const stringOrUndef = (s: any) => isString(s) ? s : undefined;
77 if (json && Array.isArray(json.src) && json.src.every((s: any) => isString(s.format) && isString(s.location))) {
84 return undefined;
85 }
87 >
88 >
89 > export interface IconFontSource {
90 > readonly location: URI;
91 > readonly format: string;
92 > }
93 >
94 > export interface IIconRegistry {
95 >
96 > readonly onDidChange: Event<void>;
97 >
98 > /**
99 > * Register a icon to the registry.
100 > * @param id The icon id
101 > * @param defaults The default values
102 > * @param description The description
103 > */
104 > registerIcon(id: IconIdentifier, defaults: IconDefaults, description?: string): ThemeIcon;
105 >
106 > /**
107 > * Deregister a icon from the registry.
108 > */
109 > deregisterIcon(id: IconIdentifier): void;
110 >
111 > /**
112 > * Get all icon contributions
113 > */
114 > getIcons(): IconContribution[];
115 >
116 > /**
117 > * Get the icon for the given id
118 > */
119 > getIcon(id: IconIdentifier): IconContribution | undefined;
120 >
121 > /**
122 > * JSON schema for an object to assign icon values to one of the icon contributions.
123 > */
124 > getIconSchema(): IJSONSchema;
125 >
126 > /**
127 > * JSON schema to for a reference to a icon contribution.
128 > */
129 > getIconReferenceSchema(): IJSONSchema;
130 >
131 > /**
132 > * Register a icon font to the registry.
133 > * @param id The icon font id
134 > * @param definition The icon font definition
135 > */
136 > registerIconFont(id: string, definition: IconFontDefinition): IconFontDefinition;
137 >
138 > /**
139 > * Deregister an icon font to the registry.
140 > */
141 > deregisterIconFont(id: string): void;
142 >
143 > /**
144 > * Get the icon font for the given id
145 > */
146 > getIconFont(id: string): IconFontDefinition | undefined;
147 > }
148 >
149 > // regexes for validation of font properties
150 >
151 > export const fontIdRegex = /^([\w_-]+)$/;
152 > export const fontStyleRegex = /^(normal|italic|(oblique[ \w\s-]+))$/;
153 > export const fontWeightRegex = /^(normal|bold|lighter|bolder|(\d{0-1000}))$/;
154 > export const fontSizeRegex = /^([\w_.%+-]+)$/;
155 > export const fontFormatRegex = /^woff|woff2|truetype|opentype|embedded-opentype|svg$/;
156 > export const fontColorRegex = /^#[0-9a-fA-F]{0,6}$/;
157 >
158 > export const fontIdErrorMessage = localize('schema.fontId.formatError', 'The font ID must only contain letters, numbers, underscores and dashes.');
159 >
160 > class IconRegistry extends Disposable implements IIconRegistry {
161 >
162 > private readonly _onDidChange = this._register(new Emitter<void>());
163 > readonly onDidChange: Event<void> = this._onDidChange.event;
164 >
165 > private iconsById: { [key: string]: IconContribution };
166 > private iconSchema: IJSONSchema & { properties: IJSONSchemaMap } = {
167 > definitions: {
168 > icons: {
169 > type: 'object',
170 > properties: {
171 > fontId: { type: 'string', description: localize('iconDefinition.fontId', 'The id of the font to use. If not set, the font that is defined first is used.'), pattern: fontIdRegex.source, patternErrorMessage: fontIdErrorMessage },
172 > fontCharacter: { type: 'string', description: localize('iconDefinition.fontCharacter', 'The font character associated with the icon definition.') }
173 > },
174 > additionalProperties: false,
175 > defaultSnippets: [{ body: { fontCharacter: '\\\\e030' } }]
176 > }
177 > },
178 > type: 'object',
179 > properties: {}
180 > };
181 > private iconReferenceSchema: IJSONSchema & { enum: string[]; enumDescriptions: string[] } = { type: 'string', pattern: `^${ThemeIcon.iconNameExpression}$`, enum: [], enumDescriptions: [] };
182 >
183 > private iconFontsById: { [key: string]: IconFontDefinition };
184 >
185 > constructor() {
186 > super();
187 > this.iconsById = {};
188 > this.iconFontsById = {};
189 > }
190 >
191 > public registerIcon(id: string, defaults: IconDefaults, description?: string, deprecationMessage?: string): ThemeIcon {
192 > const existing = this.iconsById[id];
193 > if (existing) {
194 if (description && !existing.description) {
195 existing.description = description;
203 return existing;
204 }
205 > const iconContribution: IconContribution = { id, description, defaults, deprecationMessage }; iconRegistry.ts
206 > this.iconsById[id] = iconContribution;
207 > const propertySchema: IJSONSchema = { $ref: '#/definitions/icons' };
208 > if (deprecationMessage) {
209 propertySchema.deprecationMessage = deprecationMessage;
210 }
211 > if (description) { iconRegistry.ts
212 > propertySchema.markdownDescription = `${description}: $(${id})`;
213 > }
214 > this.iconSchema.properties[id] = propertySchema;
215 > this.iconReferenceSchema.enum.push(id);
216 > this.iconReferenceSchema.enumDescriptions.push(description || '');
217 >
218 > this._onDidChange.fire();
219 > return { id };
220 > }
221 >
222 >
223 > public deregisterIcon(id: string): void {
224 delete this.iconsById[id];
225 delete this.iconSchema.properties[id];
231 this._onDidChange.fire();
232 }
234 > public getIcons(): IconContribution[] {
235 return Object.keys(this.iconsById).map(id => this.iconsById[id]);
236 }
238 > public getIcon(id: string): IconContribution | undefined {
239 return this.iconsById[id];
240 }
242 > public getIconSchema(): IJSONSchema {
243 > return this.iconSchema;
244 > }
245 >
246 > public getIconReferenceSchema(): IJSONSchema {
247 return this.iconReferenceSchema;
248 }
250 > public registerIconFont(id: string, definition: IconFontDefinition): IconFontDefinition {
251 const existing = this.iconFontsById[id];
252 if (existing) {
257 return definition;
258 }
260 > public deregisterIconFont(id: string): void {
261 delete this.iconFontsById[id];
262 }
264 > public getIconFont(id: string): IconFontDefinition | undefined {
265 return this.iconFontsById[id];
266 }
268 > public override toString() {
269 const sorter = (i1: IconContribution, i2: IconContribution) => {
270 return i1.id.localeCompare(i2.id);
297 return reference.join('\n');
298 }
300 > }
301 >
302 > const iconRegistry = new IconRegistry();
303 > platform.Registry.add(Extensions.IconContribution, iconRegistry);
304 >
305 > export function registerIcon(id: string, defaults: IconDefaults, description: string, deprecationMessage?: string): ThemeIcon {
306 > return iconRegistry.registerIcon(id, defaults, description, deprecationMessage);
307 > }
308 >
309 > export function getIconRegistry(): IIconRegistry {
310 return iconRegistry;
311 }
313 > function initialize() {
314 > const codiconFontCharacters = getCodiconFontCharacters();
315 > for (const icon in codiconFontCharacters) {
316 > const fontCharacter = '\\' + codiconFontCharacters[icon].toString(16);
317 > iconRegistry.registerIcon(icon, { fontCharacter });
318 > }
319 > }
320 > initialize();
321 >
322 > export const iconsSchemaId = 'vscode://schemas/icons';
323 >
324 > const schemaRegistry = platform.Registry.as<IJSONContributionRegistry>(JSONExtensions.JSONContribution);
325 > schemaRegistry.registerSchema(iconsSchemaId, iconRegistry.getIconSchema());
326 >
327 > const delayer = new RunOnceScheduler(() => schemaRegistry.notifySchemaChanged(iconsSchemaId), 200);
328 > iconRegistry.onDidChange(() => {
329 > if (!delayer.isScheduled()) {
330 > delayer.schedule();
331 > }
332 > });
333 >
334 > //setTimeout(_ => console.log(iconRegistry.toString()), 5000);
335 >
336 >
337 > // common icons
338 >
339 > export const widgetClose = registerIcon('widget-close', Codicon.close, localize('widgetClose', 'Icon for the close action in widgets.'));
340 >
341 > export const gotoPreviousLocation = registerIcon('goto-previous-location', Codicon.arrowUp, localize('previousChangeIcon', 'Icon for goto previous editor location.'));
342 > export const gotoNextLocation = registerIcon('goto-next-location', Codicon.arrowDown, localize('nextChangeIcon', 'Icon for goto next editor location.'));
343 >
344 > export const syncing = ThemeIcon.modify(Codicon.sync, 'spin');
345 > export const spinningLoading = ThemeIcon.modify(Codicon.loading, 'spin');
src/vs/base/common/themables.ts 8 introduced LOC · 2 ranges

Open complete file

79
80 export function modify(icon: ThemeIcon, modifier: 'disabled' | 'spin' | undefined): ThemeIcon {
81 > let id = icon.id; themables.ts
82 > const tildeIndex = id.lastIndexOf('~');
83 > if (tildeIndex !== -1) {
84 id = id.substring(0, tildeIndex);
85 }
86 > if (modifier) { themables.ts
87 > id = `${id}~${modifier}`;
88 > }
89 > return { id };
90 > }
91
92 export function getModifier(icon: ThemeIcon): string | undefined {
src/vs/base/common/codiconsUtil.ts 2 introduced LOC · 1 range

Open complete file

25 */
26 export function getCodiconFontCharacters(): { [id: string]: number } {
27 > return _codiconFontCharacters; codiconsUtil.ts
28 > }