From b8be5037e09216e3ffdf0999508d877ddb8f1ec4 Mon Sep 17 00:00:00 2001 From: Alvaro Sanchez-Leon Date: Wed, 14 Jun 2023 16:32:49 -0400 Subject: [PATCH 1/9] Support icon contributions from plugins - in progress --- .../src/browser/icon-theme-contribution.ts | 2 + .../tab-bar-toolbar-registry.ts | 1 + .../src/browser/monaco-frontend-module.ts | 9 ++ .../src/browser/monaco-icon-registry-types.ts | 127 ++++++++++++++++++ .../src/browser/monaco-icon-registry.ts | 59 ++++++++ .../src/browser/monaco-icon-style-sheet.ts | 28 ++++ .../plugin-ext/src/common/plugin-protocol.ts | 31 ++++- .../src/hosted/node/scanners/scanner-theia.ts | 71 +++++++++- .../browser/plugin-contribution-handler.ts | 29 +++- .../browser/plugin-ext-frontend-module.ts | 4 + .../src/main/browser/plugin-icon-service.ts | 97 +++++++++++++ .../webview-frontend-security-warnings.ts | 1 + 12 files changed, 456 insertions(+), 3 deletions(-) create mode 100644 packages/monaco/src/browser/monaco-icon-registry-types.ts create mode 100644 packages/monaco/src/browser/monaco-icon-registry.ts create mode 100644 packages/monaco/src/browser/monaco-icon-style-sheet.ts create mode 100644 packages/plugin-ext/src/main/browser/plugin-icon-service.ts diff --git a/packages/core/src/browser/icon-theme-contribution.ts b/packages/core/src/browser/icon-theme-contribution.ts index 3c1dda5465f30..d5c628f1ff51b 100644 --- a/packages/core/src/browser/icon-theme-contribution.ts +++ b/packages/core/src/browser/icon-theme-contribution.ts @@ -36,6 +36,8 @@ export class IconThemeApplicationContribution implements FrontendApplicationCont protected readonly iconThemeContributions: ContributionProvider; async onStart(): Promise { + console.log('**** alvs, IconThemeApplicationContribution onStart'); + for (const contribution of this.iconThemeContributions.getContributions()) { await contribution.registerIconThemes(this.iconThemes); } diff --git a/packages/core/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.ts b/packages/core/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.ts index 8ea697a7a3ee5..ba72696fbc992 100644 --- a/packages/core/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.ts +++ b/packages/core/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.ts @@ -81,6 +81,7 @@ export class TabBarToolbarRegistry implements FrontendApplicationContribution { throw new Error(`A toolbar item is already registered with the '${id}' ID.`); } this.items.set(id, item); + console.warn('***** alvs: registering tab item: ', item.id); this.fireOnDidChange(); const toDispose = new DisposableCollection( Disposable.create(() => this.fireOnDidChange()), diff --git a/packages/monaco/src/browser/monaco-frontend-module.ts b/packages/monaco/src/browser/monaco-frontend-module.ts index 3c4b2c049a7e7..ad67d59f9f4df 100644 --- a/packages/monaco/src/browser/monaco-frontend-module.ts +++ b/packages/monaco/src/browser/monaco-frontend-module.ts @@ -68,6 +68,9 @@ import { MimeService } from '@theia/core/lib/browser/mime-service'; import { MonacoEditorServices } from './monaco-editor'; import { MonacoColorRegistry } from './monaco-color-registry'; import { ColorRegistry } from '@theia/core/lib/browser/color-registry'; +import { IconRegistry, IconStyleSheetService } from './monaco-icon-registry-types'; +import { MonacoIconRegistry } from './monaco-icon-registry'; +import { MonacoIconStyleSheetService } from './monaco-icon-style-sheet'; import { MonacoThemingService } from './monaco-theming-service'; import { bindContributionProvider } from '@theia/core'; import { WorkspaceSymbolCommand } from './workspace-symbol-command'; @@ -186,6 +189,12 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { bind(ThemeServiceWithDB).toSelf().inSingletonScope(); rebind(ThemeService).toService(ThemeServiceWithDB); + + bind(MonacoIconRegistry).toSelf().inSingletonScope(); + bind(IconRegistry).toService(MonacoIconRegistry); + + bind(MonacoIconStyleSheetService).toSelf().inSingletonScope(); + bind(IconStyleSheetService).toService(MonacoIconStyleSheetService); }); export const MonacoConfigurationService = Symbol('MonacoConfigurationService'); diff --git a/packages/monaco/src/browser/monaco-icon-registry-types.ts b/packages/monaco/src/browser/monaco-icon-registry-types.ts new file mode 100644 index 0000000000000..22ef36c55213b --- /dev/null +++ b/packages/monaco/src/browser/monaco-icon-registry-types.ts @@ -0,0 +1,127 @@ + +// ***************************************************************************** +// Copyright (C) 2023 Ericsson and others. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0. +// +// This Source Code may also be made available under the following Secondary +// Licenses when the conditions for such availability set forth in the Eclipse +// Public License v. 2.0 are satisfied: GNU General Public License, version 2 +// with the GNU Classpath Exception which is available at +// https://www.gnu.org/software/classpath/license.html. +// +// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 +// ***************************************************************************** +import { Event } from '@theia/core'; +import { IJSONSchema } from '@theia/core/lib/common/json-schema'; +import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/themeService'; +import { URI } from '@theia/core/shared/vscode-uri'; + +// ------ API types + +export type IconIdentifier = string; + +// icon registry +export const Extensions = { + IconContribution: 'base.contributions.icons' +}; + +export type IconDefaults = ThemeIcon | IconDefinition; + +export interface IconDefinition { + font?: IconFontContribution; // undefined for the default font (codicon) + fontCharacter: string; +} + +export interface IconContribution { + readonly id: string; + description: string | undefined; + deprecationMessage?: string; + readonly defaults: IconDefaults; +} + +export interface IconFontContribution { + readonly id: string; + readonly definition: IconFontDefinition; +} + +export interface IconFontDefinition { + readonly weight?: string; + readonly style?: string; + readonly src: IconFontSource[]; +} + +export interface IconFontSource { + readonly location: URI; + readonly format: string; +} + +export const IconRegistry = Symbol('IconRegistry'); +export interface IconRegistry { + + readonly onDidChange: Event; + + /** + * Register a icon to the registry. + * @param id The icon id + * @param defaults The default values + * @param description The description + */ + registerIcon(id: IconIdentifier, defaults: IconDefaults, description?: string): ThemeIcon; + + /** + * Deregister a icon from the registry. + */ + deregisterIcon(id: IconIdentifier): void; + + /** + * Get all icon contributions + */ + getIcons(): IconContribution[]; + + /** + * Get the icon for the given id + */ + getIcon(id: IconIdentifier): IconContribution | undefined; + + /** + * JSON schema for an object to assign icon values to one of the icon contributions. + */ + getIconSchema(): IJSONSchema; + + /** + * JSON schema to for a reference to a icon contribution. + */ + getIconReferenceSchema(): IJSONSchema; + + /** + * Register a icon font to the registry. + * @param id The icon font id + * @param definition The icon font definition + */ + registerIconFont(id: string, definition: IconFontDefinition): IconFontDefinition; + + /** + * Deregister an icon font to the registry. + */ + deregisterIconFont(id: string): void; + + /** + * Get the icon font for the given id + */ + getIconFont(id: string): IconFontDefinition | undefined; +} + +export const IconsStyleSheet = Symbol('IconsStyleSheet'); +export interface IconsStyleSheet { + getCSS(): string; + readonly onDidChange: Event; +} + +export const IconStyleSheetService = Symbol('IconStyleSheetService'); +export interface IconStyleSheetService { + getIconsStyleSheet(): IconsStyleSheet; +} + diff --git a/packages/monaco/src/browser/monaco-icon-registry.ts b/packages/monaco/src/browser/monaco-icon-registry.ts new file mode 100644 index 0000000000000..ba91f620cd647 --- /dev/null +++ b/packages/monaco/src/browser/monaco-icon-registry.ts @@ -0,0 +1,59 @@ + +// ***************************************************************************** +// Copyright (C) 2023 Ericsson and others. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0. +// +// This Source Code may also be made available under the following Secondary +// Licenses when the conditions for such availability set forth in the Eclipse +// Public License v. 2.0 are satisfied: GNU General Public License, version 2 +// with the GNU Classpath Exception which is available at +// https://www.gnu.org/software/classpath/license.html. +// +// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 +// ***************************************************************************** + +import { injectable } from '@theia/core/shared/inversify'; +import * as monaco from '@theia/monaco-editor-core/esm/vs/platform/theme/common/iconRegistry'; +import { IconContribution, IconDefaults, IconFontDefinition, IconRegistry } from './monaco-icon-registry-types'; +import { Event } from '@theia/core'; +import { IJSONSchema } from '@theia/core/lib/common/json-schema'; +import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/themeService'; + +@injectable() +export class MonacoIconRegistry implements IconRegistry { + protected readonly iconRegistry = monaco.getIconRegistry(); + + onDidChange: Event = this.iconRegistry.onDidChange; + + registerIcon(id: string, defaults: IconDefaults, description?: string | undefined): ThemeIcon { + return this.iconRegistry.registerIcon(id, defaults, description); + } + deregisterIcon(id: string): void { + return this.iconRegistry.deregisterIcon(id); + } + getIcons(): IconContribution[] { + return this.iconRegistry.getIcons(); + } + getIcon(id: string): IconContribution | undefined { + return this.iconRegistry.getIcon(id); + } + getIconSchema(): IJSONSchema { + return this.iconRegistry.getIconSchema(); + } + getIconReferenceSchema(): IJSONSchema { + return this.iconRegistry.getIconReferenceSchema(); + } + registerIconFont(id: string, definition: IconFontDefinition): IconFontDefinition { + return this.iconRegistry.registerIconFont(id, definition); + } + deregisterIconFont(id: string): void { + return this.iconRegistry.deregisterIconFont(id); + } + getIconFont(id: string): IconFontDefinition | undefined { + return this.iconRegistry.getIconFont(id); + } + +} diff --git a/packages/monaco/src/browser/monaco-icon-style-sheet.ts b/packages/monaco/src/browser/monaco-icon-style-sheet.ts new file mode 100644 index 0000000000000..6d3678a02a422 --- /dev/null +++ b/packages/monaco/src/browser/monaco-icon-style-sheet.ts @@ -0,0 +1,28 @@ + +// ***************************************************************************** +// Copyright (C) 2023 Ericsson and others. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0. +// +// This Source Code may also be made available under the following Secondary +// Licenses when the conditions for such availability set forth in the Eclipse +// Public License v. 2.0 are satisfied: GNU General Public License, version 2 +// with the GNU Classpath Exception which is available at +// https://www.gnu.org/software/classpath/license.html. +// +// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 +// ***************************************************************************** + +import { injectable } from '@theia/core/shared/inversify'; +import { getIconsStyleSheet } from '@theia/monaco-editor-core/esm/vs/platform/theme/browser/iconsStyleSheet'; +import { IconsStyleSheet } from './monaco-icon-registry-types'; + +@injectable() +export class MonacoIconStyleSheetService { + protected getIconsStyleSheet(): IconsStyleSheet { + return getIconsStyleSheet(undefined); + } + +} diff --git a/packages/plugin-ext/src/common/plugin-protocol.ts b/packages/plugin-ext/src/common/plugin-protocol.ts index 32f27ae6178ba..50b293725f3e0 100644 --- a/packages/plugin-ext/src/common/plugin-protocol.ts +++ b/packages/plugin-ext/src/common/plugin-protocol.ts @@ -17,7 +17,7 @@ import { RpcServer } from '@theia/core/lib/common/messaging/proxy-factory'; import { RPCProtocol } from './rpc-protocol'; import { Disposable } from '@theia/core/lib/common/disposable'; import { LogPart, KeysToAnyValues, KeysToKeysToAnyValue } from './types'; -import { CharacterPair, CommentRule, PluginAPIFactory, Plugin } from './plugin-api-rpc'; +import { CharacterPair, CommentRule, PluginAPIFactory, Plugin, ThemeIcon } from './plugin-api-rpc'; import { ExtPluginApi } from './plugin-ext-api-contribution'; import { IJSONSchema, IJSONSchemaSnippet } from '@theia/core/lib/common/json-schema'; import { RecursivePartial } from '@theia/core/lib/common/types'; @@ -90,6 +90,7 @@ export interface PluginPackageContribution { snippets?: PluginPackageSnippetsContribution[]; themes?: PluginThemeContribution[]; iconThemes?: PluginIconThemeContribution[]; + icons?: PluginIconContribution[]; colors?: PluginColorContribution[]; taskDefinitions?: PluginTaskDefinitionContribution[]; problemMatchers?: PluginProblemMatcherContribution[]; @@ -253,6 +254,13 @@ export interface PluginIconThemeContribution { uiTheme?: PluginUiTheme; } +export interface PluginIconContribution { + [id: string]: { + description: string; + default: { fontPath: string; fontCharacter: string } | string; + }; +} + export interface PlatformSpecificAdapterContribution { program?: string; args?: string[]; @@ -577,6 +585,7 @@ export interface PluginContribution { snippets?: SnippetContribution[]; themes?: ThemeContribution[]; iconThemes?: IconThemeContribution[]; + icons?: IconContribution[]; colors?: ColorDefinition[]; taskDefinitions?: TaskDefinition[]; problemMatchers?: ProblemMatcherContribution[]; @@ -644,6 +653,26 @@ export interface IconThemeContribution { uiTheme?: UiTheme; } +export interface IconDefinition { + fontCharacter: string; + location: string; +} + +export type IconDefaults = ThemeIcon | IconDefinition; + +export interface IconContribution { + id: string; + extensionId: string; + description: string | undefined; + defaults: IconDefaults; +} + +export namespace IconContribution { + export function isIconDefinition(defaults: IconDefaults): defaults is IconDefinition { + return 'fontCharacter' in defaults; + } +} + export interface GrammarsContribution { format: 'json' | 'plist'; language?: string; diff --git a/packages/plugin-ext/src/hosted/node/scanners/scanner-theia.ts b/packages/plugin-ext/src/hosted/node/scanners/scanner-theia.ts index 28306abb2af04..1923ade494e48 100644 --- a/packages/plugin-ext/src/hosted/node/scanners/scanner-theia.ts +++ b/packages/plugin-ext/src/hosted/node/scanners/scanner-theia.ts @@ -23,6 +23,7 @@ import { buildFrontendModuleName, DebuggerContribution, IconThemeContribution, + IconContribution, IconUrl, Keybinding, LanguageConfiguration, @@ -60,7 +61,8 @@ import { PluginPackageTranslation, Translation, PluginIdentifiers, - TerminalProfile + TerminalProfile, + PluginIconContribution } from '../../../common/plugin-protocol'; import * as fs from 'fs'; import * as path from 'path'; @@ -73,6 +75,7 @@ import { deepClone } from '@theia/core/lib/common/objects'; import { PreferenceSchema, PreferenceSchemaProperties } from '@theia/core/lib/common/preferences/preference-schema'; import { TaskDefinition } from '@theia/task/lib/common/task-protocol'; import { ColorDefinition } from '@theia/core/lib/common/color'; +import { CSSIcon } from '@theia/core/lib/common/markdown-rendering/icon-utilities'; import { PluginUriFactory } from './plugin-uri-factory'; namespace nls { @@ -88,6 +91,12 @@ const INTERNAL_CONSOLE_OPTIONS_SCHEMA = { }; const colorIdPattern = '^\\w+[.\\w+]*$'; +const iconIdPattern = `^${CSSIcon.iconNameSegment}(-${CSSIcon.iconNameSegment})+$`; + +function getFileExtension(filePath: string): string { + const index = filePath.lastIndexOf('.'); + return index === -1 ? '' : filePath.substring(index + 1); +} @injectable() export class TheiaPluginScanner implements PluginScanner { @@ -145,6 +154,7 @@ export class TheiaPluginScanner implements PluginScanner { } getContribution(rawPlugin: PluginPackage): PluginContribution | undefined { + console.warn('**** alvs, scanner-theia.ts#getContribution: ', rawPlugin.name); if (!rawPlugin.contributes && !rawPlugin.activationEvents) { return undefined; } @@ -342,6 +352,12 @@ export class TheiaPluginScanner implements PluginScanner { console.error(`Could not read '${rawPlugin.name}' contribution 'themes'.`, rawPlugin.contributes.themes, err); } + try { + contributions.icons = this.readIcons(rawPlugin); + } catch (err) { + console.error(`Could not read '${rawPlugin.name}' contribution 'icons'.`, rawPlugin.contributes.icons, err); + } + try { contributions.iconThemes = this.readIconThemes(rawPlugin); } catch (err) { @@ -512,6 +528,59 @@ export class TheiaPluginScanner implements PluginScanner { return result; } + protected readIcons(pck: PluginPackage): IconContribution[] | undefined { + if (!pck.contributes || !pck.contributes.icons) { + return undefined; + } + const result: IconContribution[] = []; + const iconEntries = (pck.contributes.icons); + for (const id in iconEntries) { + if (pck.contributes.icons.hasOwnProperty(id)) { + if (!id.match(iconIdPattern)) { + console.error("'configuration.icons' keys represent the icon id and can only contain letter, digits and minuses. " + + 'They need to consist of at least two segments in the form `component-iconname`.', 'extension: ', pck.name, 'icon id: ', id); + return; + } + const iconContribution = iconEntries[id]; + if (typeof iconContribution.description !== 'string' || iconContribution.description['length'] === 0) { + console.error('configuration.icons.description must be defined and can not be empty, ', 'extension: ', pck.name, 'icon id: ', id); + return; + } + + const defaultIcon = iconContribution.default; + if (typeof defaultIcon === 'string') { + result.push({ + id, + extensionId: pck.publisher + '.' + pck.name, + description: iconContribution.description, + defaults: { id: defaultIcon } + }); + } else if (typeof defaultIcon === 'object' && typeof defaultIcon.fontPath === 'string' && typeof defaultIcon.fontCharacter === 'string') { + const format = getFileExtension(defaultIcon.fontPath); + if (['woff', 'woff2', 'ttf'].indexOf(format) === -1) { + console.warn("Expected `contributes.icons.default.fontPath` to have file extension 'woff', woff2' or 'ttf', is '{0}'.", format); + return; + } + + const iconFontLocation = this.pluginUriFactory.createUri(pck, defaultIcon.fontPath).toString(); + result.push({ + id, + extensionId: pck.publisher + '.' + pck.name, + description: iconContribution.description, + defaults: { + fontCharacter: defaultIcon.fontCharacter, + location: iconFontLocation + } + }); + } else { + console.error("'configuration.icons.default' must be either a reference to the id of an other theme icon (string) or a icon definition (object) with ", + 'properties `fontPath` and `fontCharacter`.'); + } + } + } + return result; + } + protected readSnippets(pck: PluginPackage): SnippetContribution[] | undefined { if (!pck.contributes || !pck.contributes.snippets) { return undefined; diff --git a/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts b/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts index fe671d99b6dd3..ddabc67008377 100644 --- a/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts +++ b/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts @@ -21,7 +21,17 @@ import { TextmateRegistry, getEncodedLanguageId, MonacoTextmateService, GrammarD import { MenusContributionPointHandler } from './menus/menus-contribution-handler'; import { PluginViewRegistry } from './view/plugin-view-registry'; import { PluginCustomEditorRegistry } from './custom-editors/plugin-custom-editor-registry'; -import { PluginContribution, IndentationRules, FoldingRules, ScopeMap, DeployedPlugin, GrammarsContribution, EnterAction, OnEnterRule, RegExpOptions } from '../../common'; +import { + PluginContribution, + IndentationRules, + FoldingRules, + ScopeMap, + DeployedPlugin, + GrammarsContribution, + EnterAction, + OnEnterRule, + RegExpOptions, + IconContribution } from '../../common'; import { DefaultUriLabelProviderContribution, LabelProviderContribution, @@ -39,6 +49,7 @@ import { PluginDebugService } from './debug/plugin-debug-service'; import { DebugSchemaUpdater } from '@theia/debug/lib/browser/debug-schema-updater'; import { MonacoThemingService } from '@theia/monaco/lib/browser/monaco-theming-service'; import { ColorRegistry } from '@theia/core/lib/browser/color-registry'; +import { PluginIconService } from './plugin-icon-service'; import { PluginIconThemeService } from './plugin-icon-theme-service'; import { ContributionProvider } from '@theia/core/lib/common'; import * as monaco from '@theia/monaco-editor-core'; @@ -108,6 +119,9 @@ export class PluginContributionHandler { @inject(ColorRegistry) protected readonly colors: ColorRegistry; + @inject(PluginIconService) + protected readonly iconService: PluginIconService; + @inject(PluginIconThemeService) protected readonly iconThemeService: PluginIconThemeService; @@ -322,6 +336,19 @@ export class PluginContributionHandler { } } + if (contributions.icons && contributions.icons.length) { + for (const icon of contributions.icons) { + const defaultIcon = icon.defaults; + let key: string; + if (IconContribution.isIconDefinition(defaultIcon)) { + key = defaultIcon.location; + } else { + key = defaultIcon.id; + } + pushContribution(`icons.${key}`, () => this.iconService.register(icon, plugin)); + } + } + const colors = contributions.colors; if (colors) { pushContribution('colors', () => this.colors.register(...colors)); diff --git a/packages/plugin-ext/src/main/browser/plugin-ext-frontend-module.ts b/packages/plugin-ext/src/main/browser/plugin-ext-frontend-module.ts index f737307a54961..6bf19e5985ef1 100644 --- a/packages/plugin-ext/src/main/browser/plugin-ext-frontend-module.ts +++ b/packages/plugin-ext/src/main/browser/plugin-ext-frontend-module.ts @@ -80,6 +80,7 @@ import { bindTreeViewDecoratorUtilities, TreeViewDecoratorService } from './view import { CodeEditorWidgetUtil } from './menus/vscode-theia-menu-mappings'; import { PluginMenuCommandAdapter } from './menus/plugin-menu-command-adapter'; import './theme-icon-override'; +import { PluginIconService } from './plugin-icon-service'; import { PluginTerminalRegistry } from './plugin-terminal-registry'; import { DnDFileContentStore } from './view/dnd-file-content-store'; import { WebviewContextKeys } from './webview/webview-context-keys'; @@ -248,6 +249,9 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { bind(WebviewFrontendSecurityWarnings).toSelf().inSingletonScope(); bind(FrontendApplicationContribution).toService(WebviewFrontendSecurityWarnings); + bind(PluginIconService).toSelf().inSingletonScope(); + bind(FrontendApplicationContribution).toService(PluginIconService); + bind(PluginAuthenticationServiceImpl).toSelf().inSingletonScope(); rebind(AuthenticationService).toService(PluginAuthenticationServiceImpl); diff --git a/packages/plugin-ext/src/main/browser/plugin-icon-service.ts b/packages/plugin-ext/src/main/browser/plugin-icon-service.ts new file mode 100644 index 0000000000000..b8a4b5092ae9c --- /dev/null +++ b/packages/plugin-ext/src/main/browser/plugin-icon-service.ts @@ -0,0 +1,97 @@ +// ***************************************************************************** +// Copyright (C) 2023 Ericsson and others. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0. +// +// This Source Code may also be made available under the following Secondary +// Licenses when the conditions for such availability set forth in the Eclipse +// Public License v. 2.0 are satisfied: GNU General Public License, version 2 +// with the GNU Classpath Exception which is available at +// https://www.gnu.org/software/classpath/license.html. +// +// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 +// ***************************************************************************** + +import { FrontendApplicationContribution } from '@theia/core/lib/browser'; +import { Disposable } from '@theia/core/lib/common/disposable'; +import { inject, injectable } from '@theia/core/shared/inversify'; +import { URI } from '@theia/core/shared/vscode-uri'; +import { IconRegistry, IconStyleSheetService } from '@theia/monaco/lib/browser/monaco-icon-registry-types'; +import * as path from 'path'; +import { IconContribution, DeployedPlugin } from '../../common/plugin-protocol'; + +@injectable() +export class PluginIconService implements Disposable, FrontendApplicationContribution { + + @inject(IconRegistry) + protected readonly iconRegistry: IconRegistry; + + @inject(IconStyleSheetService) + protected readonly iconStyleSheetService: IconStyleSheetService; + + styleSheet: string = ''; + + styleElement: HTMLStyleElement; + + // @inject(ContributionProvider) + // protected readonly iconContributions: ContributionProvider; + + async onStart(): Promise { + console.log('**** alvs, PluginIconService onStart'); + // NOTE: The registration of the following icons is performed by the icon registry by default + // this.iconRegistry.registerIcon('goto-previous-location', { id: 'arrow-up'}, 'Icon for goto previous editor location.'); + // this.iconRegistry.registerIcon('goto-next-location', { id: 'arrowDown'}, 'Icon for goto next editor location.'); + + } + + register(contribution: IconContribution, plugin: DeployedPlugin): Disposable { + const defaultIcon = contribution.defaults; + if (IconContribution.isIconDefinition(defaultIcon)) { + const location = defaultIcon.location; + const format = getFileExtension(location); + const fontId = getFontId(contribution.extensionId, location); + const definition = this.iconRegistry.registerIconFont(fontId, { src: [{ location: URI.file(location), format }] }); + this.iconRegistry.registerIcon(contribution.id, { + fontCharacter: defaultIcon.fontCharacter, + font: { + id: fontId, + definition + } + }, contribution.description); + } else { + this.iconRegistry.registerIcon(contribution.id, { id: defaultIcon.id}, contribution.description); + } + console.warn('**** alvs, iconContributionr registered: ', contribution.id); + this.updateStyle(); + return Disposable.NULL; + } + + updateStyle(): void { + if (!this.styleElement) { + const styleElement = document.createElement('style'); + styleElement.type = 'text/css'; + styleElement.media = 'screen'; + styleElement.id = 'contributedIconsStyles'; + document.head.appendChild(styleElement); + this.styleElement = styleElement; + } + + this.styleElement.innerText = this.iconStyleSheetService.getIconsStyleSheet().getCSS(); + // const toRemoveStyleElement = Disposable.create(() => styleElement.remove()); + } + + dispose(): void { + // Implement me + } +} + +function getFontId(extensionId: string, fontPath: string): string { + return path.join(extensionId, fontPath); +} + +function getFileExtension(filePath: string): string { + const index = filePath.lastIndexOf('.'); + return index === -1 ? '' : filePath.substring(index + 1); +} diff --git a/packages/plugin-ext/src/main/browser/webview/webview-frontend-security-warnings.ts b/packages/plugin-ext/src/main/browser/webview/webview-frontend-security-warnings.ts index 7435b78eedf0f..3fd3ac8cd911b 100644 --- a/packages/plugin-ext/src/main/browser/webview/webview-frontend-security-warnings.ts +++ b/packages/plugin-ext/src/main/browser/webview/webview-frontend-security-warnings.ts @@ -40,6 +40,7 @@ export class WebviewFrontendSecurityWarnings implements FrontendApplicationContr } protected async checkHostPattern(): Promise { + console.log('**** alvs, WebviewFrontendSecurityWarnings checkHostPattern'); if (FrontendApplicationConfigProvider.get()['warnOnPotentiallyInsecureHostPattern'] === false) { return; } From f265351dc69a63bb078fb852129fe166e669c7ee Mon Sep 17 00:00:00 2001 From: Vlad Arama Date: Wed, 23 Aug 2023 14:57:31 -0400 Subject: [PATCH 2/9] working icon contributions This commit supports the icon contributions point. It is working well, but there is some code simplification and cleanup still to do. Signed-off-by: Vlad Arama --- .../src/main/browser/plugin-icon-service.ts | 79 +++++++++++++++++-- 1 file changed, 71 insertions(+), 8 deletions(-) diff --git a/packages/plugin-ext/src/main/browser/plugin-icon-service.ts b/packages/plugin-ext/src/main/browser/plugin-icon-service.ts index b8a4b5092ae9c..934559a80fb40 100644 --- a/packages/plugin-ext/src/main/browser/plugin-icon-service.ts +++ b/packages/plugin-ext/src/main/browser/plugin-icon-service.ts @@ -14,13 +14,17 @@ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 // ***************************************************************************** -import { FrontendApplicationContribution } from '@theia/core/lib/browser'; +import { asCSSPropertyValue } from '@theia/monaco-editor-core/esm/vs/base/browser/dom'; +import { Endpoint, FrontendApplicationContribution } from '@theia/core/lib/browser'; import { Disposable } from '@theia/core/lib/common/disposable'; +import { getIconRegistry } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/iconRegistry'; import { inject, injectable } from '@theia/core/shared/inversify'; import { URI } from '@theia/core/shared/vscode-uri'; -import { IconRegistry, IconStyleSheetService } from '@theia/monaco/lib/browser/monaco-icon-registry-types'; +import { IconFontDefinition, IconContribution as Icon, IconRegistry, IconStyleSheetService } from '@theia/monaco/lib/browser/monaco-icon-registry-types'; import * as path from 'path'; import { IconContribution, DeployedPlugin } from '../../common/plugin-protocol'; +import { IThemeService } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/themeService'; +import { UnthemedProductIconTheme } from '@theia/monaco-editor-core/esm/vs/platform/theme/browser/iconsStyleSheet'; @injectable() export class PluginIconService implements Disposable, FrontendApplicationContribution { @@ -61,14 +65,14 @@ export class PluginIconService implements Disposable, FrontendApplicationContrib } }, contribution.description); } else { - this.iconRegistry.registerIcon(contribution.id, { id: defaultIcon.id}, contribution.description); + this.iconRegistry.registerIcon(contribution.id, { id: defaultIcon.id }, contribution.description); } console.warn('**** alvs, iconContributionr registered: ', contribution.id); - this.updateStyle(); + this.updateStyle(contribution); return Disposable.NULL; } - updateStyle(): void { + updateStyle(contribution: IconContribution): void { if (!this.styleElement) { const styleElement = document.createElement('style'); styleElement.type = 'text/css'; @@ -77,14 +81,73 @@ export class PluginIconService implements Disposable, FrontendApplicationContrib document.head.appendChild(styleElement); this.styleElement = styleElement; } - - this.styleElement.innerText = this.iconStyleSheetService.getIconsStyleSheet().getCSS(); - // const toRemoveStyleElement = Disposable.create(() => styleElement.remove()); + const css = this.getCSS(contribution); + if (css) { + this.styleElement.innerText = css; + } + // const toRemoveStyleElement = Disposable.create(() => this.styleElement.remove()); } dispose(): void { // Implement me } + + protected getCSS(iconContribution: IconContribution, themeService?: IThemeService): string | undefined { + const iconRegistry = getIconRegistry(); + const productIconTheme = themeService ? themeService.getProductIconTheme() : new UnthemedProductIconTheme(); + const usedFontIds: { [id: string]: IconFontDefinition } = {}; + const formatIconRule = (contribution: Icon): string | undefined => { + const definition = productIconTheme.getIcon(contribution); + if (!definition) { + return undefined; + } + const fontContribution = definition.font; + if (fontContribution) { + usedFontIds[fontContribution.id] = fontContribution.definition; + return `.codicon-${contribution.id}:before { content: '${definition.fontCharacter}'; font-family: ${asCSSPropertyValue(iconContribution.extensionId)}; }`; + } + // default font (codicon) + return `.codicon-${contribution.id}:before { content: '${definition.fontCharacter}'; }`; + }; + + const rules = []; + for (const contribution of iconRegistry.getIcons()) { + const rule = formatIconRule(contribution); + if (rule) { + rules.push(rule); + } + } + for (const id in usedFontIds) { + if (id) { + const definition = usedFontIds[id]; + const fontWeight = definition.weight ? `font-weight: ${definition.weight};` : ''; + const fontStyle = definition.style ? `font-style: ${definition.style};` : ''; + const src = definition.src.map(icon => + `${this.toPluginUrl(iconContribution.extensionId, getIconRelativePath(icon.location.path))} format('${icon.format}')`) + .join(', '); + rules.push(`@font-face { src: ${src}; font-family: ${asCSSPropertyValue(iconContribution.extensionId)};${fontWeight}${fontStyle} font-display: block; }`); + } + } + return rules.join('\n'); + } + + protected toPluginUrl(id: string, relativePath: string): string { + return `url('${new Endpoint({ + path: `hostedPlugin/${this.formatExtensionId(id)}/${encodeURIComponent(relativePath)}` + }).getRestUrl().toString()}')`; + } + + protected formatExtensionId(id: string): string { + return id.replace(/\W/g, '_'); + } +} + +function getIconRelativePath(iconPath: string): string { + const index = iconPath.indexOf('extension'); + if (index === -1) { + return ''; + } + return iconPath.substring(index + 'extension'.length + 1); } function getFontId(extensionId: string, fontPath: string): string { From 0f3897c9c9413ac77e442ba2da1f010365c44294 Mon Sep 17 00:00:00 2001 From: Vlad Arama Date: Fri, 15 Sep 2023 10:11:38 -0400 Subject: [PATCH 3/9] code improvement and cleanup This commit cleans up the remaining console.log statements and adds disposable methods to the `PluginIconService` class. Signed-off-by: Vlad Arama --- .../src/browser/icon-theme-contribution.ts | 2 -- .../tab-bar-toolbar-registry.ts | 1 - .../browser/plugin-contribution-handler.ts | 1 + .../src/main/browser/plugin-icon-service.ts | 25 ++++++------------- .../webview-frontend-security-warnings.ts | 1 - 5 files changed, 9 insertions(+), 21 deletions(-) diff --git a/packages/core/src/browser/icon-theme-contribution.ts b/packages/core/src/browser/icon-theme-contribution.ts index d5c628f1ff51b..3c1dda5465f30 100644 --- a/packages/core/src/browser/icon-theme-contribution.ts +++ b/packages/core/src/browser/icon-theme-contribution.ts @@ -36,8 +36,6 @@ export class IconThemeApplicationContribution implements FrontendApplicationCont protected readonly iconThemeContributions: ContributionProvider; async onStart(): Promise { - console.log('**** alvs, IconThemeApplicationContribution onStart'); - for (const contribution of this.iconThemeContributions.getContributions()) { await contribution.registerIconThemes(this.iconThemes); } diff --git a/packages/core/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.ts b/packages/core/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.ts index 78f94f7d939a5..92b3c5f219955 100644 --- a/packages/core/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.ts +++ b/packages/core/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.ts @@ -81,7 +81,6 @@ export class TabBarToolbarRegistry implements FrontendApplicationContribution { throw new Error(`A toolbar item is already registered with the '${id}' ID.`); } this.items.set(id, item); - console.warn('***** alvs: registering tab item: ', item.id); this.fireOnDidChange(); const toDispose = new DisposableCollection( Disposable.create(() => this.fireOnDidChange()), diff --git a/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts b/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts index 68e8bbdf4beeb..516fa8cbf4cd7 100644 --- a/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts +++ b/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts @@ -33,6 +33,7 @@ import { RegExpOptions, IconContribution } from '../../common'; +import { getPluginId } from '../../common/plugin-protocol'; import { DefaultUriLabelProviderContribution, LabelProviderContribution, diff --git a/packages/plugin-ext/src/main/browser/plugin-icon-service.ts b/packages/plugin-ext/src/main/browser/plugin-icon-service.ts index 934559a80fb40..7dc5a3d773fd1 100644 --- a/packages/plugin-ext/src/main/browser/plugin-icon-service.ts +++ b/packages/plugin-ext/src/main/browser/plugin-icon-service.ts @@ -15,8 +15,8 @@ // ***************************************************************************** import { asCSSPropertyValue } from '@theia/monaco-editor-core/esm/vs/base/browser/dom'; -import { Endpoint, FrontendApplicationContribution } from '@theia/core/lib/browser'; -import { Disposable } from '@theia/core/lib/common/disposable'; +import { Endpoint } from '@theia/core/lib/browser'; +import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable'; import { getIconRegistry } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/iconRegistry'; import { inject, injectable } from '@theia/core/shared/inversify'; import { URI } from '@theia/core/shared/vscode-uri'; @@ -27,7 +27,7 @@ import { IThemeService } from '@theia/monaco-editor-core/esm/vs/platform/theme/c import { UnthemedProductIconTheme } from '@theia/monaco-editor-core/esm/vs/platform/theme/browser/iconsStyleSheet'; @injectable() -export class PluginIconService implements Disposable, FrontendApplicationContribution { +export class PluginIconService implements Disposable { @inject(IconRegistry) protected readonly iconRegistry: IconRegistry; @@ -35,21 +35,12 @@ export class PluginIconService implements Disposable, FrontendApplicationContrib @inject(IconStyleSheetService) protected readonly iconStyleSheetService: IconStyleSheetService; + protected readonly toDispose = new DisposableCollection(); + styleSheet: string = ''; styleElement: HTMLStyleElement; - // @inject(ContributionProvider) - // protected readonly iconContributions: ContributionProvider; - - async onStart(): Promise { - console.log('**** alvs, PluginIconService onStart'); - // NOTE: The registration of the following icons is performed by the icon registry by default - // this.iconRegistry.registerIcon('goto-previous-location', { id: 'arrow-up'}, 'Icon for goto previous editor location.'); - // this.iconRegistry.registerIcon('goto-next-location', { id: 'arrowDown'}, 'Icon for goto next editor location.'); - - } - register(contribution: IconContribution, plugin: DeployedPlugin): Disposable { const defaultIcon = contribution.defaults; if (IconContribution.isIconDefinition(defaultIcon)) { @@ -67,7 +58,6 @@ export class PluginIconService implements Disposable, FrontendApplicationContrib } else { this.iconRegistry.registerIcon(contribution.id, { id: defaultIcon.id }, contribution.description); } - console.warn('**** alvs, iconContributionr registered: ', contribution.id); this.updateStyle(contribution); return Disposable.NULL; } @@ -85,11 +75,12 @@ export class PluginIconService implements Disposable, FrontendApplicationContrib if (css) { this.styleElement.innerText = css; } - // const toRemoveStyleElement = Disposable.create(() => this.styleElement.remove()); + const toRemoveStyleElement = Disposable.create(() => this.styleElement.remove()); + this.toDispose.push(toRemoveStyleElement); } dispose(): void { - // Implement me + this.toDispose.dispose(); } protected getCSS(iconContribution: IconContribution, themeService?: IThemeService): string | undefined { diff --git a/packages/plugin-ext/src/main/browser/webview/webview-frontend-security-warnings.ts b/packages/plugin-ext/src/main/browser/webview/webview-frontend-security-warnings.ts index 3fd3ac8cd911b..7435b78eedf0f 100644 --- a/packages/plugin-ext/src/main/browser/webview/webview-frontend-security-warnings.ts +++ b/packages/plugin-ext/src/main/browser/webview/webview-frontend-security-warnings.ts @@ -40,7 +40,6 @@ export class WebviewFrontendSecurityWarnings implements FrontendApplicationContr } protected async checkHostPattern(): Promise { - console.log('**** alvs, WebviewFrontendSecurityWarnings checkHostPattern'); if (FrontendApplicationConfigProvider.get()['warnOnPotentiallyInsecureHostPattern'] === false) { return; } From 9c662cdce6e3fe4ad9c7c5c267e5d98838c839c7 Mon Sep 17 00:00:00 2001 From: Vlad Arama Date: Fri, 15 Sep 2023 11:30:18 -0400 Subject: [PATCH 4/9] simplify `PluginIconService` This commit simplifies the `PluginIconService` class by adding helper methods and decomposing the large code into smaller manageable functions. Signed-off-by: Vlad Arama --- .../src/main/browser/plugin-icon-service.ts | 59 +++++++++++-------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/packages/plugin-ext/src/main/browser/plugin-icon-service.ts b/packages/plugin-ext/src/main/browser/plugin-icon-service.ts index 7dc5a3d773fd1..5b7e7c7f7a9b0 100644 --- a/packages/plugin-ext/src/main/browser/plugin-icon-service.ts +++ b/packages/plugin-ext/src/main/browser/plugin-icon-service.ts @@ -22,7 +22,7 @@ import { inject, injectable } from '@theia/core/shared/inversify'; import { URI } from '@theia/core/shared/vscode-uri'; import { IconFontDefinition, IconContribution as Icon, IconRegistry, IconStyleSheetService } from '@theia/monaco/lib/browser/monaco-icon-registry-types'; import * as path from 'path'; -import { IconContribution, DeployedPlugin } from '../../common/plugin-protocol'; +import { IconContribution, DeployedPlugin, IconDefinition } from '../../common/plugin-protocol'; import { IThemeService } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/themeService'; import { UnthemedProductIconTheme } from '@theia/monaco-editor-core/esm/vs/platform/theme/browser/iconsStyleSheet'; @@ -38,39 +38,21 @@ export class PluginIconService implements Disposable { protected readonly toDispose = new DisposableCollection(); styleSheet: string = ''; - styleElement: HTMLStyleElement; register(contribution: IconContribution, plugin: DeployedPlugin): Disposable { const defaultIcon = contribution.defaults; if (IconContribution.isIconDefinition(defaultIcon)) { - const location = defaultIcon.location; - const format = getFileExtension(location); - const fontId = getFontId(contribution.extensionId, location); - const definition = this.iconRegistry.registerIconFont(fontId, { src: [{ location: URI.file(location), format }] }); - this.iconRegistry.registerIcon(contribution.id, { - fontCharacter: defaultIcon.fontCharacter, - font: { - id: fontId, - definition - } - }, contribution.description); + this.registerFontIcon(contribution, defaultIcon); } else { - this.iconRegistry.registerIcon(contribution.id, { id: defaultIcon.id }, contribution.description); + this.registerRegularIcon(contribution, defaultIcon.id); } this.updateStyle(contribution); return Disposable.NULL; } updateStyle(contribution: IconContribution): void { - if (!this.styleElement) { - const styleElement = document.createElement('style'); - styleElement.type = 'text/css'; - styleElement.media = 'screen'; - styleElement.id = 'contributedIconsStyles'; - document.head.appendChild(styleElement); - this.styleElement = styleElement; - } + this.updateStyleElement(); const css = this.getCSS(contribution); if (css) { this.styleElement.innerText = css; @@ -83,6 +65,34 @@ export class PluginIconService implements Disposable { this.toDispose.dispose(); } + protected registerFontIcon(contribution: IconContribution, defaultIcon: IconDefinition): void { + const location = defaultIcon.location; + const format = getFileExtension(location); + const fontId = getFontId(contribution.extensionId, location); + const definition = this.iconRegistry.registerIconFont(fontId, { src: [{ location: URI.file(location), format }] }); + this.iconRegistry.registerIcon(contribution.id, { + fontCharacter: defaultIcon.fontCharacter, + font: { + id: fontId, + definition + } + }, contribution.description); + } + + protected registerRegularIcon(contribution: IconContribution, defaultIconId: string): void { + this.iconRegistry.registerIcon(contribution.id, { id: defaultIconId }, contribution.description); + } + + protected updateStyleElement(): void { + if (!this.styleElement) { + const styleElement = document.createElement('style'); + styleElement.type = 'text/css'; + styleElement.media = 'screen'; + styleElement.id = 'contributedIconsStyles'; + document.head.appendChild(styleElement); + this.styleElement = styleElement; + } + } protected getCSS(iconContribution: IconContribution, themeService?: IThemeService): string | undefined { const iconRegistry = getIconRegistry(); const productIconTheme = themeService ? themeService.getProductIconTheme() : new UnthemedProductIconTheme(); @@ -135,10 +145,7 @@ export class PluginIconService implements Disposable { function getIconRelativePath(iconPath: string): string { const index = iconPath.indexOf('extension'); - if (index === -1) { - return ''; - } - return iconPath.substring(index + 'extension'.length + 1); + return index === -1 ? '' : iconPath.substring(index + 'extension'.length + 1); } function getFontId(extensionId: string, fontPath: string): string { From b7609f8cda2e0a3de2c96c90205a4acf87ab3800 Mon Sep 17 00:00:00 2001 From: Vlad Arama Date: Fri, 15 Sep 2023 15:24:37 -0400 Subject: [PATCH 5/9] fix linting This commit fixes a few linting errors related to file-headers. Signed-off-by: Vlad Arama --- packages/monaco/src/browser/monaco-icon-registry-types.ts | 4 ++-- packages/monaco/src/browser/monaco-icon-registry.ts | 3 +-- packages/monaco/src/browser/monaco-icon-style-sheet.ts | 3 +-- packages/plugin-ext/src/main/browser/plugin-icon-service.ts | 2 +- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/monaco/src/browser/monaco-icon-registry-types.ts b/packages/monaco/src/browser/monaco-icon-registry-types.ts index 22ef36c55213b..b9ff5cbbdaf51 100644 --- a/packages/monaco/src/browser/monaco-icon-registry-types.ts +++ b/packages/monaco/src/browser/monaco-icon-registry-types.ts @@ -1,4 +1,3 @@ - // ***************************************************************************** // Copyright (C) 2023 Ericsson and others. // @@ -12,8 +11,9 @@ // with the GNU Classpath Exception which is available at // https://www.gnu.org/software/classpath/license.html. // -// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 +// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 // ***************************************************************************** + import { Event } from '@theia/core'; import { IJSONSchema } from '@theia/core/lib/common/json-schema'; import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/themeService'; diff --git a/packages/monaco/src/browser/monaco-icon-registry.ts b/packages/monaco/src/browser/monaco-icon-registry.ts index ba91f620cd647..f8e02cf87f8d7 100644 --- a/packages/monaco/src/browser/monaco-icon-registry.ts +++ b/packages/monaco/src/browser/monaco-icon-registry.ts @@ -1,4 +1,3 @@ - // ***************************************************************************** // Copyright (C) 2023 Ericsson and others. // @@ -12,7 +11,7 @@ // with the GNU Classpath Exception which is available at // https://www.gnu.org/software/classpath/license.html. // -// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 +// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 // ***************************************************************************** import { injectable } from '@theia/core/shared/inversify'; diff --git a/packages/monaco/src/browser/monaco-icon-style-sheet.ts b/packages/monaco/src/browser/monaco-icon-style-sheet.ts index 6d3678a02a422..698ce22b96165 100644 --- a/packages/monaco/src/browser/monaco-icon-style-sheet.ts +++ b/packages/monaco/src/browser/monaco-icon-style-sheet.ts @@ -1,4 +1,3 @@ - // ***************************************************************************** // Copyright (C) 2023 Ericsson and others. // @@ -12,7 +11,7 @@ // with the GNU Classpath Exception which is available at // https://www.gnu.org/software/classpath/license.html. // -// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 +// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 // ***************************************************************************** import { injectable } from '@theia/core/shared/inversify'; diff --git a/packages/plugin-ext/src/main/browser/plugin-icon-service.ts b/packages/plugin-ext/src/main/browser/plugin-icon-service.ts index 5b7e7c7f7a9b0..093b11959dbdb 100644 --- a/packages/plugin-ext/src/main/browser/plugin-icon-service.ts +++ b/packages/plugin-ext/src/main/browser/plugin-icon-service.ts @@ -11,7 +11,7 @@ // with the GNU Classpath Exception which is available at // https://www.gnu.org/software/classpath/license.html. // -// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 +// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 // ***************************************************************************** import { asCSSPropertyValue } from '@theia/monaco-editor-core/esm/vs/base/browser/dom'; From 7943b97b46c162be70d4cce7108d510317124ae8 Mon Sep 17 00:00:00 2001 From: Vlad Arama Date: Tue, 24 Oct 2023 11:13:47 -0400 Subject: [PATCH 6/9] address feedback --- .../src/browser/monaco-frontend-module.ts | 11 +--- .../src/browser/monaco-icon-registry-types.ts | 52 +++-------------- .../src/browser/monaco-icon-registry.ts | 58 ------------------- .../src/browser/monaco-icon-style-sheet.ts | 27 --------- .../browser/plugin-contribution-handler.ts | 12 +--- .../src/main/browser/plugin-icon-service.ts | 5 +- 6 files changed, 14 insertions(+), 151 deletions(-) delete mode 100644 packages/monaco/src/browser/monaco-icon-registry.ts delete mode 100644 packages/monaco/src/browser/monaco-icon-style-sheet.ts diff --git a/packages/monaco/src/browser/monaco-frontend-module.ts b/packages/monaco/src/browser/monaco-frontend-module.ts index cae06f3a1f2ba..7baf7b42e151c 100644 --- a/packages/monaco/src/browser/monaco-frontend-module.ts +++ b/packages/monaco/src/browser/monaco-frontend-module.ts @@ -68,9 +68,8 @@ import { MimeService } from '@theia/core/lib/browser/mime-service'; import { MonacoEditorServices } from './monaco-editor'; import { MonacoColorRegistry } from './monaco-color-registry'; import { ColorRegistry } from '@theia/core/lib/browser/color-registry'; -import { IconRegistry, IconStyleSheetService } from './monaco-icon-registry-types'; -import { MonacoIconRegistry } from './monaco-icon-registry'; -import { MonacoIconStyleSheetService } from './monaco-icon-style-sheet'; +import { IconRegistry } from './monaco-icon-registry-types'; +import { getIconRegistry } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/iconRegistry'; import { MonacoThemingService } from './monaco-theming-service'; import { bindContributionProvider } from '@theia/core'; import { WorkspaceSymbolCommand } from './workspace-symbol-command'; @@ -191,11 +190,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { bind(ThemeServiceWithDB).toSelf().inSingletonScope(); rebind(ThemeService).toService(ThemeServiceWithDB); - bind(MonacoIconRegistry).toSelf().inSingletonScope(); - bind(IconRegistry).toService(MonacoIconRegistry); - - bind(MonacoIconStyleSheetService).toSelf().inSingletonScope(); - bind(IconStyleSheetService).toService(MonacoIconStyleSheetService); + bind(IconRegistry).toDynamicValue(() => getIconRegistry()).inSingletonScope(); }); export const MonacoConfigurationService = Symbol('MonacoConfigurationService'); diff --git a/packages/monaco/src/browser/monaco-icon-registry-types.ts b/packages/monaco/src/browser/monaco-icon-registry-types.ts index b9ff5cbbdaf51..7b71d1f38a893 100644 --- a/packages/monaco/src/browser/monaco-icon-registry-types.ts +++ b/packages/monaco/src/browser/monaco-icon-registry-types.ts @@ -13,23 +13,18 @@ // // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 // ***************************************************************************** +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// code copied and modified from https://github.com/Microsoft/vscode/blob/main/src/vs/platform/theme/common/iconRegistry.ts import { Event } from '@theia/core'; -import { IJSONSchema } from '@theia/core/lib/common/json-schema'; import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/themeService'; import { URI } from '@theia/core/shared/vscode-uri'; // ------ API types -export type IconIdentifier = string; - -// icon registry -export const Extensions = { - IconContribution: 'base.contributions.icons' -}; - -export type IconDefaults = ThemeIcon | IconDefinition; - export interface IconDefinition { font?: IconFontContribution; // undefined for the default font (codicon) fontCharacter: string; @@ -39,7 +34,7 @@ export interface IconContribution { readonly id: string; description: string | undefined; deprecationMessage?: string; - readonly defaults: IconDefaults; + readonly defaults: ThemeIcon | IconDefinition; } export interface IconFontContribution { @@ -69,32 +64,12 @@ export interface IconRegistry { * @param defaults The default values * @param description The description */ - registerIcon(id: IconIdentifier, defaults: IconDefaults, description?: string): ThemeIcon; + registerIcon(id: string, defaults: ThemeIcon | IconDefinition, description?: string): ThemeIcon; /** * Deregister a icon from the registry. */ - deregisterIcon(id: IconIdentifier): void; - - /** - * Get all icon contributions - */ - getIcons(): IconContribution[]; - - /** - * Get the icon for the given id - */ - getIcon(id: IconIdentifier): IconContribution | undefined; - - /** - * JSON schema for an object to assign icon values to one of the icon contributions. - */ - getIconSchema(): IJSONSchema; - - /** - * JSON schema to for a reference to a icon contribution. - */ - getIconReferenceSchema(): IJSONSchema; + deregisterIcon(id: string): void; /** * Register a icon font to the registry. @@ -114,14 +89,3 @@ export interface IconRegistry { getIconFont(id: string): IconFontDefinition | undefined; } -export const IconsStyleSheet = Symbol('IconsStyleSheet'); -export interface IconsStyleSheet { - getCSS(): string; - readonly onDidChange: Event; -} - -export const IconStyleSheetService = Symbol('IconStyleSheetService'); -export interface IconStyleSheetService { - getIconsStyleSheet(): IconsStyleSheet; -} - diff --git a/packages/monaco/src/browser/monaco-icon-registry.ts b/packages/monaco/src/browser/monaco-icon-registry.ts deleted file mode 100644 index f8e02cf87f8d7..0000000000000 --- a/packages/monaco/src/browser/monaco-icon-registry.ts +++ /dev/null @@ -1,58 +0,0 @@ -// ***************************************************************************** -// Copyright (C) 2023 Ericsson and others. -// -// This program and the accompanying materials are made available under the -// terms of the Eclipse Public License v. 2.0 which is available at -// http://www.eclipse.org/legal/epl-2.0. -// -// This Source Code may also be made available under the following Secondary -// Licenses when the conditions for such availability set forth in the Eclipse -// Public License v. 2.0 are satisfied: GNU General Public License, version 2 -// with the GNU Classpath Exception which is available at -// https://www.gnu.org/software/classpath/license.html. -// -// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 -// ***************************************************************************** - -import { injectable } from '@theia/core/shared/inversify'; -import * as monaco from '@theia/monaco-editor-core/esm/vs/platform/theme/common/iconRegistry'; -import { IconContribution, IconDefaults, IconFontDefinition, IconRegistry } from './monaco-icon-registry-types'; -import { Event } from '@theia/core'; -import { IJSONSchema } from '@theia/core/lib/common/json-schema'; -import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/themeService'; - -@injectable() -export class MonacoIconRegistry implements IconRegistry { - protected readonly iconRegistry = monaco.getIconRegistry(); - - onDidChange: Event = this.iconRegistry.onDidChange; - - registerIcon(id: string, defaults: IconDefaults, description?: string | undefined): ThemeIcon { - return this.iconRegistry.registerIcon(id, defaults, description); - } - deregisterIcon(id: string): void { - return this.iconRegistry.deregisterIcon(id); - } - getIcons(): IconContribution[] { - return this.iconRegistry.getIcons(); - } - getIcon(id: string): IconContribution | undefined { - return this.iconRegistry.getIcon(id); - } - getIconSchema(): IJSONSchema { - return this.iconRegistry.getIconSchema(); - } - getIconReferenceSchema(): IJSONSchema { - return this.iconRegistry.getIconReferenceSchema(); - } - registerIconFont(id: string, definition: IconFontDefinition): IconFontDefinition { - return this.iconRegistry.registerIconFont(id, definition); - } - deregisterIconFont(id: string): void { - return this.iconRegistry.deregisterIconFont(id); - } - getIconFont(id: string): IconFontDefinition | undefined { - return this.iconRegistry.getIconFont(id); - } - -} diff --git a/packages/monaco/src/browser/monaco-icon-style-sheet.ts b/packages/monaco/src/browser/monaco-icon-style-sheet.ts deleted file mode 100644 index 698ce22b96165..0000000000000 --- a/packages/monaco/src/browser/monaco-icon-style-sheet.ts +++ /dev/null @@ -1,27 +0,0 @@ -// ***************************************************************************** -// Copyright (C) 2023 Ericsson and others. -// -// This program and the accompanying materials are made available under the -// terms of the Eclipse Public License v. 2.0 which is available at -// http://www.eclipse.org/legal/epl-2.0. -// -// This Source Code may also be made available under the following Secondary -// Licenses when the conditions for such availability set forth in the Eclipse -// Public License v. 2.0 are satisfied: GNU General Public License, version 2 -// with the GNU Classpath Exception which is available at -// https://www.gnu.org/software/classpath/license.html. -// -// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 -// ***************************************************************************** - -import { injectable } from '@theia/core/shared/inversify'; -import { getIconsStyleSheet } from '@theia/monaco-editor-core/esm/vs/platform/theme/browser/iconsStyleSheet'; -import { IconsStyleSheet } from './monaco-icon-registry-types'; - -@injectable() -export class MonacoIconStyleSheetService { - protected getIconsStyleSheet(): IconsStyleSheet { - return getIconsStyleSheet(undefined); - } - -} diff --git a/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts b/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts index 516fa8cbf4cd7..07aa6d28e0eb6 100644 --- a/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts +++ b/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts @@ -22,16 +22,8 @@ import { MenusContributionPointHandler } from './menus/menus-contribution-handle import { PluginViewRegistry } from './view/plugin-view-registry'; import { PluginCustomEditorRegistry } from './custom-editors/plugin-custom-editor-registry'; import { - PluginContribution, - IndentationRules, - FoldingRules, - ScopeMap, - DeployedPlugin, - GrammarsContribution, - EnterAction, - OnEnterRule, - RegExpOptions, - IconContribution + PluginContribution, IndentationRules, FoldingRules, ScopeMap, DeployedPlugin, + GrammarsContribution, EnterAction, OnEnterRule, RegExpOptions, IconContribution } from '../../common'; import { getPluginId } from '../../common/plugin-protocol'; import { diff --git a/packages/plugin-ext/src/main/browser/plugin-icon-service.ts b/packages/plugin-ext/src/main/browser/plugin-icon-service.ts index 093b11959dbdb..6451f6c94a562 100644 --- a/packages/plugin-ext/src/main/browser/plugin-icon-service.ts +++ b/packages/plugin-ext/src/main/browser/plugin-icon-service.ts @@ -20,7 +20,7 @@ import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposa import { getIconRegistry } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/iconRegistry'; import { inject, injectable } from '@theia/core/shared/inversify'; import { URI } from '@theia/core/shared/vscode-uri'; -import { IconFontDefinition, IconContribution as Icon, IconRegistry, IconStyleSheetService } from '@theia/monaco/lib/browser/monaco-icon-registry-types'; +import { IconFontDefinition, IconContribution as Icon, IconRegistry } from '@theia/monaco/lib/browser/monaco-icon-registry-types'; import * as path from 'path'; import { IconContribution, DeployedPlugin, IconDefinition } from '../../common/plugin-protocol'; import { IThemeService } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/themeService'; @@ -32,9 +32,6 @@ export class PluginIconService implements Disposable { @inject(IconRegistry) protected readonly iconRegistry: IconRegistry; - @inject(IconStyleSheetService) - protected readonly iconStyleSheetService: IconStyleSheetService; - protected readonly toDispose = new DisposableCollection(); styleSheet: string = ''; From 2735e90dc0e9e5426d30df911c5fd02b5654f4e4 Mon Sep 17 00:00:00 2001 From: Vlad Arama Date: Wed, 25 Oct 2023 08:06:13 -0400 Subject: [PATCH 7/9] address core vs monaco layering --- .../browser/frontend-application-module.ts | 2 + .../src/browser/icon-registry.ts} | 57 ++++++--------- .../src/browser/monaco-frontend-module.ts | 7 +- .../src/browser/monaco-icon-registry.ts | 70 +++++++++++++++++++ .../src/main/browser/plugin-icon-service.ts | 7 +- 5 files changed, 101 insertions(+), 42 deletions(-) rename packages/{monaco/src/browser/monaco-icon-registry-types.ts => core/src/browser/icon-registry.ts} (60%) create mode 100644 packages/monaco/src/browser/monaco-icon-registry.ts diff --git a/packages/core/src/browser/frontend-application-module.ts b/packages/core/src/browser/frontend-application-module.ts index 871f03815d654..c8a1232b0787b 100644 --- a/packages/core/src/browser/frontend-application-module.ts +++ b/packages/core/src/browser/frontend-application-module.ts @@ -137,6 +137,7 @@ import { StylingParticipant, StylingService } from './styling-service'; import { bindCommonStylingParticipants } from './common-styling-participants'; import { HoverService } from './hover-service'; import { AdditionalViewsMenuWidget, AdditionalViewsMenuWidgetFactory } from './shell/additional-views-menu-widget'; +import { IconRegistry } from './icon-registry'; export { bindResourceProvider, bindMessageService, bindPreferenceService }; @@ -151,6 +152,7 @@ export const frontendApplicationModule = new ContainerModule((bind, _unbind, _is bind(FrontendApplicationContribution).toService(IconThemeApplicationContribution); bind(ColorRegistry).toSelf().inSingletonScope(); + bind(IconRegistry).toSelf().inSingletonScope(); bindContributionProvider(bind, ColorContribution); bind(ColorApplicationContribution).toSelf().inSingletonScope(); bind(FrontendApplicationContribution).toService(ColorApplicationContribution); diff --git a/packages/monaco/src/browser/monaco-icon-registry-types.ts b/packages/core/src/browser/icon-registry.ts similarity index 60% rename from packages/monaco/src/browser/monaco-icon-registry-types.ts rename to packages/core/src/browser/icon-registry.ts index 7b71d1f38a893..167865ff65cad 100644 --- a/packages/monaco/src/browser/monaco-icon-registry-types.ts +++ b/packages/core/src/browser/icon-registry.ts @@ -19,14 +19,12 @@ *--------------------------------------------------------------------------------------------*/ // code copied and modified from https://github.com/Microsoft/vscode/blob/main/src/vs/platform/theme/common/iconRegistry.ts -import { Event } from '@theia/core'; -import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/themeService'; -import { URI } from '@theia/core/shared/vscode-uri'; - -// ------ API types +import { injectable } from 'inversify'; +import { Emitter } from '../common/event'; +import { URI } from 'vscode-uri'; export interface IconDefinition { - font?: IconFontContribution; // undefined for the default font (codicon) + font?: IconFontContribution; fontCharacter: string; } @@ -53,39 +51,26 @@ export interface IconFontSource { readonly format: string; } -export const IconRegistry = Symbol('IconRegistry'); -export interface IconRegistry { - - readonly onDidChange: Event; - - /** - * Register a icon to the registry. - * @param id The icon id - * @param defaults The default values - * @param description The description - */ - registerIcon(id: string, defaults: ThemeIcon | IconDefinition, description?: string): ThemeIcon; +export interface ThemeIcon { + readonly id: string; + readonly color?: ThemeColor; +} - /** - * Deregister a icon from the registry. - */ - deregisterIcon(id: string): void; +export interface ThemeColor { + id: string; +} - /** - * Register a icon font to the registry. - * @param id The icon font id - * @param definition The icon font definition - */ - registerIconFont(id: string, definition: IconFontDefinition): IconFontDefinition; +@injectable() +export abstract class IconRegistry { + protected readonly onDidChangeEmitter = new Emitter(); + readonly onDidChange = this.onDidChangeEmitter.event; - /** - * Deregister an icon font to the registry. - */ - deregisterIconFont(id: string): void; + protected fireDidChange(): void { + this.onDidChangeEmitter.fire(undefined); + } - /** - * Get the icon font for the given id - */ - getIconFont(id: string): IconFontDefinition | undefined; + abstract registerIcon(id: string, defaults: ThemeIcon | IconDefinition, description?: string): ThemeIcon; + abstract deregisterIcon(id: string): void; + abstract getIconFont(id: string): IconFontDefinition | undefined; } diff --git a/packages/monaco/src/browser/monaco-frontend-module.ts b/packages/monaco/src/browser/monaco-frontend-module.ts index 7baf7b42e151c..431fe8aef778a 100644 --- a/packages/monaco/src/browser/monaco-frontend-module.ts +++ b/packages/monaco/src/browser/monaco-frontend-module.ts @@ -68,8 +68,8 @@ import { MimeService } from '@theia/core/lib/browser/mime-service'; import { MonacoEditorServices } from './monaco-editor'; import { MonacoColorRegistry } from './monaco-color-registry'; import { ColorRegistry } from '@theia/core/lib/browser/color-registry'; -import { IconRegistry } from './monaco-icon-registry-types'; -import { getIconRegistry } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/iconRegistry'; +import { IconRegistry } from '@theia/core/lib/browser/icon-registry'; +import { MonacoIconRegistry } from './monaco-icon-registry'; import { MonacoThemingService } from './monaco-theming-service'; import { bindContributionProvider } from '@theia/core'; import { WorkspaceSymbolCommand } from './workspace-symbol-command'; @@ -190,7 +190,8 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { bind(ThemeServiceWithDB).toSelf().inSingletonScope(); rebind(ThemeService).toService(ThemeServiceWithDB); - bind(IconRegistry).toDynamicValue(() => getIconRegistry()).inSingletonScope(); + bind(MonacoIconRegistry).toSelf().inSingletonScope(); + rebind(IconRegistry).toService(MonacoIconRegistry); }); export const MonacoConfigurationService = Symbol('MonacoConfigurationService'); diff --git a/packages/monaco/src/browser/monaco-icon-registry.ts b/packages/monaco/src/browser/monaco-icon-registry.ts new file mode 100644 index 0000000000000..c387857ae833b --- /dev/null +++ b/packages/monaco/src/browser/monaco-icon-registry.ts @@ -0,0 +1,70 @@ +// ***************************************************************************** +// Copyright (C) 2023 Ericsson and others. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0. +// +// This Source Code may also be made available under the following Secondary +// Licenses when the conditions for such availability set forth in the Eclipse +// Public License v. 2.0 are satisfied: GNU General Public License, version 2 +// with the GNU Classpath Exception which is available at +// https://www.gnu.org/software/classpath/license.html. +// +// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 +// ***************************************************************************** + +import { Event } from '@theia/core'; +import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/themeService'; +import { IconRegistry } from '@theia/core/lib/browser/icon-registry'; +import { IconDefinition, IconFontDefinition, getIconRegistry } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/iconRegistry'; + +export class MonacoIconRegistry extends IconRegistry { + + override readonly onDidChange: Event; + protected readonly monacoIconService = getIconRegistry(); + + /** + * Register a icon to the registry. + * @param id The icon id + * @param defaults The default values + * @param description The description + */ + registerIcon(id: string, defaults: ThemeIcon | IconDefinition, description?: string): ThemeIcon { + return this.monacoIconService.registerIcon(id, defaults, description); + } + + /** + * Deregister a icon from the registry. + * @param id The icon id + */ + deregisterIcon(id: string): void { + return this.monacoIconService.deregisterIcon(id); + } + + /** + * Register a icon font to the registry. + * @param id The icon font id + * @param definition The icon font definition + */ + registerIconFont(id: string, definition: IconFontDefinition): IconFontDefinition { + return this.monacoIconService.registerIconFont(id, definition); + } + + /** + * Deregister an icon font from the registry. + * @param id The icon font id + */ + deregisterIconFont(id: string): void { + return this.monacoIconService.deregisterIconFont(id); + } + + /** + * Get the icon font for the given id + * @param id The icon font id + */ + getIconFont(id: string): IconFontDefinition | undefined { + return this.monacoIconService.getIconFont(id); + } +} + diff --git a/packages/plugin-ext/src/main/browser/plugin-icon-service.ts b/packages/plugin-ext/src/main/browser/plugin-icon-service.ts index 6451f6c94a562..caef198ea31c0 100644 --- a/packages/plugin-ext/src/main/browser/plugin-icon-service.ts +++ b/packages/plugin-ext/src/main/browser/plugin-icon-service.ts @@ -20,7 +20,8 @@ import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposa import { getIconRegistry } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/iconRegistry'; import { inject, injectable } from '@theia/core/shared/inversify'; import { URI } from '@theia/core/shared/vscode-uri'; -import { IconFontDefinition, IconContribution as Icon, IconRegistry } from '@theia/monaco/lib/browser/monaco-icon-registry-types'; +import { IconFontDefinition, IconContribution as Icon } from '@theia/core/lib/browser/icon-registry'; +import { MonacoIconRegistry } from '@theia/monaco/lib/browser/monaco-icon-registry'; import * as path from 'path'; import { IconContribution, DeployedPlugin, IconDefinition } from '../../common/plugin-protocol'; import { IThemeService } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/themeService'; @@ -29,8 +30,8 @@ import { UnthemedProductIconTheme } from '@theia/monaco-editor-core/esm/vs/platf @injectable() export class PluginIconService implements Disposable { - @inject(IconRegistry) - protected readonly iconRegistry: IconRegistry; + @inject(MonacoIconRegistry) + protected readonly iconRegistry: MonacoIconRegistry; protected readonly toDispose = new DisposableCollection(); From ba547e1943abec8472395c71dc4323e02530c9ed Mon Sep 17 00:00:00 2001 From: Vlad Arama Date: Wed, 25 Oct 2023 09:18:22 -0400 Subject: [PATCH 8/9] simplify icon-registry --- .../browser/frontend-application-module.ts | 2 - packages/core/src/browser/icon-registry.ts | 46 ++++++++++++++----- .../src/browser/monaco-frontend-module.ts | 4 +- .../src/browser/monaco-icon-registry.ts | 29 ++---------- 4 files changed, 40 insertions(+), 41 deletions(-) diff --git a/packages/core/src/browser/frontend-application-module.ts b/packages/core/src/browser/frontend-application-module.ts index 58f47d2f8ba08..9b2531485382a 100644 --- a/packages/core/src/browser/frontend-application-module.ts +++ b/packages/core/src/browser/frontend-application-module.ts @@ -138,7 +138,6 @@ import { StylingParticipant, StylingService } from './styling-service'; import { bindCommonStylingParticipants } from './common-styling-participants'; import { HoverService } from './hover-service'; import { AdditionalViewsMenuWidget, AdditionalViewsMenuWidgetFactory } from './shell/additional-views-menu-widget'; -import { IconRegistry } from './icon-registry'; export { bindResourceProvider, bindMessageService, bindPreferenceService }; @@ -153,7 +152,6 @@ export const frontendApplicationModule = new ContainerModule((bind, _unbind, _is bind(FrontendApplicationContribution).toService(IconThemeApplicationContribution); bind(ColorRegistry).toSelf().inSingletonScope(); - bind(IconRegistry).toSelf().inSingletonScope(); bindContributionProvider(bind, ColorContribution); bind(ColorApplicationContribution).toSelf().inSingletonScope(); bind(FrontendApplicationContribution).toService(ColorApplicationContribution); diff --git a/packages/core/src/browser/icon-registry.ts b/packages/core/src/browser/icon-registry.ts index 167865ff65cad..e52462bc0b284 100644 --- a/packages/core/src/browser/icon-registry.ts +++ b/packages/core/src/browser/icon-registry.ts @@ -19,8 +19,7 @@ *--------------------------------------------------------------------------------------------*/ // code copied and modified from https://github.com/Microsoft/vscode/blob/main/src/vs/platform/theme/common/iconRegistry.ts -import { injectable } from 'inversify'; -import { Emitter } from '../common/event'; +import { Event } from '../common/event'; import { URI } from 'vscode-uri'; export interface IconDefinition { @@ -60,17 +59,40 @@ export interface ThemeColor { id: string; } -@injectable() -export abstract class IconRegistry { - protected readonly onDidChangeEmitter = new Emitter(); - readonly onDidChange = this.onDidChangeEmitter.event; +export const IconRegistry = Symbol('IconRegistry'); +export interface IconRegistry { + readonly onDidChange: Event; + /** + * Register a icon to the registry. + * @param id The icon id + * @param defaults The default values + * @param description The description + */ + registerIcon(id: string, defaults: ThemeIcon | IconDefinition, description?: string): ThemeIcon; - protected fireDidChange(): void { - this.onDidChangeEmitter.fire(undefined); - } + /** + * Deregister a icon from the registry. + * @param id The icon id + */ + deregisterIcon(id: string): void; - abstract registerIcon(id: string, defaults: ThemeIcon | IconDefinition, description?: string): ThemeIcon; - abstract deregisterIcon(id: string): void; - abstract getIconFont(id: string): IconFontDefinition | undefined; + /** + * Register a icon font to the registry. + * @param id The icon font id + * @param definition The icon font definition + */ + registerIconFont(id: string, definition: IconFontDefinition): IconFontDefinition; + + /** + * Deregister an icon font from the registry. + * @param id The icon font id + */ + deregisterIconFont(id: string): void; + + /** + * Get the icon font for the given id + * @param id The icon font id + */ + getIconFont(id: string): IconFontDefinition | undefined; } diff --git a/packages/monaco/src/browser/monaco-frontend-module.ts b/packages/monaco/src/browser/monaco-frontend-module.ts index 181c90c68834c..87320ec47284a 100644 --- a/packages/monaco/src/browser/monaco-frontend-module.ts +++ b/packages/monaco/src/browser/monaco-frontend-module.ts @@ -66,8 +66,8 @@ import { MimeService } from '@theia/core/lib/browser/mime-service'; import { MonacoEditorServices } from './monaco-editor'; import { MonacoColorRegistry } from './monaco-color-registry'; import { ColorRegistry } from '@theia/core/lib/browser/color-registry'; -import { IconRegistry } from '@theia/core/lib/browser/icon-registry'; import { MonacoIconRegistry } from './monaco-icon-registry'; +import { IconRegistry } from '@theia/core/lib/browser/icon-registry'; import { MonacoThemingService } from './monaco-theming-service'; import { bindContributionProvider } from '@theia/core'; import { WorkspaceSymbolCommand } from './workspace-symbol-command'; @@ -188,7 +188,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { rebind(ThemeService).toService(ThemeServiceWithDB); bind(MonacoIconRegistry).toSelf().inSingletonScope(); - rebind(IconRegistry).toService(MonacoIconRegistry); + bind(IconRegistry).toService(MonacoIconRegistry); }); export const MonacoConfigurationService = Symbol('MonacoConfigurationService'); diff --git a/packages/monaco/src/browser/monaco-icon-registry.ts b/packages/monaco/src/browser/monaco-icon-registry.ts index c387857ae833b..ce36ee9b8ab07 100644 --- a/packages/monaco/src/browser/monaco-icon-registry.ts +++ b/packages/monaco/src/browser/monaco-icon-registry.ts @@ -14,55 +14,34 @@ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 // ***************************************************************************** +import { injectable } from '@theia/core/shared/inversify'; import { Event } from '@theia/core'; import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/themeService'; import { IconRegistry } from '@theia/core/lib/browser/icon-registry'; import { IconDefinition, IconFontDefinition, getIconRegistry } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/iconRegistry'; -export class MonacoIconRegistry extends IconRegistry { +@injectable() +export class MonacoIconRegistry implements IconRegistry { - override readonly onDidChange: Event; + readonly onDidChange: Event; protected readonly monacoIconService = getIconRegistry(); - /** - * Register a icon to the registry. - * @param id The icon id - * @param defaults The default values - * @param description The description - */ registerIcon(id: string, defaults: ThemeIcon | IconDefinition, description?: string): ThemeIcon { return this.monacoIconService.registerIcon(id, defaults, description); } - /** - * Deregister a icon from the registry. - * @param id The icon id - */ deregisterIcon(id: string): void { return this.monacoIconService.deregisterIcon(id); } - /** - * Register a icon font to the registry. - * @param id The icon font id - * @param definition The icon font definition - */ registerIconFont(id: string, definition: IconFontDefinition): IconFontDefinition { return this.monacoIconService.registerIconFont(id, definition); } - /** - * Deregister an icon font from the registry. - * @param id The icon font id - */ deregisterIconFont(id: string): void { return this.monacoIconService.deregisterIconFont(id); } - /** - * Get the icon font for the given id - * @param id The icon font id - */ getIconFont(id: string): IconFontDefinition | undefined { return this.monacoIconService.getIconFont(id); } From 04ad54a87d4a5f610701ea8dca3a924acaddf8ea Mon Sep 17 00:00:00 2001 From: Vlad Arama Date: Wed, 25 Oct 2023 20:08:35 -0400 Subject: [PATCH 9/9] remove unused event --- packages/core/src/browser/icon-registry.ts | 2 -- .../monaco/src/browser/monaco-icon-registry.ts | 14 ++++++-------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/packages/core/src/browser/icon-registry.ts b/packages/core/src/browser/icon-registry.ts index e52462bc0b284..90c1088012f37 100644 --- a/packages/core/src/browser/icon-registry.ts +++ b/packages/core/src/browser/icon-registry.ts @@ -19,7 +19,6 @@ *--------------------------------------------------------------------------------------------*/ // code copied and modified from https://github.com/Microsoft/vscode/blob/main/src/vs/platform/theme/common/iconRegistry.ts -import { Event } from '../common/event'; import { URI } from 'vscode-uri'; export interface IconDefinition { @@ -61,7 +60,6 @@ export interface ThemeColor { export const IconRegistry = Symbol('IconRegistry'); export interface IconRegistry { - readonly onDidChange: Event; /** * Register a icon to the registry. * @param id The icon id diff --git a/packages/monaco/src/browser/monaco-icon-registry.ts b/packages/monaco/src/browser/monaco-icon-registry.ts index ce36ee9b8ab07..48cadadcdf118 100644 --- a/packages/monaco/src/browser/monaco-icon-registry.ts +++ b/packages/monaco/src/browser/monaco-icon-registry.ts @@ -15,7 +15,6 @@ // ***************************************************************************** import { injectable } from '@theia/core/shared/inversify'; -import { Event } from '@theia/core'; import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/themeService'; import { IconRegistry } from '@theia/core/lib/browser/icon-registry'; import { IconDefinition, IconFontDefinition, getIconRegistry } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/iconRegistry'; @@ -23,27 +22,26 @@ import { IconDefinition, IconFontDefinition, getIconRegistry } from '@theia/mona @injectable() export class MonacoIconRegistry implements IconRegistry { - readonly onDidChange: Event; - protected readonly monacoIconService = getIconRegistry(); + protected readonly iconRegistry = getIconRegistry(); registerIcon(id: string, defaults: ThemeIcon | IconDefinition, description?: string): ThemeIcon { - return this.monacoIconService.registerIcon(id, defaults, description); + return this.iconRegistry.registerIcon(id, defaults, description); } deregisterIcon(id: string): void { - return this.monacoIconService.deregisterIcon(id); + return this.iconRegistry.deregisterIcon(id); } registerIconFont(id: string, definition: IconFontDefinition): IconFontDefinition { - return this.monacoIconService.registerIconFont(id, definition); + return this.iconRegistry.registerIconFont(id, definition); } deregisterIconFont(id: string): void { - return this.monacoIconService.deregisterIconFont(id); + return this.iconRegistry.deregisterIconFont(id); } getIconFont(id: string): IconFontDefinition | undefined { - return this.monacoIconService.getIconFont(id); + return this.iconRegistry.getIconFont(id); } }