iconRegistry.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /*---------------------------------------------------------------------------------------------
  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. import { RunOnceScheduler } from '../../../base/common/async.js';
  6. import * as Codicons from '../../../base/common/codicons.js';
  7. import { Emitter } from '../../../base/common/event.js';
  8. import { localize } from '../../../nls.js';
  9. import { Extensions as JSONExtensions } from '../../jsonschemas/common/jsonContributionRegistry.js';
  10. import * as platform from '../../registry/common/platform.js';
  11. import { ThemeIcon } from './themeService.js';
  12. // ------ API types
  13. // icon registry
  14. export const Extensions = {
  15. IconContribution: 'base.contributions.icons'
  16. };
  17. class IconRegistry {
  18. constructor() {
  19. this._onDidChange = new Emitter();
  20. this.onDidChange = this._onDidChange.event;
  21. this.iconSchema = {
  22. definitions: {
  23. icons: {
  24. type: 'object',
  25. properties: {
  26. fontId: { type: 'string', description: localize('iconDefintion.fontId', 'The id of the font to use. If not set, the font that is defined first is used.') },
  27. fontCharacter: { type: 'string', description: localize('iconDefintion.fontCharacter', 'The font character associated with the icon definition.') }
  28. },
  29. additionalProperties: false,
  30. defaultSnippets: [{ body: { fontCharacter: '\\\\e030' } }]
  31. }
  32. },
  33. type: 'object',
  34. properties: {}
  35. };
  36. this.iconReferenceSchema = { type: 'string', pattern: `^${Codicons.CSSIcon.iconNameExpression}$`, enum: [], enumDescriptions: [] };
  37. this.iconsById = {};
  38. this.iconFontsById = {};
  39. }
  40. registerIcon(id, defaults, description, deprecationMessage) {
  41. const existing = this.iconsById[id];
  42. if (existing) {
  43. if (description && !existing.description) {
  44. existing.description = description;
  45. this.iconSchema.properties[id].markdownDescription = `${description} $(${id})`;
  46. const enumIndex = this.iconReferenceSchema.enum.indexOf(id);
  47. if (enumIndex !== -1) {
  48. this.iconReferenceSchema.enumDescriptions[enumIndex] = description;
  49. }
  50. this._onDidChange.fire();
  51. }
  52. return existing;
  53. }
  54. let iconContribution = { id, description, defaults, deprecationMessage };
  55. this.iconsById[id] = iconContribution;
  56. let propertySchema = { $ref: '#/definitions/icons' };
  57. if (deprecationMessage) {
  58. propertySchema.deprecationMessage = deprecationMessage;
  59. }
  60. if (description) {
  61. propertySchema.markdownDescription = `${description}: $(${id})`;
  62. }
  63. this.iconSchema.properties[id] = propertySchema;
  64. this.iconReferenceSchema.enum.push(id);
  65. this.iconReferenceSchema.enumDescriptions.push(description || '');
  66. this._onDidChange.fire();
  67. return { id };
  68. }
  69. getIcons() {
  70. return Object.keys(this.iconsById).map(id => this.iconsById[id]);
  71. }
  72. getIcon(id) {
  73. return this.iconsById[id];
  74. }
  75. getIconSchema() {
  76. return this.iconSchema;
  77. }
  78. getIconFont(id) {
  79. return this.iconFontsById[id];
  80. }
  81. toString() {
  82. const sorter = (i1, i2) => {
  83. return i1.id.localeCompare(i2.id);
  84. };
  85. const classNames = (i) => {
  86. while (ThemeIcon.isThemeIcon(i.defaults)) {
  87. i = this.iconsById[i.defaults.id];
  88. }
  89. return `codicon codicon-${i ? i.id : ''}`;
  90. };
  91. let reference = [];
  92. reference.push(`| preview | identifier | default codicon ID | description`);
  93. reference.push(`| ----------- | --------------------------------- | --------------------------------- | --------------------------------- |`);
  94. const contributions = Object.keys(this.iconsById).map(key => this.iconsById[key]);
  95. for (const i of contributions.filter(i => !!i.description).sort(sorter)) {
  96. reference.push(`|<i class="${classNames(i)}"></i>|${i.id}|${ThemeIcon.isThemeIcon(i.defaults) ? i.defaults.id : i.id}|${i.description || ''}|`);
  97. }
  98. reference.push(`| preview | identifier `);
  99. reference.push(`| ----------- | --------------------------------- |`);
  100. for (const i of contributions.filter(i => !ThemeIcon.isThemeIcon(i.defaults)).sort(sorter)) {
  101. reference.push(`|<i class="${classNames(i)}"></i>|${i.id}|`);
  102. }
  103. return reference.join('\n');
  104. }
  105. }
  106. const iconRegistry = new IconRegistry();
  107. platform.Registry.add(Extensions.IconContribution, iconRegistry);
  108. export function registerIcon(id, defaults, description, deprecationMessage) {
  109. return iconRegistry.registerIcon(id, defaults, description, deprecationMessage);
  110. }
  111. export function getIconRegistry() {
  112. return iconRegistry;
  113. }
  114. function initialize() {
  115. for (const icon of Codicons.iconRegistry.all) {
  116. iconRegistry.registerIcon(icon.id, icon.definition, icon.description);
  117. }
  118. Codicons.iconRegistry.onDidRegister(icon => iconRegistry.registerIcon(icon.id, icon.definition, icon.description));
  119. }
  120. initialize();
  121. export const iconsSchemaId = 'vscode://schemas/icons';
  122. let schemaRegistry = platform.Registry.as(JSONExtensions.JSONContribution);
  123. schemaRegistry.registerSchema(iconsSchemaId, iconRegistry.getIconSchema());
  124. const delayer = new RunOnceScheduler(() => schemaRegistry.notifySchemaChanged(iconsSchemaId), 200);
  125. iconRegistry.onDidChange(() => {
  126. if (!delayer.isScheduled()) {
  127. delayer.schedule();
  128. }
  129. });
  130. //setTimeout(_ => console.log(iconRegistry.toString()), 5000);
  131. // common icons
  132. export const widgetClose = registerIcon('widget-close', Codicons.Codicon.close, localize('widgetClose', 'Icon for the close action in widgets.'));
  133. export const gotoPreviousLocation = registerIcon('goto-previous-location', Codicons.Codicon.arrowUp, localize('previousChangeIcon', 'Icon for goto previous editor location.'));
  134. export const gotoNextLocation = registerIcon('goto-next-location', Codicons.Codicon.arrowDown, localize('nextChangeIcon', 'Icon for goto next editor location.'));
  135. export const syncing = ThemeIcon.modify(Codicons.Codicon.sync, 'spin');
  136. export const spinningLoading = ThemeIcon.modify(Codicons.Codicon.loading, 'spin');