From 2319f162bf7226216da441bc47afc68639d1d68c Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 2 Jan 2017 11:16:10 +0200 Subject: [PATCH] Allow for theme switching --- .../services/standaloneColorServiceImpl.ts | 43 ++++++++++++++----- src/vs/editor/browser/standalone/colorizer.ts | 8 +++- .../standalone/standaloneCodeEditor.ts | 17 +++++++- .../browser/standalone/standaloneEditor.ts | 6 ++- .../common/model/textModelWithTokens.ts | 2 +- src/vs/editor/common/modes.ts | 15 ++++--- .../common/modes/monarch/monarchLexer.ts | 17 +++++--- .../common/services/standaloneColorService.ts | 3 +- src/vs/editor/common/standalone/themes.ts | 2 + 9 files changed, 83 insertions(+), 30 deletions(-) diff --git a/src/vs/editor/browser/services/standaloneColorServiceImpl.ts b/src/vs/editor/browser/services/standaloneColorServiceImpl.ts index f5e164bb841..e7a65eb27a4 100644 --- a/src/vs/editor/browser/services/standaloneColorServiceImpl.ts +++ b/src/vs/editor/browser/services/standaloneColorServiceImpl.ts @@ -4,40 +4,61 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import Event, { Emitter } from 'vs/base/common/event'; -import { Theme } from 'vs/editor/common/modes/supports/tokenization'; +import { Theme, IThemeRule } from 'vs/editor/common/modes/supports/tokenization'; import { IStandaloneColorService } from 'vs/editor/common/services/standaloneColorService'; -import { vs } from 'vs/editor/common/standalone/themes'; +import { vs, vs_dark, hc_black } from 'vs/editor/common/standalone/themes'; import * as dom from 'vs/base/browser/dom'; +import { TokenizationRegistry } from 'vs/editor/common/modes'; export class StandaloneColorServiceImpl implements IStandaloneColorService { _serviceBrand: any; - private _onThemeChanged: Emitter = new Emitter(); - public onThemeChanged: Event = this._onThemeChanged.event; - private _theme: Theme; private _styleElement: HTMLStyleElement; constructor() { - this._theme = Theme.createFromRawTheme(vs); this._styleElement = dom.createStyleSheet(); + this.setTheme('vs'); + } - let colorMap = this._theme.getColorMap(); + private static _generateCSS(colorMap: string[]): string { let rules: string[] = []; - for (let i = 0, len = colorMap.length; i < len; i++) { + for (let i = 1, len = colorMap.length; i < len; i++) { let color = colorMap[i]; rules[i] = `.mtk${i} { color: #${color}; }`; } rules.push('.mtki { font-style: italic; }'); rules.push('.mtkb { font-weight: bold; }'); rules.push('.mtku { text-decoration: underline; }'); - - this._styleElement.innerHTML = rules.join('\n'); + return rules.join('\n'); } public getTheme(): Theme { return this._theme; } + + public setTheme(themeName: string): void { + let themeRules: IThemeRule[] = null; + switch (themeName) { + case 'vs': + themeRules = vs; + break; + case 'vs-dark': + themeRules = vs_dark; + break; + case 'hc-black': + themeRules = hc_black; + break; + default: + themeRules = []; + } + console.log(themeRules); + this._theme = Theme.createFromRawTheme(themeRules); + let colorMap = this._theme.getColorMap(); + let cssRules = StandaloneColorServiceImpl._generateCSS(colorMap); + this._styleElement.innerHTML = cssRules; + + TokenizationRegistry.setColorMap(colorMap); + } } diff --git a/src/vs/editor/browser/standalone/colorizer.ts b/src/vs/editor/browser/standalone/colorizer.ts index 692513c2b8c..50872e29295 100644 --- a/src/vs/editor/browser/standalone/colorizer.ts +++ b/src/vs/editor/browser/standalone/colorizer.ts @@ -14,6 +14,7 @@ import { ViewLineToken } from 'vs/editor/common/core/viewLineToken'; import { LineParts } from 'vs/editor/common/core/lineParts'; import { LineTokens } from 'vs/editor/common/core/lineTokens'; import * as strings from 'vs/base/common/strings'; +import { IStandaloneColorService } from 'vs/editor/common/services/standaloneColorService'; export interface IColorizerOptions { tabSize?: number; @@ -26,7 +27,7 @@ export interface IColorizerElementOptions extends IColorizerOptions { export class Colorizer { - public static colorizeElement(modeService: IModeService, domNode: HTMLElement, options: IColorizerElementOptions): TPromise { + public static colorizeElement(standaloneColorService: IStandaloneColorService, modeService: IModeService, domNode: HTMLElement, options: IColorizerElementOptions): TPromise { options = options || {}; let theme = options.theme || 'vs'; let mimeType = options.mimeType || domNode.getAttribute('lang') || domNode.getAttribute('data-lang'); @@ -34,6 +35,9 @@ export class Colorizer { console.error('Mode not detected'); return; } + + standaloneColorService.setTheme(theme); + let text = domNode.firstChild.nodeValue; domNode.className += 'monaco-editor ' + theme; let render = (str: string) => { @@ -53,7 +57,7 @@ export class Colorizer { return new TPromise((c, e, p) => { listener = TokenizationRegistry.onDidChange((e) => { - if (e.languageId === languageId) { + if (e.languageIds.indexOf(languageId) >= 0) { stopListening(); c(void 0); } diff --git a/src/vs/editor/browser/standalone/standaloneCodeEditor.ts b/src/vs/editor/browser/standalone/standaloneCodeEditor.ts index c97af5d72aa..1b41468ce13 100644 --- a/src/vs/editor/browser/standalone/standaloneCodeEditor.ts +++ b/src/vs/editor/browser/standalone/standaloneCodeEditor.ts @@ -11,7 +11,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { ICommandService, ICommandHandler } from 'vs/platform/commands/common/commands'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { IActionDescriptor, ICodeEditorWidgetCreationOptions, IDiffEditorOptions, IModel, IModelChangedEvent, EventType } from 'vs/editor/common/editorCommon'; +import { IEditorOptions, IActionDescriptor, ICodeEditorWidgetCreationOptions, IDiffEditorOptions, IModel, IModelChangedEvent, EventType } from 'vs/editor/common/editorCommon'; import { ICodeEditorService } from 'vs/editor/common/services/codeEditorService'; import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService'; import { StandaloneKeybindingService } from 'vs/editor/browser/standalone/simpleServices'; @@ -19,6 +19,7 @@ import { IEditorContextViewService } from 'vs/editor/browser/standalone/standalo import { CodeEditor } from 'vs/editor/browser/codeEditor'; import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; import { ICodeEditor, IDiffEditor } from 'vs/editor/browser/editorBrowser'; +import { IStandaloneColorService } from 'vs/editor/common/services/standaloneColorService'; /** * The options to create an editor. @@ -57,6 +58,7 @@ export interface IStandaloneDiffEditor extends IDiffEditor { export class StandaloneEditor extends CodeEditor implements IStandaloneCodeEditor { private _standaloneKeybindingService: StandaloneKeybindingService; + private _standaloneColorService: IStandaloneColorService; private _contextViewService: IEditorContextViewService; private _ownsModel: boolean; private _toDispose2: IDisposable[]; @@ -70,10 +72,12 @@ export class StandaloneEditor extends CodeEditor implements IStandaloneCodeEdito @ICommandService commandService: ICommandService, @IContextKeyService contextKeyService: IContextKeyService, @IKeybindingService keybindingService: IKeybindingService, - @IContextViewService contextViewService: IContextViewService + @IContextViewService contextViewService: IContextViewService, + @IStandaloneColorService standaloneColorService: IStandaloneColorService ) { options = options || {}; super(domElement, options, instantiationService, codeEditorService, commandService, contextKeyService); + this._standaloneColorService = standaloneColorService; if (keybindingService instanceof StandaloneKeybindingService) { this._standaloneKeybindingService = keybindingService; @@ -111,6 +115,15 @@ export class StandaloneEditor extends CodeEditor implements IStandaloneCodeEdito this.dispose(); } + public updateOptions(newOptions: IEditorOptions): void { + let oldTheme = this._configuration.editor.viewInfo.theme; + super.updateOptions(newOptions); + let newTheme = this._configuration.editor.viewInfo.theme; + if (oldTheme !== newTheme) { + this._standaloneColorService.setTheme(newTheme); + } + } + public addCommand(keybinding: number, handler: ICommandHandler, context: string): string { if (!this._standaloneKeybindingService) { console.warn('Cannot add command because the editor is configured with an unrecognized KeybindingService'); diff --git a/src/vs/editor/browser/standalone/standaloneEditor.ts b/src/vs/editor/browser/standalone/standaloneEditor.ts index 7face25c799..4172b76b859 100644 --- a/src/vs/editor/browser/standalone/standaloneEditor.ts +++ b/src/vs/editor/browser/standalone/standaloneEditor.ts @@ -35,6 +35,7 @@ import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerServ import { ITextModelResolverService } from 'vs/editor/common/services/resolverService'; import { IState, ITokenizationSupport, TokenizationRegistry } from 'vs/editor/common/modes'; import { NULL_STATE, nullTokenize } from 'vs/editor/common/modes/nullMode'; +import { IStandaloneColorService } from 'vs/editor/common/services/standaloneColorService'; /** * @internal @@ -92,7 +93,8 @@ export function create(domElement: HTMLElement, options?: IEditorConstructionOpt services.get(ICommandService), services.get(IContextKeyService), services.get(IKeybindingService), - services.get(IContextViewService) + services.get(IContextViewService), + services.get(IStandaloneColorService) ); }); } @@ -240,7 +242,7 @@ export function createWebWorker(opts: IWebWorkerOptions): MonacoWebWorker * Colorize the contents of `domNode` using attribute `data-lang`. */ export function colorizeElement(domNode: HTMLElement, options: IColorizerElementOptions): TPromise { - return Colorizer.colorizeElement(StaticServices.modeService.get(), domNode, options); + return Colorizer.colorizeElement(StaticServices.standaloneColorService.get(), StaticServices.modeService.get(), domNode, options); } /** diff --git a/src/vs/editor/common/model/textModelWithTokens.ts b/src/vs/editor/common/model/textModelWithTokens.ts index 529b74e0c48..3c0b04280b0 100644 --- a/src/vs/editor/common/model/textModelWithTokens.ts +++ b/src/vs/editor/common/model/textModelWithTokens.ts @@ -95,7 +95,7 @@ export class TextModelWithTokens extends TextModel implements editorCommon.IToke this._languageIdentifier = languageIdentifier || NULL_LANGUAGE_IDENTIFIER; this._tokenizationListener = TokenizationRegistry.onDidChange((e) => { - if (e.languageId !== this._languageIdentifier.sid) { + if (e.languageIds.indexOf(this._languageIdentifier.sid) === -1) { return; } diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index d3fb45d5b43..93a3bc9e3f7 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -826,7 +826,7 @@ export const LinkProviderRegistry = new LanguageFeatureRegistry(); * @internal */ export interface ITokenizationSupportChangedEvent { - languageId: string; + languageIds: string[]; } /** @@ -850,20 +850,20 @@ export class TokenizationRegistryImpl { * Fire a change event for a language. * This is useful for languages that embed other languages. */ - public fire(languageId: string): void { - this._onDidChange.fire({ languageId: languageId }); + public fire(languageIds: string[]): void { + this._onDidChange.fire({ languageIds: languageIds }); } public register(languageId: string, support: ITokenizationSupport): IDisposable { this._map[languageId] = support; - this.fire(languageId); + this.fire([languageId]); return { dispose: () => { if (this._map[languageId] !== support) { return; } delete this._map[languageId]; - this.fire(languageId); + this.fire([languageId]); } }; } @@ -872,6 +872,11 @@ export class TokenizationRegistryImpl { return (this._map[languageId] || null); } + public setColorMap(colorMap: string[]): void { + this._colorMap = colorMap; + this.fire(Object.keys(this._map)); + } + public getColorMap(): string[] { return this._colorMap; } diff --git a/src/vs/editor/common/modes/monarch/monarchLexer.ts b/src/vs/editor/common/modes/monarch/monarchLexer.ts index 417f02e365f..84f09f1c8e8 100644 --- a/src/vs/editor/common/modes/monarch/monarchLexer.ts +++ b/src/vs/editor/common/modes/monarch/monarchLexer.ts @@ -408,10 +408,17 @@ export class MonarchTokenizer implements modes.ITokenizationSupport { if (emitting) { return; } - let isOneOfMyEmbeddedModes = this._embeddedModes[e.languageId]; + let isOneOfMyEmbeddedModes = false; + for (let i = 0, len = e.languageIds.length; i < len; i++) { + let languageId = e.languageIds[i]; + if (this._embeddedModes[languageId]) { + isOneOfMyEmbeddedModes = true; + break; + } + } if (isOneOfMyEmbeddedModes) { emitting = true; - modes.TokenizationRegistry.fire(this._modeId); + modes.TokenizationRegistry.fire([this._modeId]); emitting = false; } }); @@ -801,6 +808,9 @@ export class MonarchTokenizer implements modes.ITokenizationSupport { let modeId = this._modeService.getModeId(mimetypeOrModeId); + // Fire mode loading event + this._modeService.getOrCreateMode(modeId); + let mode = this._modeService.getMode(modeId); if (mode) { // Re-emit tokenizationSupport change events from all modes that I ever embedded @@ -808,9 +818,6 @@ export class MonarchTokenizer implements modes.ITokenizationSupport { return mode; } - // Fire mode loading event - this._modeService.getOrCreateMode(modeId); - this._embeddedModes[modeId] = true; return null; diff --git a/src/vs/editor/common/services/standaloneColorService.ts b/src/vs/editor/common/services/standaloneColorService.ts index 67ff7bfaa71..c63d42109af 100644 --- a/src/vs/editor/common/services/standaloneColorService.ts +++ b/src/vs/editor/common/services/standaloneColorService.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import Event from 'vs/base/common/event'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { Theme } from 'vs/editor/common/modes/supports/tokenization'; @@ -13,7 +12,7 @@ export var IStandaloneColorService = createDecorator('s export interface IStandaloneColorService { _serviceBrand: any; - onThemeChanged: Event; + setTheme(themeName: string): void; getTheme(): Theme; } diff --git a/src/vs/editor/common/standalone/themes.ts b/src/vs/editor/common/standalone/themes.ts index 83ac6f70efc..cbe3fcbb8ef 100644 --- a/src/vs/editor/common/standalone/themes.ts +++ b/src/vs/editor/common/standalone/themes.ts @@ -9,6 +9,7 @@ import { IThemeRule } from 'vs/editor/common/modes/supports/tokenization'; /* -------------------------------- Begin vs tokens -------------------------------- */ export const vs: IThemeRule[] = [ + { token: '', foreground: '000000' }, { token: 'invalid', foreground: 'cd3131' }, { token: 'emphasis', fontStyle: 'italic' }, { token: 'strong', fontStyle: 'bold' }, @@ -132,6 +133,7 @@ export const vs_dark: IThemeRule[] = [ /* -------------------------------- Begin hc-black tokens -------------------------------- */ export const hc_black: IThemeRule[] = [ + { token: '', foreground: 'FFFFFF' }, { token: 'invalid', foreground: 'f44747' }, { token: 'emphasis', fontStyle: 'italic' }, { token: 'strong', fontStyle: 'bold' }, -- GitLab