themeService.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  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 { CSSIcon } from '../../../base/common/codicons.js';
  6. import { Emitter } from '../../../base/common/event.js';
  7. import { Disposable, toDisposable } from '../../../base/common/lifecycle.js';
  8. import { createDecorator } from '../../instantiation/common/instantiation.js';
  9. import * as platform from '../../registry/common/platform.js';
  10. import { ColorScheme } from './theme.js';
  11. export const IThemeService = createDecorator('themeService');
  12. export var ThemeColor;
  13. (function (ThemeColor) {
  14. function isThemeColor(obj) {
  15. return obj && typeof obj === 'object' && typeof obj.id === 'string';
  16. }
  17. ThemeColor.isThemeColor = isThemeColor;
  18. })(ThemeColor || (ThemeColor = {}));
  19. export function themeColorFromId(id) {
  20. return { id };
  21. }
  22. export var ThemeIcon;
  23. (function (ThemeIcon) {
  24. function isThemeIcon(obj) {
  25. return obj && typeof obj === 'object' && typeof obj.id === 'string' && (typeof obj.color === 'undefined' || ThemeColor.isThemeColor(obj.color));
  26. }
  27. ThemeIcon.isThemeIcon = isThemeIcon;
  28. const _regexFromString = new RegExp(`^\\$\\((${CSSIcon.iconNameExpression}(?:${CSSIcon.iconModifierExpression})?)\\)$`);
  29. function fromString(str) {
  30. const match = _regexFromString.exec(str);
  31. if (!match) {
  32. return undefined;
  33. }
  34. let [, name] = match;
  35. return { id: name };
  36. }
  37. ThemeIcon.fromString = fromString;
  38. function modify(icon, modifier) {
  39. let id = icon.id;
  40. const tildeIndex = id.lastIndexOf('~');
  41. if (tildeIndex !== -1) {
  42. id = id.substring(0, tildeIndex);
  43. }
  44. if (modifier) {
  45. id = `${id}~${modifier}`;
  46. }
  47. return { id };
  48. }
  49. ThemeIcon.modify = modify;
  50. function getModifier(icon) {
  51. const tildeIndex = icon.id.lastIndexOf('~');
  52. if (tildeIndex !== -1) {
  53. return icon.id.substring(tildeIndex + 1);
  54. }
  55. return undefined;
  56. }
  57. ThemeIcon.getModifier = getModifier;
  58. function isEqual(ti1, ti2) {
  59. var _a, _b;
  60. return ti1.id === ti2.id && ((_a = ti1.color) === null || _a === void 0 ? void 0 : _a.id) === ((_b = ti2.color) === null || _b === void 0 ? void 0 : _b.id);
  61. }
  62. ThemeIcon.isEqual = isEqual;
  63. function asThemeIcon(codicon, color) {
  64. return { id: codicon.id, color: color ? themeColorFromId(color) : undefined };
  65. }
  66. ThemeIcon.asThemeIcon = asThemeIcon;
  67. ThemeIcon.asClassNameArray = CSSIcon.asClassNameArray;
  68. ThemeIcon.asClassName = CSSIcon.asClassName;
  69. ThemeIcon.asCSSSelector = CSSIcon.asCSSSelector;
  70. })(ThemeIcon || (ThemeIcon = {}));
  71. export function getThemeTypeSelector(type) {
  72. switch (type) {
  73. case ColorScheme.DARK: return 'vs-dark';
  74. case ColorScheme.HIGH_CONTRAST: return 'hc-black';
  75. default: return 'vs';
  76. }
  77. }
  78. // static theming participant
  79. export const Extensions = {
  80. ThemingContribution: 'base.contributions.theming'
  81. };
  82. class ThemingRegistry {
  83. constructor() {
  84. this.themingParticipants = [];
  85. this.themingParticipants = [];
  86. this.onThemingParticipantAddedEmitter = new Emitter();
  87. }
  88. onColorThemeChange(participant) {
  89. this.themingParticipants.push(participant);
  90. this.onThemingParticipantAddedEmitter.fire(participant);
  91. return toDisposable(() => {
  92. const idx = this.themingParticipants.indexOf(participant);
  93. this.themingParticipants.splice(idx, 1);
  94. });
  95. }
  96. getThemingParticipants() {
  97. return this.themingParticipants;
  98. }
  99. }
  100. let themingRegistry = new ThemingRegistry();
  101. platform.Registry.add(Extensions.ThemingContribution, themingRegistry);
  102. export function registerThemingParticipant(participant) {
  103. return themingRegistry.onColorThemeChange(participant);
  104. }
  105. /**
  106. * Utility base class for all themable components.
  107. */
  108. export class Themable extends Disposable {
  109. constructor(themeService) {
  110. super();
  111. this.themeService = themeService;
  112. this.theme = themeService.getColorTheme();
  113. // Hook up to theme changes
  114. this._register(this.themeService.onDidColorThemeChange(theme => this.onThemeChange(theme)));
  115. }
  116. onThemeChange(theme) {
  117. this.theme = theme;
  118. this.updateStyles();
  119. }
  120. updateStyles() {
  121. // Subclasses to override
  122. }
  123. }