UNPKG

@sussudio/platform

Version:

Internal APIs for VS Code's service injection the base services.

234 lines (233 loc) 8.06 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { RunOnceScheduler } from '@sussudio/base/common/async.mjs'; import { Codicon, CSSIcon } from '@sussudio/base/common/codicons.mjs'; import { Emitter } from '@sussudio/base/common/event.mjs'; import { isString } from '@sussudio/base/common/types.mjs'; import { URI } from '@sussudio/base/common/uri.mjs'; import { localize } from 'vscode-nls.mjs'; import { Extensions as JSONExtensions } from '../../jsonschemas/common/jsonContributionRegistry.mjs'; import * as platform from '../../registry/common/platform.mjs'; import { ThemeIcon } from './themeService.mjs'; // icon registry export const Extensions = { IconContribution: 'base.contributions.icons', }; export var IconContribution; (function (IconContribution) { function getDefinition(contribution, registry) { let definition = contribution.defaults; while (ThemeIcon.isThemeIcon(definition)) { const c = iconRegistry.getIcon(definition.id); if (!c) { return undefined; } definition = c.defaults; } return definition; } IconContribution.getDefinition = getDefinition; })(IconContribution || (IconContribution = {})); export var IconFontDefinition; (function (IconFontDefinition) { function toJSONObject(iconFont) { return { weight: iconFont.weight, style: iconFont.style, src: iconFont.src.map((s) => ({ format: s.format, location: s.location.toString() })), }; } IconFontDefinition.toJSONObject = toJSONObject; function fromJSONObject(json) { const stringOrUndef = (s) => (isString(s) ? s : undefined); if (json && Array.isArray(json.src) && json.src.every((s) => isString(s.format) && isString(s.location))) { return { weight: stringOrUndef(json.weight), style: stringOrUndef(json.style), src: json.src.map((s) => ({ format: s.format, location: URI.parse(s.location) })), }; } return undefined; } IconFontDefinition.fromJSONObject = fromJSONObject; })(IconFontDefinition || (IconFontDefinition = {})); class IconRegistry { _onDidChange = new Emitter(); onDidChange = this._onDidChange.event; iconsById; iconSchema = { definitions: { icons: { type: 'object', properties: { 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.', ), }, fontCharacter: { type: 'string', description: localize( 'iconDefinition.fontCharacter', 'The font character associated with the icon definition.', ), }, }, additionalProperties: false, defaultSnippets: [{ body: { fontCharacter: '\\\\e030' } }], }, }, type: 'object', properties: {}, }; iconReferenceSchema = { type: 'string', pattern: `^${CSSIcon.iconNameExpression}$`, enum: [], enumDescriptions: [] }; iconFontsById; constructor() { this.iconsById = {}; this.iconFontsById = {}; } registerIcon(id, defaults, description, deprecationMessage) { const existing = this.iconsById[id]; if (existing) { if (description && !existing.description) { existing.description = description; this.iconSchema.properties[id].markdownDescription = `${description} $(${id})`; const enumIndex = this.iconReferenceSchema.enum.indexOf(id); if (enumIndex !== -1) { this.iconReferenceSchema.enumDescriptions[enumIndex] = description; } this._onDidChange.fire(); } return existing; } const iconContribution = { id, description, defaults, deprecationMessage }; this.iconsById[id] = iconContribution; const propertySchema = { $ref: '#/definitions/icons' }; if (deprecationMessage) { propertySchema.deprecationMessage = deprecationMessage; } if (description) { propertySchema.markdownDescription = `${description}: $(${id})`; } this.iconSchema.properties[id] = propertySchema; this.iconReferenceSchema.enum.push(id); this.iconReferenceSchema.enumDescriptions.push(description || ''); this._onDidChange.fire(); return { id }; } deregisterIcon(id) { delete this.iconsById[id]; delete this.iconSchema.properties[id]; const index = this.iconReferenceSchema.enum.indexOf(id); if (index !== -1) { this.iconReferenceSchema.enum.splice(index, 1); this.iconReferenceSchema.enumDescriptions.splice(index, 1); } this._onDidChange.fire(); } getIcons() { return Object.keys(this.iconsById).map((id) => this.iconsById[id]); } getIcon(id) { return this.iconsById[id]; } getIconSchema() { return this.iconSchema; } getIconReferenceSchema() { return this.iconReferenceSchema; } registerIconFont(id, definition) { const existing = this.iconFontsById[id]; if (existing) { return existing; } this.iconFontsById[id] = definition; this._onDidChange.fire(); return definition; } deregisterIconFont(id) { delete this.iconFontsById[id]; } getIconFont(id) { return this.iconFontsById[id]; } toString() { const sorter = (i1, i2) => { return i1.id.localeCompare(i2.id); }; const classNames = (i) => { while (ThemeIcon.isThemeIcon(i.defaults)) { i = this.iconsById[i.defaults.id]; } return `codicon codicon-${i ? i.id : ''}`; }; const reference = []; reference.push( `| preview | identifier | default codicon ID | description`, ); reference.push( `| ----------- | --------------------------------- | --------------------------------- | --------------------------------- |`, ); const contributions = Object.keys(this.iconsById).map((key) => this.iconsById[key]); for (const i of contributions.filter((i) => !!i.description).sort(sorter)) { reference.push( `|<i class="${classNames(i)}"></i>|${i.id}|${ThemeIcon.isThemeIcon(i.defaults) ? i.defaults.id : i.id}|${ i.description || '' }|`, ); } reference.push(`| preview | identifier `); reference.push(`| ----------- | --------------------------------- |`); for (const i of contributions.filter((i) => !ThemeIcon.isThemeIcon(i.defaults)).sort(sorter)) { reference.push(`|<i class="${classNames(i)}"></i>|${i.id}|`); } return reference.join('\n'); } } const iconRegistry = new IconRegistry(); platform.Registry.add(Extensions.IconContribution, iconRegistry); export function registerIcon(id, defaults, description, deprecationMessage) { return iconRegistry.registerIcon(id, defaults, description, deprecationMessage); } export function getIconRegistry() { return iconRegistry; } function initialize() { for (const icon of Codicon.getAll()) { iconRegistry.registerIcon(icon.id, icon.definition, icon.description); } } initialize(); export const iconsSchemaId = 'vscode://schemas/icons'; const schemaRegistry = platform.Registry.as(JSONExtensions.JSONContribution); schemaRegistry.registerSchema(iconsSchemaId, iconRegistry.getIconSchema()); const delayer = new RunOnceScheduler(() => schemaRegistry.notifySchemaChanged(iconsSchemaId), 200); iconRegistry.onDidChange(() => { if (!delayer.isScheduled()) { delayer.schedule(); } }); //setTimeout(_ => console.log(iconRegistry.toString()), 5000); // common icons export const widgetClose = registerIcon( 'widget-close', Codicon.close, localize('widgetClose', 'Icon for the close action in widgets.'), ); export const gotoPreviousLocation = registerIcon( 'goto-previous-location', Codicon.arrowUp, localize('previousChangeIcon', 'Icon for goto previous editor location.'), ); export const gotoNextLocation = registerIcon( 'goto-next-location', Codicon.arrowDown, localize('nextChangeIcon', 'Icon for goto next editor location.'), ); export const syncing = ThemeIcon.modify(Codicon.sync, 'spin'); export const spinningLoading = ThemeIcon.modify(Codicon.loading, 'spin');