From 1fe99da60be0da63bcf22a8efefb5c9363a771b9 Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Thu, 31 Oct 2019 18:09:11 +0000 Subject: [PATCH 01/65] [plugin/theming] #4831: load themes from json files Signed-off-by: Anton Kosyakov --- packages/core/src/browser/theming.ts | 11 +- .../src/browser/monaco-frontend-module.ts | 3 + .../src/browser/monaco-theming-service.ts | 121 ++++++++++++++++++ .../plugin-ext/src/common/plugin-protocol.ts | 18 +++ .../src/hosted/node/scanners/scanner-theia.ts | 28 +++- .../browser/plugin-contribution-handler.ts | 12 ++ .../src/main/browser/plugin-shared-style.ts | 4 +- .../src/main/browser/webview/webview.ts | 3 +- 8 files changed, 194 insertions(+), 6 deletions(-) create mode 100644 packages/monaco/src/browser/monaco-theming-service.ts diff --git a/packages/core/src/browser/theming.ts b/packages/core/src/browser/theming.ts index 72949d198c16f..4f9b321a9196d 100644 --- a/packages/core/src/browser/theming.ts +++ b/packages/core/src/browser/theming.ts @@ -17,6 +17,7 @@ import { injectable, inject } from 'inversify'; import { CommandRegistry, CommandContribution, CommandHandler, Command } from '../common/command'; import { Emitter, Event } from '../common/event'; +import { Disposable } from '../common/disposable'; import { QuickOpenModel, QuickOpenItem, QuickOpenMode } from './quick-open/quick-open-model'; import { QuickOpenService } from './quick-open/quick-open-service'; import { FrontendApplicationConfigProvider } from './frontend-application-config-provider'; @@ -63,10 +64,18 @@ export class ThemeService { global[ThemeServiceSymbol] = this; } - register(...themes: Theme[]): void { + register(...themes: Theme[]): Disposable { for (const theme of themes) { this.themes[theme.id] = theme; } + return Disposable.create(() => { + for (const theme of themes) { + delete this.themes[theme.id]; + } + if (this.activeTheme && !this.themes[this.activeTheme.id]) { + this.startupTheme(); + } + }); } getThemes(): Theme[] { diff --git a/packages/monaco/src/browser/monaco-frontend-module.ts b/packages/monaco/src/browser/monaco-frontend-module.ts index 91f1967f016a4..b181a935a0251 100644 --- a/packages/monaco/src/browser/monaco-frontend-module.ts +++ b/packages/monaco/src/browser/monaco-frontend-module.ts @@ -62,12 +62,15 @@ 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 { MonacoThemingService } from './monaco-theming-service'; decorate(injectable(), MonacoToProtocolConverter); decorate(injectable(), ProtocolToMonacoConverter); decorate(injectable(), monaco.contextKeyService.ContextKeyService); export default new ContainerModule((bind, unbind, isBound, rebind) => { + bind(MonacoThemingService).toSelf().inSingletonScope(); + bind(MonacoContextKeyService).toSelf().inSingletonScope(); rebind(ContextKeyService).toService(MonacoContextKeyService); diff --git a/packages/monaco/src/browser/monaco-theming-service.ts b/packages/monaco/src/browser/monaco-theming-service.ts new file mode 100644 index 0000000000000..1c5126d6a1efe --- /dev/null +++ b/packages/monaco/src/browser/monaco-theming-service.ts @@ -0,0 +1,121 @@ +/******************************************************************************** + * Copyright (C) 2019 TypeFox 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 + ********************************************************************************/ + +// tslint:disable:no-any + +import { injectable, inject } from 'inversify'; +import * as jsoncparser from 'jsonc-parser'; +import { ThemeService, BuiltinThemeProvider } from '@theia/core/lib/browser/theming'; +import URI from '@theia/core/lib/common/uri'; +import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable'; +import { FileSystem } from '@theia/filesystem/lib/common/filesystem'; +import { MonacoThemeRegistry } from './textmate/monaco-theme-registry'; + +export interface MonacoTheme { + id?: string; + label?: string; + uiTheme?: 'vs' | 'vs-dark' | 'hc-black'; + description?: string; + uri: string; +} + +@injectable() +export class MonacoThemingService { + + @inject(FileSystem) + protected readonly fileSystem: FileSystem; + + // tslint:disable-next-line:no-any + register(theme: MonacoTheme, pendingIncludes: { [uri: string]: Promise } = {}): Disposable { + const toDispose = new DisposableCollection(Disposable.create(() => { /* mark as not disposed */ })); + this.doRegister(theme, pendingIncludes, toDispose); + return toDispose; + } + + protected async doRegister(theme: MonacoTheme, + pendingIncludes: { [uri: string]: Promise }, + toDispose: DisposableCollection + ): Promise { + try { + if (new URI(theme.uri).path.ext !== '.json') { + console.error('Unknown theme file: ' + theme.uri); + return; + } + const includes = {}; + const json = await this.loadTheme(theme.uri, includes, pendingIncludes, toDispose); + if (toDispose.disposed) { + return; + } + const uiTheme = theme.uiTheme || 'vs-dark'; + const label = theme.label || new URI(theme.uri).path.base; + const id = theme.id || label; + const cssSelector = this.toCssSelector(id); + const editorTheme = MonacoThemeRegistry.SINGLETON.register(json, includes, cssSelector, uiTheme).name!; + const type = uiTheme === 'vs' ? 'light' : uiTheme === 'vs-dark' ? 'dark' : 'hc'; + const builtInTheme = uiTheme === 'vs' ? BuiltinThemeProvider.lightCss : BuiltinThemeProvider.darkCss; + toDispose.push(ThemeService.get().register({ + type, + id, + label, + description: theme.description, + editorTheme, + activate(): void { + builtInTheme.use(); + }, + deactivate(): void { + builtInTheme.unuse(); + } + })); + } catch (e) { + console.error('Failed to load theme from ' + theme.uri, e); + } + } + + protected async loadTheme( + uri: string, + includes: { [include: string]: any }, + pendingIncludes: { [uri: string]: Promise }, + toDispose: DisposableCollection + ): Promise { + // tslint:enabled:no-any + const { content } = await this.fileSystem.resolveContent(uri); + if (toDispose.disposed) { + return undefined; + } + const json = jsoncparser.parse(content, undefined, { disallowComments: false }); + if (json.include) { + const includeUri = new URI(uri).parent.resolve(json.include).toString(); + if (!pendingIncludes[includeUri]) { + pendingIncludes[includeUri] = this.loadTheme(includeUri, includes, pendingIncludes, toDispose); + } + includes[json.include] = await pendingIncludes[includeUri]; + if (toDispose.disposed) { + return; + } + } + return json; + } + + /* remove all characters that are not allowed in css */ + protected toCssSelector(str: string): string { + str = str.replace(/[^\-a-zA-Z0-9]/g, '-'); + if (str.charAt(0).match(/[0-9\-]/)) { + str = '-' + str; + } + return str; + } + +} diff --git a/packages/plugin-ext/src/common/plugin-protocol.ts b/packages/plugin-ext/src/common/plugin-protocol.ts index c2acff87e9300..92dd58630e081 100644 --- a/packages/plugin-ext/src/common/plugin-protocol.ts +++ b/packages/plugin-ext/src/common/plugin-protocol.ts @@ -76,6 +76,7 @@ export interface PluginPackageContribution { keybindings?: PluginPackageKeybinding | PluginPackageKeybinding[]; debuggers?: PluginPackageDebuggersContribution[]; snippets: PluginPackageSnippetsContribution[]; + themes?: PluginThemeContribution[]; taskDefinitions?: PluginTaskDefinitionContribution[]; problemMatchers?: PluginProblemMatcherContribution[]; problemPatterns?: PluginProblemPatternContribution[]; @@ -134,6 +135,14 @@ export interface PluginPackageSnippetsContribution { path?: string; } +export interface PluginThemeContribution { + id?: string; + label?: string; + description?: string; + path?: string; + uiTheme?: 'vs' | 'vs-dark' | 'hc-black'; +} + export interface PlatformSpecificAdapterContribution { program?: string; args?: string[]; @@ -408,6 +417,7 @@ export interface PluginContribution { keybindings?: Keybinding[]; debuggers?: DebuggerContribution[]; snippets?: SnippetContribution[]; + themes?: ThemeContribution[]; taskDefinitions?: TaskDefinition[]; problemMatchers?: ProblemMatcherContribution[]; problemPatterns?: ProblemPatternContribution[]; @@ -419,6 +429,14 @@ export interface SnippetContribution { language?: string } +export interface ThemeContribution { + id?: string; + label?: string; + description?: string; + uri: string; + uiTheme?: 'vs' | 'vs-dark' | 'hc-black'; +} + 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 6c906383d04e5..22d4368f5e7d1 100644 --- a/packages/plugin-ext/src/hosted/node/scanners/scanner-theia.ts +++ b/packages/plugin-ext/src/hosted/node/scanners/scanner-theia.ts @@ -43,7 +43,8 @@ import { SnippetContribution, PluginPackageCommand, PluginCommand, - IconUrl + IconUrl, + ThemeContribution } from '../../../common/plugin-protocol'; import * as fs from 'fs'; import * as path from 'path'; @@ -271,6 +272,12 @@ export class TheiaPluginScanner implements PluginScanner { } catch (err) { console.error(`Could not read '${rawPlugin.name}' contribution 'snippets'.`, rawPlugin.contributes!.snippets, err); } + + try { + contributions.themes = this.readThemes(rawPlugin); + } catch (err) { + console.error(`Could not read '${rawPlugin.name}' contribution 'themes'.`, rawPlugin.contributes.themes, err); + } return contributions; } @@ -293,6 +300,25 @@ export class TheiaPluginScanner implements PluginScanner { return PluginPackage.toPluginUrl(pck, relativePath); } + protected readThemes(pck: PluginPackage): ThemeContribution[] | undefined { + if (!pck.contributes || !pck.contributes.themes) { + return undefined; + } + const result: ThemeContribution[] = []; + for (const contribution of pck.contributes.themes) { + if (contribution.path) { + result.push({ + id: contribution.id, + uri: FileUri.create(path.join(pck.packagePath, contribution.path)).toString(), + description: contribution.description, + label: contribution.label, + uiTheme: contribution.uiTheme + }); + } + } + 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 ba8a0b8af8353..5d5be3c99a948 100644 --- a/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts +++ b/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts @@ -31,6 +31,7 @@ import { Emitter } from '@theia/core/lib/common/event'; import { TaskDefinitionRegistry, ProblemMatcherRegistry, ProblemPatternRegistry } from '@theia/task/lib/browser'; 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'; @injectable() export class PluginContributionHandler { @@ -79,6 +80,9 @@ export class PluginContributionHandler { @inject(DebugSchemaUpdater) protected readonly debugSchema: DebugSchemaUpdater; + @inject(MonacoThemingService) + protected readonly monacoThemingService: MonacoThemingService; + protected readonly commandHandlers = new Map(); protected readonly onDidRegisterCommandHandlerEmitter = new Emitter(); @@ -230,6 +234,13 @@ export class PluginContributionHandler { } } + if (contributions.themes && contributions.themes.length) { + const includes = {}; + for (const theme of contributions.themes) { + pushContribution(`themes.${theme.uri}`, () => this.monacoThemingService.register(theme, includes)); + } + } + if (contributions.taskDefinitions) { for (const taskDefinition of contributions.taskDefinitions) { pushContribution(`taskDefinitions.${taskDefinition.taskType}`, @@ -473,4 +484,5 @@ export class PluginContributionHandler { } } } + } diff --git a/packages/plugin-ext/src/main/browser/plugin-shared-style.ts b/packages/plugin-ext/src/main/browser/plugin-shared-style.ts index 42c7c5a3419a0..b6561344ee095 100644 --- a/packages/plugin-ext/src/main/browser/plugin-shared-style.ts +++ b/packages/plugin-ext/src/main/browser/plugin-shared-style.ts @@ -16,7 +16,7 @@ import { injectable } from 'inversify'; import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable'; -import { ThemeService, Theme, BuiltinThemeProvider } from '@theia/core/lib/browser/theming'; +import { ThemeService, Theme } from '@theia/core/lib/browser/theming'; import { IconUrl } from '../../common/plugin-protocol'; import { Reference, SyncReferenceCollection } from '@theia/core/lib/common/reference'; @@ -110,7 +110,7 @@ export class PluginSharedStyle { background-position: 2px; width: ${size}px; height: ${size}px; - background: no-repeat url("${theme.id === BuiltinThemeProvider.lightTheme.id ? lightIconUrl : darkIconUrl}"); + background: no-repeat url("${theme.type === 'light' ? lightIconUrl : darkIconUrl}"); background-size: ${size}px; `)); return { diff --git a/packages/plugin-ext/src/main/browser/webview/webview.ts b/packages/plugin-ext/src/main/browser/webview/webview.ts index 35a3e4cdaffcc..1e7a84167c5d1 100644 --- a/packages/plugin-ext/src/main/browser/webview/webview.ts +++ b/packages/plugin-ext/src/main/browser/webview/webview.ts @@ -38,7 +38,6 @@ import { open, OpenerService } from '@theia/core/lib/browser/opener-service'; import { KeybindingRegistry } from '@theia/core/lib/browser/keybinding'; import { Schemes } from '../../../common/uri-components'; import { PluginSharedStyle } from '../plugin-shared-style'; -import { BuiltinThemeProvider } from '@theia/core/lib/browser/theming'; import { WebviewThemeDataProvider } from './webview-theme-data-provider'; import { ExternalUriService } from '@theia/core/lib/browser/external-uri-service'; import { OutputChannelManager } from '@theia/output/lib/common/output-channel'; @@ -352,7 +351,7 @@ export class WebviewWidget extends BaseWidget implements StatefulWidget { const iconClass = `webview-${this.identifier.id}-file-icon`; this.toDisposeOnIcon.push(this.sharedStyle.insertRule( `.theia-webview-icon.${iconClass}::before`, - theme => `background-image: url(${theme.id === BuiltinThemeProvider.lightTheme.id ? lightIconUrl : darkIconUrl});` + theme => `background-image: url(${theme.type === 'light' ? lightIconUrl : darkIconUrl});` )); this.title.iconClass = `theia-webview-icon ${iconClass}`; } else { From 6a11491ec429898ec21b6587612c55cc47235ecc Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Fri, 1 Nov 2019 07:27:36 +0000 Subject: [PATCH 02/65] [monaco] preserve color themes between user sessions and reconnections Signed-off-by: Anton Kosyakov --- packages/core/src/browser/theming.ts | 18 ++++- .../src/browser/monaco-frontend-module.ts | 2 + .../src/browser/monaco-theming-service.ts | 81 ++++++++++++++----- .../browser/textmate/monaco-theme-registry.ts | 12 +-- 4 files changed, 86 insertions(+), 27 deletions(-) diff --git a/packages/core/src/browser/theming.ts b/packages/core/src/browser/theming.ts index 4f9b321a9196d..646ca8b689108 100644 --- a/packages/core/src/browser/theming.ts +++ b/packages/core/src/browser/theming.ts @@ -68,16 +68,28 @@ export class ThemeService { for (const theme of themes) { this.themes[theme.id] = theme; } + this.validateActiveTheme(); return Disposable.create(() => { for (const theme of themes) { delete this.themes[theme.id]; } - if (this.activeTheme && !this.themes[this.activeTheme.id]) { - this.startupTheme(); - } + this.validateActiveTheme(); }); } + protected validateActiveTheme(): void { + if (!this.activeTheme) { + return; + } + const theme = this.themes[this.activeTheme.id]; + if (!theme) { + this.loadUserTheme(); + } else if (theme !== this.activeTheme) { + this.activeTheme = undefined; + this.setCurrentTheme(theme.id); + } + } + getThemes(): Theme[] { const result = []; for (const o in this.themes) { diff --git a/packages/monaco/src/browser/monaco-frontend-module.ts b/packages/monaco/src/browser/monaco-frontend-module.ts index b181a935a0251..b57a653b3a582 100644 --- a/packages/monaco/src/browser/monaco-frontend-module.ts +++ b/packages/monaco/src/browser/monaco-frontend-module.ts @@ -68,6 +68,8 @@ decorate(injectable(), MonacoToProtocolConverter); decorate(injectable(), ProtocolToMonacoConverter); decorate(injectable(), monaco.contextKeyService.ContextKeyService); +MonacoThemingService.init(); + export default new ContainerModule((bind, unbind, isBound, rebind) => { bind(MonacoThemingService).toSelf().inSingletonScope(); diff --git a/packages/monaco/src/browser/monaco-theming-service.ts b/packages/monaco/src/browser/monaco-theming-service.ts index 1c5126d6a1efe..e22d48f5b66ca 100644 --- a/packages/monaco/src/browser/monaco-theming-service.ts +++ b/packages/monaco/src/browser/monaco-theming-service.ts @@ -22,7 +22,7 @@ import { ThemeService, BuiltinThemeProvider } from '@theia/core/lib/browser/them import URI from '@theia/core/lib/common/uri'; import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable'; import { FileSystem } from '@theia/filesystem/lib/common/filesystem'; -import { MonacoThemeRegistry } from './textmate/monaco-theme-registry'; +import { MonacoThemeRegistry, ThemeMix } from './textmate/monaco-theme-registry'; export interface MonacoTheme { id?: string; @@ -35,6 +35,8 @@ export interface MonacoTheme { @injectable() export class MonacoThemingService { + static monacoThemes = new Map(); + @inject(FileSystem) protected readonly fileSystem: FileSystem; @@ -62,23 +64,9 @@ export class MonacoThemingService { const uiTheme = theme.uiTheme || 'vs-dark'; const label = theme.label || new URI(theme.uri).path.base; const id = theme.id || label; - const cssSelector = this.toCssSelector(id); - const editorTheme = MonacoThemeRegistry.SINGLETON.register(json, includes, cssSelector, uiTheme).name!; - const type = uiTheme === 'vs' ? 'light' : uiTheme === 'vs-dark' ? 'dark' : 'hc'; - const builtInTheme = uiTheme === 'vs' ? BuiltinThemeProvider.lightCss : BuiltinThemeProvider.darkCss; - toDispose.push(ThemeService.get().register({ - type, - id, - label, - description: theme.description, - editorTheme, - activate(): void { - builtInTheme.use(); - }, - deactivate(): void { - builtInTheme.unuse(); - } - })); + const cssSelector = MonacoThemingService.toCssSelector(id); + const data = MonacoThemeRegistry.SINGLETON.register(json, includes, cssSelector, uiTheme); + toDispose.push(MonacoThemingService.doRegister({ id, label, description: theme.description, uiTheme, data })); } catch (e) { console.error('Failed to load theme from ' + theme.uri, e); } @@ -109,8 +97,54 @@ export class MonacoThemingService { return json; } + static init(): void { + ThemeService.get().onThemeChange(e => + MonacoThemingService.store(MonacoThemingService.monacoThemes.get(e.newTheme.id)) + ); + try { + const value = window.localStorage.getItem('monacoTheme'); + if (value) { + const state: MonacoThemingService.MonacoThemeState = JSON.parse(value); + MonacoThemeRegistry.SINGLETON.setTheme(state.data.name!, state.data); + MonacoThemingService.doRegister(state); + } + } catch (e) { + console.error('Failed to restore monaco theme', e); + } + } + + static store(state: MonacoThemingService.MonacoThemeState | undefined): void { + if (state) { + window.localStorage.setItem('monacoTheme', JSON.stringify(state)); + } else { + window.localStorage.removeItem('monacoTheme'); + } + } + + static doRegister(state: MonacoThemingService.MonacoThemeState): Disposable { + const { id, label, description, uiTheme, data } = state; + const type = uiTheme === 'vs' ? 'light' : uiTheme === 'vs-dark' ? 'dark' : 'hc'; + const builtInTheme = uiTheme === 'vs' ? BuiltinThemeProvider.lightCss : BuiltinThemeProvider.darkCss; + const toDispose = new DisposableCollection(ThemeService.get().register({ + type, + id, + label, + description: description, + editorTheme: data.name!, + activate(): void { + builtInTheme.use(); + }, + deactivate(): void { + builtInTheme.unuse(); + } + })); + MonacoThemingService.monacoThemes.set(id, state); + toDispose.push(Disposable.create(() => MonacoThemingService.monacoThemes.delete(id))); + return toDispose; + } + /* remove all characters that are not allowed in css */ - protected toCssSelector(str: string): string { + static toCssSelector(str: string): string { str = str.replace(/[^\-a-zA-Z0-9]/g, '-'); if (str.charAt(0).match(/[0-9\-]/)) { str = '-' + str; @@ -119,3 +153,12 @@ export class MonacoThemingService { } } +export namespace MonacoThemingService { + export interface MonacoThemeState { + id: string, + label: string, + description?: string, + uiTheme: MonacoTheme['uiTheme'] + data: ThemeMix + } +} diff --git a/packages/monaco/src/browser/textmate/monaco-theme-registry.ts b/packages/monaco/src/browser/textmate/monaco-theme-registry.ts index 18465aa331150..ce1eb159bfe62 100644 --- a/packages/monaco/src/browser/textmate/monaco-theme-registry.ts +++ b/packages/monaco/src/browser/textmate/monaco-theme-registry.ts @@ -29,6 +29,12 @@ export class MonacoThemeRegistry { return this.themes.get(name); } + setTheme(name: string, data: ThemeMix): void { + // monaco auto refrehes a theme with new data + monaco.editor.defineTheme(name, data); + this.themes.set(name, data); + } + /** * Register VS Code compatible themes */ @@ -42,10 +48,6 @@ export class MonacoThemeRegistry { rules: [], settings: [] }; - if (this.themes.has(name)) { - return this.themes.get(name)!; - } - this.themes.set(name, result); if (typeof json.include !== 'undefined') { if (!includes || !includes[json.include]) { console.error(`Couldn't resolve includes theme ${json.include}.`); @@ -80,7 +82,7 @@ export class MonacoThemeRegistry { if (result.colors && result.colors['editor.background']) { result.encodedTokensColors[2] = result.colors['editor.background']; } - monaco.editor.defineTheme(givenName, result); + this.setTheme(givenName, result); } return result; } From 27a52429cfd10201086ad1a39e1c311e165c729d Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Fri, 1 Nov 2019 08:14:01 +0000 Subject: [PATCH 03/65] [plugin]: handle colors contribution point Signed-off-by: Anton Kosyakov --- .../browser/color-application-contribution.ts | 11 ++--- packages/core/src/browser/color-registry.ts | 38 ++++++++++++++-- .../src/browser/monaco-color-registry.ts | 8 ++-- packages/monaco/src/typings/monaco/index.d.ts | 2 +- .../plugin-ext/src/common/plugin-protocol.ts | 9 ++++ .../src/hosted/node/scanners/scanner-theia.ts | 45 +++++++++++++++++++ .../browser/plugin-contribution-handler.ts | 8 ++++ .../plugin-ext/src/main/browser/scm-main.ts | 12 +++-- .../webview/webview-theme-data-provider.ts | 10 ++--- .../decorations/scm-navigator-decorator.ts | 17 +++---- 10 files changed, 127 insertions(+), 33 deletions(-) diff --git a/packages/core/src/browser/color-application-contribution.ts b/packages/core/src/browser/color-application-contribution.ts index 9f03df91e57a1..398339a7231ed 100644 --- a/packages/core/src/browser/color-application-contribution.ts +++ b/packages/core/src/browser/color-application-contribution.ts @@ -46,6 +46,7 @@ export class ColorApplicationContribution implements FrontendApplicationContribu this.update(); ThemeService.get().onThemeChange(() => this.update()); + this.colors.onDidChange(() => this.update()); } protected readonly toUpdate = new DisposableCollection(); @@ -61,11 +62,11 @@ export class ColorApplicationContribution implements FrontendApplicationContribu const documentElement = document.documentElement; if (documentElement) { for (const id of this.colors.getColors()) { - const color = this.colors.getCurrentColor(id); - if (color) { - const propertyName = `--theia-${id.replace('.', '-')}`; - documentElement.style.setProperty(propertyName, color); - this.toUpdate.push(Disposable.create(() => documentElement.style.removeProperty(propertyName))); + const variable = this.colors.getCurrentCssVariable(id); + if (variable) { + const { name, value } = variable; + documentElement.style.setProperty(name, value); + this.toUpdate.push(Disposable.create(() => documentElement.style.removeProperty(name))); } } } diff --git a/packages/core/src/browser/color-registry.ts b/packages/core/src/browser/color-registry.ts index 03fcc2ec19530..22d5519b10ba8 100644 --- a/packages/core/src/browser/color-registry.ts +++ b/packages/core/src/browser/color-registry.ts @@ -15,7 +15,8 @@ ********************************************************************************/ import { injectable } from 'inversify'; -import { Disposable } from '../common/disposable'; +import { DisposableCollection, Disposable } from '../common/disposable'; +import { Emitter } from '../common/event'; export interface ColorDefaults { light?: string @@ -23,24 +24,55 @@ export interface ColorDefaults { hc?: string } -export interface ColorOptions { +export interface ColorDefinition { + id: string defaults?: ColorDefaults description: string } +export interface ColorCssVariable { + name: string + value: string +} + /** * It should be implemented by an extension, e.g. by the monaco extension. */ @injectable() export class ColorRegistry { + protected readonly onDidChangeEmitter = new Emitter(); + readonly onDidChange = this.onDidChangeEmitter.event; + protected fireDidChange(): void { + this.onDidChangeEmitter.fire(undefined); + } + *getColors(): IterableIterator { } + getCurrentCssVariable(id: string): ColorCssVariable | undefined { + const value = this.getCurrentColor(id); + if (!value) { + return undefined; + } + const name = this.toCssVariableName(id); + return { name, value }; + } + + toCssVariableName(id: string, prefix = 'theia'): string { + return `--${prefix}-${id.replace('.', '-')}`; + } + getCurrentColor(id: string): string | undefined { return undefined; } - register(id: string, options: ColorOptions): Disposable { + register(...definitions: ColorDefinition[]): Disposable { + const result = new DisposableCollection(...definitions.map(definition => this.doRegister(definition))); + this.fireDidChange(); + return result; + } + + protected doRegister(definition: ColorDefinition): Disposable { return Disposable.NULL; } diff --git a/packages/monaco/src/browser/monaco-color-registry.ts b/packages/monaco/src/browser/monaco-color-registry.ts index f776ae4d9a721..c4f118665efad 100644 --- a/packages/monaco/src/browser/monaco-color-registry.ts +++ b/packages/monaco/src/browser/monaco-color-registry.ts @@ -15,11 +15,11 @@ ********************************************************************************/ import { injectable } from 'inversify'; -import { ColorRegistry, ColorOptions } from '@theia/core/lib/browser/color-registry'; +import { ColorRegistry, ColorDefinition } from '@theia/core/lib/browser/color-registry'; import { Disposable } from '@theia/core/lib/common/disposable'; @injectable() -export class MonacoColorRegistry implements ColorRegistry { +export class MonacoColorRegistry extends ColorRegistry { protected readonly monacoThemeService = monaco.services.StaticServices.standaloneThemeService.get(); protected readonly monacoColorRegistry = monaco.color.getColorRegistry(); @@ -35,8 +35,8 @@ export class MonacoColorRegistry implements ColorRegistry { return color && color.toString(); } - register(id: string, options: ColorOptions): Disposable { - const identifier = this.monacoColorRegistry.registerColor(id, options.defaults, options.description); + protected doRegister(definition: ColorDefinition): Disposable { + const identifier = this.monacoColorRegistry.registerColor(definition.id, definition.defaults, definition.description); return Disposable.create(() => this.monacoColorRegistry.deregisterColor(identifier)); } diff --git a/packages/monaco/src/typings/monaco/index.d.ts b/packages/monaco/src/typings/monaco/index.d.ts index 4e5f2b07213c6..6e7653b6d5182 100644 --- a/packages/monaco/src/typings/monaco/index.d.ts +++ b/packages/monaco/src/typings/monaco/index.d.ts @@ -544,7 +544,7 @@ declare module monaco.color { readonly id: string; } export interface ColorDefaults { - ligh?: string; + light?: string; dark?: string; hc?: string; } diff --git a/packages/plugin-ext/src/common/plugin-protocol.ts b/packages/plugin-ext/src/common/plugin-protocol.ts index 92dd58630e081..94f9d0f941a15 100644 --- a/packages/plugin-ext/src/common/plugin-protocol.ts +++ b/packages/plugin-ext/src/common/plugin-protocol.ts @@ -24,6 +24,7 @@ import { RecursivePartial } from '@theia/core/lib/common/types'; import { PreferenceSchema, PreferenceSchemaProperties } from '@theia/core/lib/common/preferences/preference-schema'; import { ProblemMatcherContribution, ProblemPatternContribution, TaskDefinition } from '@theia/task/lib/common'; import { FileStat } from '@theia/filesystem/lib/common'; +import { ColorDefinition } from '@theia/core/lib/browser/color-registry'; export const hostedServicePath = '/services/hostedPlugin'; @@ -77,6 +78,7 @@ export interface PluginPackageContribution { debuggers?: PluginPackageDebuggersContribution[]; snippets: PluginPackageSnippetsContribution[]; themes?: PluginThemeContribution[]; + colors?: PluginColorContribution[]; taskDefinitions?: PluginTaskDefinitionContribution[]; problemMatchers?: PluginProblemMatcherContribution[]; problemPatterns?: PluginProblemPatternContribution[]; @@ -135,6 +137,12 @@ export interface PluginPackageSnippetsContribution { path?: string; } +export interface PluginColorContribution { + id?: string; + description?: string; + defaults?: { light?: string, dark?: string, highContrast?: string }; +} + export interface PluginThemeContribution { id?: string; label?: string; @@ -418,6 +426,7 @@ export interface PluginContribution { debuggers?: DebuggerContribution[]; snippets?: SnippetContribution[]; themes?: ThemeContribution[]; + colors?: ColorDefinition[]; taskDefinitions?: TaskDefinition[]; problemMatchers?: ProblemMatcherContribution[]; problemPatterns?: ProblemPatternContribution[]; 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 22d4368f5e7d1..f4302c85fd8e7 100644 --- a/packages/plugin-ext/src/hosted/node/scanners/scanner-theia.ts +++ b/packages/plugin-ext/src/hosted/node/scanners/scanner-theia.ts @@ -58,6 +58,7 @@ import { FileUri } from '@theia/core/lib/node/file-uri'; import { PreferenceSchema, PreferenceSchemaProperties } from '@theia/core/lib/common/preferences/preference-schema'; import { RecursivePartial } from '@theia/core/lib/common/types'; import { ProblemMatcherContribution, ProblemPatternContribution, TaskDefinition } from '@theia/task/lib/common/task-protocol'; +import { ColorDefinition } from '@theia/core/lib/browser/color-registry'; namespace nls { export function localize(key: string, _default: string): string { @@ -71,6 +72,8 @@ const INTERNAL_CONSOLE_OPTIONS_SCHEMA = { description: nls.localize('internalConsoleOptions', 'Controls when the internal debug console should open.') }; +const colorIdPattern = '^\\w+[.\\w+]*$'; + @injectable() export class TheiaPluginScanner implements PluginScanner { @@ -278,6 +281,12 @@ export class TheiaPluginScanner implements PluginScanner { } catch (err) { console.error(`Could not read '${rawPlugin.name}' contribution 'themes'.`, rawPlugin.contributes.themes, err); } + + try { + contributions.colors = this.readColors(rawPlugin); + } catch (err) { + console.error(`Could not read '${rawPlugin.name}' contribution 'colors'.`, rawPlugin.contributes.colors, err); + } return contributions; } @@ -300,6 +309,42 @@ export class TheiaPluginScanner implements PluginScanner { return PluginPackage.toPluginUrl(pck, relativePath); } + protected readColors(pck: PluginPackage): ColorDefinition[] | undefined { + if (!pck.contributes || !pck.contributes.colors) { + return undefined; + } + const result: ColorDefinition[] = []; + for (const contribution of pck.contributes.colors) { + if (typeof contribution.id !== 'string' || contribution.id.length === 0) { + console.error("'configuration.colors.id' must be defined and can not be empty"); + continue; + } + if (!contribution.id.match(colorIdPattern)) { + console.error("'configuration.colors.id' must follow the word[.word]*"); + continue; + } + if (typeof contribution.description !== 'string' || contribution.id.length === 0) { + console.error("'configuration.colors.description' must be defined and can not be empty"); + continue; + } + const defaults = contribution.defaults; + if (!defaults || typeof defaults !== 'object' || typeof defaults.light !== 'string' || typeof defaults.dark !== 'string' || typeof defaults.highContrast !== 'string') { + console.error("'configuration.colors.defaults' must be defined and must contain 'light', 'dark' and 'highContrast'"); + continue; + } + result.push({ + id: contribution.id, + description: contribution.description, + defaults: { + light: defaults.light, + dark: defaults.dark, + hc: defaults.highContrast + } + }); + } + return result; + } + protected readThemes(pck: PluginPackage): ThemeContribution[] | undefined { if (!pck.contributes || !pck.contributes.themes) { 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 5d5be3c99a948..b882d9b12a48e 100644 --- a/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts +++ b/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts @@ -32,6 +32,7 @@ import { TaskDefinitionRegistry, ProblemMatcherRegistry, ProblemPatternRegistry 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'; @injectable() export class PluginContributionHandler { @@ -83,6 +84,9 @@ export class PluginContributionHandler { @inject(MonacoThemingService) protected readonly monacoThemingService: MonacoThemingService; + @inject(ColorRegistry) + protected readonly colors: ColorRegistry; + protected readonly commandHandlers = new Map(); protected readonly onDidRegisterCommandHandlerEmitter = new Emitter(); @@ -241,6 +245,10 @@ export class PluginContributionHandler { } } + if (contributions.colors) { + pushContribution('colors', () => this.colors.register(...contributions.colors)); + } + if (contributions.taskDefinitions) { for (const taskDefinition of contributions.taskDefinitions) { pushContribution(`taskDefinitions.${taskDefinition.taskType}`, diff --git a/packages/plugin-ext/src/main/browser/scm-main.ts b/packages/plugin-ext/src/main/browser/scm-main.ts index 3a65e2ed9cc8d..50fa67f16e8df 100644 --- a/packages/plugin-ext/src/main/browser/scm-main.ts +++ b/packages/plugin-ext/src/main/browser/scm-main.ts @@ -32,13 +32,14 @@ import { CancellationToken } from '@theia/core/lib/common/cancellation'; import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable'; import URI from '@theia/core/lib/common/uri'; import { LabelProvider } from '@theia/core/lib/browser'; -import { ScmNavigatorDecorator } from '@theia/scm/lib/browser/decorations/scm-navigator-decorator'; +import { ColorRegistry } from '@theia/core/lib/browser/color-registry'; export class ScmMainImpl implements ScmMain, Disposable { private readonly proxy: ScmExt; private readonly scmService: ScmService; private readonly scmRepositoryMap = new Map(); private readonly labelProvider: LabelProvider; + private readonly colors: ColorRegistry; private lastSelectedSourceControlHandle: number | undefined; private readonly toDispose = new DisposableCollection(); @@ -47,6 +48,7 @@ export class ScmMainImpl implements ScmMain, Disposable { this.proxy = rpc.getProxy(MAIN_RPC_CONTEXT.SCM_EXT); this.scmService = container.get(ScmService); this.labelProvider = container.get(LabelProvider); + this.colors = container.get(ColorRegistry); this.toDispose.push(this.scmService.onDidChangeSelectedRepository(repository => this.updateSelectedRepository(repository))); } @@ -73,7 +75,7 @@ export class ScmMainImpl implements ScmMain, Disposable { } async $registerSourceControl(sourceControlHandle: number, id: string, label: string, rootUri: string): Promise { - const provider = new PluginScmProvider(this.proxy, sourceControlHandle, id, label, rootUri, this.labelProvider); + const provider = new PluginScmProvider(this.proxy, sourceControlHandle, id, label, rootUri, this.labelProvider, this.colors); const repository = this.scmService.registerScmProvider(provider); repository.input.onDidChange(() => this.proxy.$updateInputBox(sourceControlHandle, repository.input.value) @@ -169,7 +171,8 @@ export class PluginScmProvider implements ScmProvider { readonly id: string, readonly label: string, readonly rootUri: string, - protected readonly labelProvider: LabelProvider + protected readonly labelProvider: LabelProvider, + protected readonly colors: ColorRegistry ) { this.disposableCollection.push(this.onDidChangeEmitter); this.disposableCollection.push(this.onDidChangeCommitTemplateEmitter); @@ -308,12 +311,13 @@ export class PluginScmProvider implements ScmProvider { let scmDecorations; const decorations = resource.decorations; if (decorations) { + const colorVariable = resource.colorId && this.colors.toCssVariableName(resource.colorId); const icon = decorations.iconPath ? decorations.iconPath : await this.labelProvider.getIcon(new URI(resource.resourceUri)); scmDecorations = { icon, tooltip: decorations.tooltip, letter: resource.letter, - color: ScmNavigatorDecorator.getDecorationColor(resource.colorId) + color: colorVariable && `var(${colorVariable})` }; } return new PluginScmResource( diff --git a/packages/plugin-ext/src/main/browser/webview/webview-theme-data-provider.ts b/packages/plugin-ext/src/main/browser/webview/webview-theme-data-provider.ts index 081cad8ec4066..e544767c925dc 100644 --- a/packages/plugin-ext/src/main/browser/webview/webview-theme-data-provider.ts +++ b/packages/plugin-ext/src/main/browser/webview/webview-theme-data-provider.ts @@ -42,7 +42,7 @@ export class WebviewThemeDataProvider { protected readonly editorPreferences: EditorPreferences; @inject(ColorRegistry) - protected readonly colorRegistry: ColorRegistry; + protected readonly colors: ColorRegistry; @inject(ColorApplicationContribution) protected readonly colorContribution: ColorApplicationContribution; @@ -86,8 +86,8 @@ export class WebviewThemeDataProvider { const addStyle = (id: string, rawValue: any) => { if (rawValue) { const value = typeof rawValue === 'number' || typeof rawValue === 'string' ? rawValue : String(rawValue); - styles['vscode-' + id.replace('.', '-')] = value; - styles['theia-' + id.replace('.', '-')] = value; + styles[this.colors.toCssVariableName(id).substr(2)] = value; + styles[this.colors.toCssVariableName(id, 'vscode').substr(2)] = value; } }; @@ -96,8 +96,8 @@ export class WebviewThemeDataProvider { addStyle('font-size', '13px'); this.editorStyles.forEach((value, key) => addStyle(value, this.editorPreferences[key])); - for (const id of this.colorRegistry.getColors()) { - const color = this.colorRegistry.getCurrentColor(id); + for (const id of this.colors.getColors()) { + const color = this.colors.getCurrentColor(id); if (color) { addStyle(id, color.toString()); } diff --git a/packages/scm/src/browser/decorations/scm-navigator-decorator.ts b/packages/scm/src/browser/decorations/scm-navigator-decorator.ts index 7828f9d64fe91..b187f32fab294 100644 --- a/packages/scm/src/browser/decorations/scm-navigator-decorator.ts +++ b/packages/scm/src/browser/decorations/scm-navigator-decorator.ts @@ -23,6 +23,7 @@ import { DepthFirstTreeIterator } from '@theia/core/lib/browser'; import { FileStatNode } from '@theia/filesystem/lib/browser'; import { DecorationData, ScmDecorationsService } from './scm-decorations-service'; import URI from '@theia/core/lib/common/uri'; +import { ColorRegistry } from '@theia/core/lib/browser/color-registry'; @injectable() export class ScmNavigatorDecorator implements TreeDecorator { @@ -32,6 +33,9 @@ export class ScmNavigatorDecorator implements TreeDecorator { @inject(ILogger) protected readonly logger: ILogger; + @inject(ColorRegistry) + protected readonly colors: ColorRegistry; + constructor(@inject(ScmDecorationsService) protected readonly decorationsService: ScmDecorationsService) { this.decorationsService.onNavigatorDecorationsChanged(data => { this.decorationsMap = data; @@ -58,12 +62,13 @@ export class ScmNavigatorDecorator implements TreeDecorator { } protected toDecorator(change: DecorationData): TreeDecoration.Data { + const colorVariable = change.color && this.colors.toCssVariableName(change.color.id); return { tailDecorations: [ { data: change.letter ? change.letter : '', fontData: { - color: change.color ? ScmNavigatorDecorator.getDecorationColor(change.color.id) : '', + color: colorVariable && `var(${colorVariable})` }, tooltip: change.title ? change.title : '' } @@ -109,14 +114,4 @@ export class ScmNavigatorDecorator implements TreeDecorator { this.emitter.fire(event); } - static getDecorationColor(colorId: string | undefined): string | undefined { - switch (colorId) { - case 'gitDecoration.addedResourceForeground': return 'var(--theia-success-color0)'; - case 'gitDecoration.ignoredResourceForeground': // Fall through. - case 'gitDecoration.untrackedResourceForeground': // Fall through. - case 'gitDecoration.modifiedResourceForeground': return 'var(--theia-brand-color0)'; - case 'gitDecoration.deletedResourceForeground': return 'var(--theia-warn-color0)'; - case 'gitDecoration.conflictingResourceForeground': return 'var(--theia-error-color0)'; - } - } } From 396c02f30c9141200dce6041b8633c5cf7a37951 Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Fri, 1 Nov 2019 12:52:34 +0000 Subject: [PATCH 04/65] [monaco] load themes from tmTheme files Signed-off-by: Anton Kosyakov --- packages/monaco/package.json | 1 + .../src/browser/monaco-theming-service.ts | 52 +++++++++++++------ .../browser/textmate/monaco-theme-registry.ts | 3 +- .../browser/plugin-contribution-handler.ts | 4 +- 4 files changed, 41 insertions(+), 19 deletions(-) diff --git a/packages/monaco/package.json b/packages/monaco/package.json index 3978bb751514c..04a2739190b0d 100644 --- a/packages/monaco/package.json +++ b/packages/monaco/package.json @@ -11,6 +11,7 @@ "@theia/outline-view": "^0.14.0", "@theia/workspace": "^0.14.0", "deepmerge": "2.0.1", + "fast-plist": "^0.1.2", "jsonc-parser": "^2.0.2", "monaco-css": "^2.5.0", "monaco-html": "^2.5.2", diff --git a/packages/monaco/src/browser/monaco-theming-service.ts b/packages/monaco/src/browser/monaco-theming-service.ts index e22d48f5b66ca..117c63c86fb54 100644 --- a/packages/monaco/src/browser/monaco-theming-service.ts +++ b/packages/monaco/src/browser/monaco-theming-service.ts @@ -18,6 +18,7 @@ import { injectable, inject } from 'inversify'; import * as jsoncparser from 'jsonc-parser'; +import * as plistparser from 'fast-plist'; import { ThemeService, BuiltinThemeProvider } from '@theia/core/lib/browser/theming'; import URI from '@theia/core/lib/common/uri'; import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable'; @@ -41,23 +42,19 @@ export class MonacoThemingService { protected readonly fileSystem: FileSystem; // tslint:disable-next-line:no-any - register(theme: MonacoTheme, pendingIncludes: { [uri: string]: Promise } = {}): Disposable { + register(theme: MonacoTheme, pending: { [uri: string]: Promise } = {}): Disposable { const toDispose = new DisposableCollection(Disposable.create(() => { /* mark as not disposed */ })); - this.doRegister(theme, pendingIncludes, toDispose); + this.doRegister(theme, pending, toDispose); return toDispose; } protected async doRegister(theme: MonacoTheme, - pendingIncludes: { [uri: string]: Promise }, + pending: { [uri: string]: Promise }, toDispose: DisposableCollection ): Promise { try { - if (new URI(theme.uri).path.ext !== '.json') { - console.error('Unknown theme file: ' + theme.uri); - return; - } const includes = {}; - const json = await this.loadTheme(theme.uri, includes, pendingIncludes, toDispose); + const json = await this.loadTheme(theme.uri, includes, pending, toDispose); if (toDispose.disposed) { return; } @@ -75,21 +72,32 @@ export class MonacoThemingService { protected async loadTheme( uri: string, includes: { [include: string]: any }, - pendingIncludes: { [uri: string]: Promise }, + pending: { [uri: string]: Promise }, toDispose: DisposableCollection ): Promise { // tslint:enabled:no-any const { content } = await this.fileSystem.resolveContent(uri); if (toDispose.disposed) { - return undefined; + return; + } + const themeUri = new URI(uri); + if (themeUri.path.ext !== '.json') { + const value = plistparser.parse(content); + if (value && 'settings' in value && Array.isArray(value.settings)) { + return { tokenColors: value.settings }; + } + throw new Error(`Problem parsing tmTheme file: ${uri}. 'settings' is not array.`); } const json = jsoncparser.parse(content, undefined, { disallowComments: false }); - if (json.include) { - const includeUri = new URI(uri).parent.resolve(json.include).toString(); - if (!pendingIncludes[includeUri]) { - pendingIncludes[includeUri] = this.loadTheme(includeUri, includes, pendingIncludes, toDispose); + if ('tokenColors' in json && typeof json.tokenColors === 'string') { + const value = await this.doLoadTheme(themeUri, json.tokenColors, includes, pending, toDispose); + if (toDispose.disposed) { + return; } - includes[json.include] = await pendingIncludes[includeUri]; + json.tokenColors = value.tokenColors; + } + if (json.include) { + includes[json.include] = await this.doLoadTheme(themeUri, json.include, includes, pending, toDispose); if (toDispose.disposed) { return; } @@ -97,6 +105,20 @@ export class MonacoThemingService { return json; } + protected doLoadTheme( + themeUri: URI, + referencedPath: string, + includes: { [include: string]: any }, + pending: { [uri: string]: Promise }, + toDispose: DisposableCollection + ): Promise { + const referencedUri = themeUri.parent.resolve(referencedPath).toString(); + if (!pending[referencedUri]) { + pending[referencedUri] = this.loadTheme(referencedUri, includes, pending, toDispose); + } + return pending[referencedUri]; + } + static init(): void { ThemeService.get().onThemeChange(e => MonacoThemingService.store(MonacoThemingService.monacoThemes.get(e.newTheme.id)) diff --git a/packages/monaco/src/browser/textmate/monaco-theme-registry.ts b/packages/monaco/src/browser/textmate/monaco-theme-registry.ts index ce1eb159bfe62..87bc1518b1da6 100644 --- a/packages/monaco/src/browser/textmate/monaco-theme-registry.ts +++ b/packages/monaco/src/browser/textmate/monaco-theme-registry.ts @@ -91,8 +91,7 @@ export class MonacoThemeRegistry { if (typeof tokenColor.scope === 'undefined') { tokenColor.scope = ['']; } else if (typeof tokenColor.scope === 'string') { - // tokenColor.scope = tokenColor.scope.split(',').map((scope: string) => scope.trim()); // ? - tokenColor.scope = [tokenColor.scope]; + tokenColor.scope = tokenColor.scope.split(',').map((scope: string) => scope.trim()); } for (const scope of tokenColor.scope) { 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 b882d9b12a48e..c43e8b8cf9c01 100644 --- a/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts +++ b/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts @@ -239,9 +239,9 @@ export class PluginContributionHandler { } if (contributions.themes && contributions.themes.length) { - const includes = {}; + const pending = {}; for (const theme of contributions.themes) { - pushContribution(`themes.${theme.uri}`, () => this.monacoThemingService.register(theme, includes)); + pushContribution(`themes.${theme.uri}`, () => this.monacoThemingService.register(theme, pending)); } } From 04896a99f32ce10593ecc8724036422086cd28d9 Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Mon, 25 Nov 2019 16:25:34 +0000 Subject: [PATCH 05/65] [vscode] icon theming Signed-off-by: Anton Kosyakov --- ...ple-dynamic-label-provider-contribution.ts | 6 +- .../browser/common-frontend-contribution.ts | 56 +- packages/core/src/browser/diff-uris.ts | 11 +- .../browser/frontend-application-module.ts | 18 +- .../src/browser/icon-theme-contribution.ts | 64 ++ .../core/src/browser/icon-theme-service.ts | 180 ++++++ .../core/src/browser/label-provider.spec.ts | 6 +- packages/core/src/browser/label-provider.ts | 169 +++--- packages/core/src/browser/shell/tab-bars.ts | 14 +- packages/core/src/browser/style/icons.css | 16 +- packages/core/src/browser/style/menus.css | 2 +- .../src/browser/style/quick-title-bar.css | 4 +- packages/core/src/browser/style/tabs.css | 15 +- .../src/browser/style/tree-decorators.css | 2 +- packages/core/src/browser/style/tree.css | 7 +- .../style/variables-bright.useable.css | 3 +- .../browser/style/variables-dark.useable.css | 3 +- .../core/src/browser/style/view-container.css | 14 +- .../browser/tree/test/tree-test-container.ts | 5 +- .../src/browser/tree/tree-iterator.spec.ts | 30 +- .../src/browser/tree/tree-label-provider.ts | 40 ++ packages/core/src/browser/tree/tree-search.ts | 8 +- .../browser/tree/tree-selection-state.spec.ts | 30 +- .../core/src/browser/tree/tree-widget.tsx | 53 +- packages/core/src/browser/tree/tree.ts | 12 +- packages/debug/src/browser/style/index.css | 4 +- packages/editor/src/browser/editor-command.ts | 9 +- .../src/browser/editor-quick-open-service.ts | 23 +- .../src/browser/editor-widget-factory.ts | 10 +- .../src/browser/quick-file-open.ts | 21 +- .../file-dialog/file-dialog-service.ts | 4 +- .../src/browser/file-dialog/file-dialog.ts | 11 +- .../file-tree/file-tree-label-provider.ts | 53 ++ .../src/browser/file-tree/file-tree-model.ts | 9 +- .../browser/file-tree/file-tree-widget.tsx | 41 +- .../src/browser/file-tree/file-tree.ts | 63 +- .../src/browser/filesystem-frontend-module.ts | 6 +- .../src/browser/style/file-icons.css | 13 +- .../git/src/browser/diff/git-diff-widget.tsx | 55 +- .../browser/git-file-change-label-provider.ts | 75 +++ .../git/src/browser/git-file-change-node.ts | 7 +- .../git/src/browser/git-frontend-module.ts | 4 + .../src/browser/git-navigable-list-widget.tsx | 67 +- .../git/src/browser/git-repository-tracker.ts | 7 +- packages/git/src/browser/git-scm-provider.ts | 32 +- .../src/browser/git-uri-label-contribution.ts | 14 +- .../browser/history/git-history-widget.tsx | 78 +-- packages/git/src/browser/style/index.css | 10 +- .../java/src/browser/java-label-provider.ts | 3 +- packages/keymaps/src/browser/style/index.css | 2 +- .../src/browser/marker-tree-label-provider.ts | 53 ++ packages/markers/src/browser/marker-tree.ts | 38 +- .../problem/problem-frontend-module.ts | 6 +- .../src/browser/problem/problem-tree-model.ts | 6 +- .../src/browser/problem/problem-widget.tsx | 9 +- .../src/browser/mini-browser-open-handler.ts | 2 +- .../mini-browser/src/browser/style/index.css | 2 +- .../monaco/src/browser/style/symbol-icons.css | 6 +- .../navigator/src/browser/navigator-tree.ts | 5 +- .../src/browser/navigator-widget.tsx | 8 +- .../browser/hosted-plugin-manager-client.ts | 4 +- .../plugin-ext/src/common/plugin-api-rpc.ts | 2 +- .../plugin-ext/src/common/plugin-protocol.ts | 26 +- .../src/hosted/node/scanners/scanner-theia.ts | 34 +- .../src/main/browser/dialogs-main.ts | 14 +- .../browser/plugin-contribution-handler.ts | 10 + .../browser/plugin-ext-frontend-module.ts | 18 +- .../main/browser/plugin-icon-theme-service.ts | 571 ++++++++++++++++++ .../src/main/browser/quick-open-main.ts | 10 +- .../plugin-ext/src/main/browser/scm-main.ts | 8 +- .../src/main/browser/style/index.css | 35 ++ .../plugin-tree-view-node-label-provider.ts | 78 +++ .../main/browser/view/tree-view-widget.tsx | 56 +- .../plugin-ext/src/plugin/tree/tree-views.ts | 18 +- .../src/browser/markdown/style/markdown.css | 2 +- .../src/browser/style/preview-widget.css | 2 +- packages/scm/src/browser/scm-provider.ts | 1 - packages/scm/src/browser/scm-widget.tsx | 11 +- packages/scm/src/browser/style/index.css | 10 +- .../search-in-workspace-frontend-module.ts | 6 +- .../search-in-workspace-label-provider.ts | 48 ++ ...search-in-workspace-result-tree-widget.tsx | 69 +-- .../src/browser/styles/index.css | 8 +- .../src/browser/quick-open-workspace.ts | 4 +- .../workspace-uri-contribution.spec.ts | 59 +- .../src/browser/workspace-uri-contribution.ts | 35 +- 86 files changed, 1961 insertions(+), 702 deletions(-) create mode 100644 packages/core/src/browser/icon-theme-contribution.ts create mode 100644 packages/core/src/browser/icon-theme-service.ts create mode 100644 packages/core/src/browser/tree/tree-label-provider.ts create mode 100644 packages/filesystem/src/browser/file-tree/file-tree-label-provider.ts create mode 100644 packages/git/src/browser/git-file-change-label-provider.ts create mode 100644 packages/markers/src/browser/marker-tree-label-provider.ts create mode 100644 packages/plugin-ext/src/main/browser/plugin-icon-theme-service.ts create mode 100644 packages/plugin-ext/src/main/browser/view/plugin-tree-view-node-label-provider.ts create mode 100644 packages/search-in-workspace/src/browser/search-in-workspace-label-provider.ts diff --git a/examples/api-samples/src/browser/sample-dynamic-label-provider-contribution.ts b/examples/api-samples/src/browser/sample-dynamic-label-provider-contribution.ts index ae7087af40f28..b82d92e096f51 100644 --- a/examples/api-samples/src/browser/sample-dynamic-label-provider-contribution.ts +++ b/examples/api-samples/src/browser/sample-dynamic-label-provider-contribution.ts @@ -14,7 +14,7 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ -import { DefaultUriLabelProviderContribution, DidChangeLabelEvent, FILE_ICON } from '@theia/core/lib/browser/label-provider'; +import { DefaultUriLabelProviderContribution, DidChangeLabelEvent } from '@theia/core/lib/browser/label-provider'; import URI from '@theia/core/lib/common/uri'; import { injectable } from 'inversify'; import { Emitter, Event } from '@theia/core'; @@ -58,11 +58,11 @@ export class SampleDynamicLabelProviderContribution extends DefaultUriLabelProvi return new URI(element.toString()); } - async getIcon(element: URI): Promise { + getIcon(element: URI): string { const uri = this.getUri(element); const icon = super.getFileIcon(uri); if (!icon) { - return FILE_ICON; + return this.defaultFileIcon; } return icon; } diff --git a/packages/core/src/browser/common-frontend-contribution.ts b/packages/core/src/browser/common-frontend-contribution.ts index f9780737fa620..77346bf28edbe 100644 --- a/packages/core/src/browser/common-frontend-contribution.ts +++ b/packages/core/src/browser/common-frontend-contribution.ts @@ -36,8 +36,9 @@ import { UriSelection } from '../common/selection'; import { StorageService } from './storage-service'; import { Navigatable } from './navigatable'; import { QuickViewService } from './quick-view-service'; -import { PrefixQuickOpenService } from './quick-open'; +import { PrefixQuickOpenService, QuickOpenItem, QuickOpenMode, QuickOpenService } from './quick-open'; import { environment } from '@theia/application-package/lib/environment'; +import { IconThemeService } from './icon-theme-service'; export namespace CommonMenus { @@ -198,6 +199,12 @@ export namespace CommonCommands { label: 'Open Preferences', }; + export const SELECT_ICON_THEME: Command = { + id: 'workbench.action.selectIconTheme', + label: 'File Icon Theme', + category: 'Preferences' + }; + } export const supportCut = browser.isNative || document.queryCommandSupported('cut'); @@ -238,6 +245,12 @@ export class CommonFrontendContribution implements FrontendApplicationContributi @inject(PrefixQuickOpenService) protected readonly quickOpen: PrefixQuickOpenService; + @inject(IconThemeService) + protected readonly iconThemes: IconThemeService; + + @inject(QuickOpenService) + protected readonly quickOpenService: QuickOpenService; + @postConstruct() protected init(): void { this.contextKeyService.createKey('isLinux', OS.type() === OS.Type.Linux); @@ -508,6 +521,10 @@ export class CommonFrontendContribution implements FrontendApplicationContributi commandRegistry.registerCommand(CommonCommands.OPEN_VIEW, { execute: () => this.quickOpen.open(this.quickView.prefix) }); + + commandRegistry.registerCommand(CommonCommands.SELECT_ICON_THEME, { + execute: () => this.selectIconTheme() + }); } private findTabBar(event?: Event): TabBar | undefined { @@ -679,4 +696,41 @@ export class CommonFrontendContribution implements FrontendApplicationContributi this.shouldPreventClose = false; } } + + protected selectIconTheme(): void { + let resetTo: string | undefined = this.iconThemes.current; + let items: (QuickOpenItem & { id: string })[] = []; + for (const iconTheme of this.iconThemes.definitions) { + const item = Object.assign(new QuickOpenItem({ + label: iconTheme.label, + description: iconTheme.description, + run: (mode: QuickOpenMode) => { + if (mode === QuickOpenMode.OPEN) { + resetTo = undefined; + } + this.iconThemes.current = iconTheme.id; + return true; + } + }), { id: iconTheme.id }); + items.push(item); + } + items = items.sort((a, b) => { + if (a.id === 'none') { + return -1; + } + return a.getLabel()!.localeCompare(b.getLabel()!); + }); + this.quickOpenService.open({ + onType: (_, accept) => accept(items) + }, { + placeholder: 'Select File Icon Theme', + fuzzyMatchLabel: true, + selectIndex: () => items.findIndex(item => item.id === this.iconThemes.current), + onClose: () => { + if (resetTo) { + this.iconThemes.current = resetTo; + } + } + }); + } } diff --git a/packages/core/src/browser/diff-uris.ts b/packages/core/src/browser/diff-uris.ts index 6a0aa808c2b12..2dfd621a3c81a 100644 --- a/packages/core/src/browser/diff-uris.ts +++ b/packages/core/src/browser/diff-uris.ts @@ -16,7 +16,7 @@ import { injectable, inject } from 'inversify'; import URI from '../common/uri'; -import { LabelProviderContribution, LabelProvider } from './label-provider'; +import { LabelProviderContribution, LabelProvider, DidChangeLabelEvent } from './label-provider'; export namespace DiffUris { @@ -103,8 +103,13 @@ export class DiffUriLabelProviderContribution implements LabelProviderContributi return 'fa fa-columns'; } - getConstituentUris(uri: URI): URI[] { - return DiffUris.decode(uri); + affects(diffUri: URI, event: DidChangeLabelEvent): boolean { + for (const uri of DiffUris.decode(diffUri)) { + if (event.affects(uri)) { + return true; + } + } + return false; } } diff --git a/packages/core/src/browser/frontend-application-module.ts b/packages/core/src/browser/frontend-application-module.ts index 4372221050224..5aa90abd3d998 100644 --- a/packages/core/src/browser/frontend-application-module.ts +++ b/packages/core/src/browser/frontend-application-module.ts @@ -86,6 +86,9 @@ import { bindResourceProvider, bindMessageService, bindPreferenceService } from import { ColorRegistry } from './color-registry'; import { ColorContribution, ColorApplicationContribution } from './color-application-contribution'; import { ExternalUriService } from './external-uri-service'; +import { IconThemeService, NoneIconTheme } from './icon-theme-service'; +import { IconThemeApplicationContribution, IconThemeContribution, DefaultFileIconThemeContribution } from './icon-theme-contribution'; +import { TreeLabelProvider } from './tree/tree-label-provider'; export { bindResourceProvider, bindMessageService, bindPreferenceService }; @@ -94,6 +97,15 @@ export const frontendApplicationModule = new ContainerModule((bind, unbind, isBo themeService.register(...BuiltinThemeProvider.themes); themeService.startupTheme(); + bind(NoneIconTheme).toSelf().inSingletonScope(); + bind(LabelProviderContribution).toService(NoneIconTheme); + bind(IconThemeService).toSelf().inSingletonScope(); + bindContributionProvider(bind, IconThemeContribution); + bind(DefaultFileIconThemeContribution).toSelf().inSingletonScope(); + bind(IconThemeContribution).toService(DefaultFileIconThemeContribution); + bind(IconThemeApplicationContribution).toSelf().inSingletonScope(); + bind(FrontendApplicationContribution).toService(IconThemeApplicationContribution); + bind(ColorRegistry).toSelf().inSingletonScope(); bindContributionProvider(bind, ColorContribution); bind(ColorApplicationContribution).toSelf().inSingletonScope(); @@ -130,7 +142,8 @@ export const frontendApplicationModule = new ContainerModule((bind, unbind, isBo bind(TabBarRendererFactory).toFactory(context => () => { const contextMenuRenderer = context.container.get(ContextMenuRenderer); const decoratorService = context.container.get(TabBarDecoratorService); - return new TabBarRenderer(contextMenuRenderer, decoratorService); + const iconThemeService = context.container.get(IconThemeService); + return new TabBarRenderer(contextMenuRenderer, decoratorService, iconThemeService); }); bindContributionProvider(bind, TabBarDecorator); @@ -230,6 +243,9 @@ export const frontendApplicationModule = new ContainerModule((bind, unbind, isBo bind(LabelProviderContribution).to(DefaultUriLabelProviderContribution).inSingletonScope(); bind(LabelProviderContribution).to(DiffUriLabelProviderContribution).inSingletonScope(); + bind(TreeLabelProvider).toSelf().inSingletonScope(); + bind(LabelProviderContribution).toService(TreeLabelProvider); + bindPreferenceService(bind); bind(FrontendApplicationContribution).toService(PreferenceService); diff --git a/packages/core/src/browser/icon-theme-contribution.ts b/packages/core/src/browser/icon-theme-contribution.ts new file mode 100644 index 0000000000000..6c9cd13653819 --- /dev/null +++ b/packages/core/src/browser/icon-theme-contribution.ts @@ -0,0 +1,64 @@ +/******************************************************************************** + * Copyright (C) 2019 TypeFox 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, inject, named } from 'inversify'; +import { FrontendApplicationContribution } from './frontend-application'; +import { ContributionProvider } from '../common/contribution-provider'; +import { IconThemeService, IconTheme } from './icon-theme-service'; +import { MaybePromise } from '../common/types'; +import { Disposable } from '../common/disposable'; + +export const IconThemeContribution = Symbol('IconThemeContribution'); +export interface IconThemeContribution { + registerIconThemes(iconThemes: IconThemeService): MaybePromise; +} + +@injectable() +export class IconThemeApplicationContribution implements FrontendApplicationContribution { + + @inject(IconThemeService) + protected readonly iconThemes: IconThemeService; + + @inject(ContributionProvider) @named(IconThemeContribution) + protected readonly iconThemeContributions: ContributionProvider; + + async onStart(): Promise { + for (const contribution of this.iconThemeContributions.getContributions()) { + await contribution.registerIconThemes(this.iconThemes); + } + } + +} + +@injectable() +export class DefaultFileIconThemeContribution implements IconTheme, IconThemeContribution { + + readonly id = 'theia-file-icons'; + readonly label = 'File Icons (Theia)'; + readonly hasFileIcons = true; + readonly hasFolderIcons = true; + + registerIconThemes(iconThemes: IconThemeService): MaybePromise { + iconThemes.register(this); + iconThemes.default = this.id; + } + + /* rely on behaviour before for backward-compatibility */ + activate(): Disposable { + return Disposable.NULL; + } + +} diff --git a/packages/core/src/browser/icon-theme-service.ts b/packages/core/src/browser/icon-theme-service.ts new file mode 100644 index 0000000000000..fb82f1787f273 --- /dev/null +++ b/packages/core/src/browser/icon-theme-service.ts @@ -0,0 +1,180 @@ +/******************************************************************************** + * Copyright (C) 2019 TypeFox 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, inject, postConstruct } from 'inversify'; +import { Emitter } from '../common/event'; +import { Disposable, DisposableCollection } from '../common/disposable'; +import { LabelProviderContribution, DidChangeLabelEvent } from './label-provider'; + +export interface IconThemeDefinition { + readonly id: string + readonly label: string + readonly description?: string + readonly hasFileIcons?: boolean; + readonly hasFolderIcons?: boolean; + readonly hidesExplorerArrows?: boolean; +} + +export interface IconTheme extends IconThemeDefinition { + activate(): Disposable; +} + +@injectable() +export class NoneIconTheme implements IconTheme, LabelProviderContribution { + + readonly id = 'none'; + readonly label = 'None'; + readonly description = 'Disable file icons'; + readonly hasFileIcons = true; + readonly hasFolderIcons = true; + + protected readonly onDidChangeEmitter = new Emitter(); + readonly onDidChange = this.onDidChangeEmitter.event; + + protected readonly toDeactivate = new DisposableCollection(); + + activate(): Disposable { + if (this.toDeactivate.disposed) { + this.toDeactivate.push(Disposable.create(() => this.fireDidChange())); + this.fireDidChange(); + } + return this.toDeactivate; + } + + protected fireDidChange(): void { + this.onDidChangeEmitter.fire({ affects: () => true }); + } + + canHandle(): number { + if (this.toDeactivate.disposed) { + return 0; + } + return Number.MAX_SAFE_INTEGER; + } + + getIcon(): string { + return ''; + } + +} + +@injectable() +export class IconThemeService { + + protected readonly onDidChangeEmitter = new Emitter(); + readonly onDidChange = this.onDidChangeEmitter.event; + + protected readonly _iconThemes = new Map(); + get ids(): IterableIterator { + return this._iconThemes.keys(); + } + get definitions(): IterableIterator { + return this._iconThemes.values(); + } + getDefinition(id: string): IconThemeDefinition | undefined { + return this._iconThemes.get(id); + } + + @inject(NoneIconTheme) + protected readonly noneIconTheme: NoneIconTheme; + + protected readonly onDidChangeCurrentEmitter = new Emitter(); + readonly onDidChangeCurrent = this.onDidChangeCurrentEmitter.event; + + protected _default: IconTheme; + + protected readonly toDeactivate = new DisposableCollection(); + + @postConstruct() + protected init(): void { + this._default = this.noneIconTheme; + this.register(this.noneIconTheme); + } + + register(iconTheme: IconTheme): Disposable { + if (this._iconThemes.has(iconTheme.id)) { + console.warn(new Error(`Icon theme '${iconTheme.id}' has already been registered, skipping.`)); + return Disposable.NULL; + } + this._iconThemes.set(iconTheme.id, iconTheme); + this.onDidChangeEmitter.fire(undefined); + if (this.toDeactivate.disposed + && window.localStorage.getItem('iconTheme') === iconTheme.id) { + this.setCurrent(iconTheme); + } + return Disposable.create(() => this.unregister(iconTheme.id)); + } + + unregister(id: string): IconTheme | undefined { + const iconTheme = this._iconThemes.get(id); + if (!iconTheme) { + return undefined; + } + this._iconThemes.delete(id); + if (this._default === iconTheme) { + this._default = this.noneIconTheme; + } + if (window.localStorage.getItem('iconTheme') === id) { + window.localStorage.removeItem('iconTheme'); + this.onDidChangeCurrentEmitter.fire(this._default.id); + } + this.onDidChangeEmitter.fire(undefined); + return iconTheme; + } + + get current(): string { + return this.getCurrent().id; + } + + set current(id: string) { + const newCurrent = this._iconThemes.get(id) || this._default; + if (this.getCurrent().id !== newCurrent.id) { + this.setCurrent(newCurrent); + } + } + + protected getCurrent(): IconTheme { + const id = window.localStorage.getItem('iconTheme'); + return id && this._iconThemes.get(id) || this._default; + } + + protected setCurrent(current: IconTheme): void { + window.localStorage.setItem('iconTheme', current.id); + this.toDeactivate.dispose(); + this.toDeactivate.push(current.activate()); + this.onDidChangeCurrentEmitter.fire(current.id); + } + + get default(): string { + return this._default.id; + } + + set default(id: string) { + const newDefault = this._iconThemes.get(id) || this.noneIconTheme; + if (this._default.id === newDefault.id) { + return; + } + this._default = newDefault; + if (!window.localStorage.getItem('iconTheme')) { + this.onDidChangeCurrentEmitter.fire(newDefault.id); + } + } + + protected load(): string | undefined { + return window.localStorage.getItem('iconTheme') || undefined; + } + +} diff --git a/packages/core/src/browser/label-provider.spec.ts b/packages/core/src/browser/label-provider.spec.ts index dc5dd6c37b64f..74f32e0496ff5 100644 --- a/packages/core/src/browser/label-provider.spec.ts +++ b/packages/core/src/browser/label-provider.spec.ts @@ -15,7 +15,7 @@ ********************************************************************************/ import { expect } from 'chai'; -import { DefaultUriLabelProviderContribution, FOLDER_ICON } from './label-provider'; +import { DefaultUriLabelProviderContribution } from './label-provider'; import URI from '../common/uri'; describe('DefaultUriLabelProviderContribution', function (): void { @@ -38,13 +38,13 @@ describe('DefaultUriLabelProviderContribution', function (): void { const prov = new DefaultUriLabelProviderContribution(); const icon = prov.getIcon(new URI('file:///tmp/hello/you.txt')); - expect(icon).eq('text-icon medium-blue'); + expect(icon).eq('text-icon medium-blue theia-file-icons-js'); }); it('should return icon class for something that seems to be a directory', function (): void { const prov = new DefaultUriLabelProviderContribution(); const icon = prov.getIcon(new URI('file:///tmp/hello')); - expect(icon).eq(FOLDER_ICON); + expect(icon).eq(prov.defaultFolderIcon); }); }); diff --git a/packages/core/src/browser/label-provider.ts b/packages/core/src/browser/label-provider.ts index 621fa286c0135..5fb3880b7ba8e 100644 --- a/packages/core/src/browser/label-provider.ts +++ b/packages/core/src/browser/label-provider.ts @@ -18,12 +18,31 @@ import { inject, injectable, named } from 'inversify'; import * as fileIcons from 'file-icons-js'; import URI from '../common/uri'; import { ContributionProvider } from '../common/contribution-provider'; -import { Prioritizeable, MaybePromise } from '../common/types'; +import { Prioritizeable } from '../common/types'; import { Event, Emitter } from '../common'; import { FrontendApplicationContribution } from './frontend-application'; -export const FOLDER_ICON = 'fa fa-folder'; -export const FILE_ICON = 'fa fa-file'; +/** + * @internal don't export it, use `LabelProvider.folderIcon` instead. + */ +const DEFAULT_FOLDER_ICON = 'fa fa-folder'; +/** + * @internal don't export it, use `LabelProvider.fileIcon` instead. + */ +const DEFAULT_FILE_ICON = 'fa fa-file'; + +/** + * Internal folder icon class for the default (File Icons) theme. + * + * @deprecated Use `LabelProvider.folderIcon` to get a folder icon class for the current icon theme. + */ +export const FOLDER_ICON = DEFAULT_FOLDER_ICON; +/** + * Internal file icon class for the default (File Icons) theme. + * + * @deprecated Use `LabelProvider.fileIcon` to get a file icon class for the current icon theme. + */ +export const FILE_ICON = DEFAULT_FILE_ICON; export const LabelProviderContribution = Symbol('LabelProviderContribution'); export interface LabelProviderContribution { @@ -38,17 +57,17 @@ export interface LabelProviderContribution { /** * returns an icon class for the given element. */ - getIcon?(element: object): MaybePromise; + getIcon?(element: object): string | undefined; /** * returns a short name for the given element. */ - getName?(element: object): string; + getName?(element: object): string | undefined; /** * returns a long name for the given element. */ - getLongName?(element: object): string; + getLongName?(element: object): string | undefined; /** * Emit when something has changed that may result in this label provider returning a different @@ -56,7 +75,13 @@ export interface LabelProviderContribution { */ readonly onDidChange?: Event; - readonly getConstituentUris?: (compositeElement: object) => URI[]; + /** + * Check whether the given element is affected by the given change event. + * Contributions delegating to the label provider can use this hook + * to perfrom a recursive check. + */ + affects?(element: object, event: DidChangeLabelEvent): boolean; + } export interface DidChangeLabelEvent { @@ -73,20 +98,32 @@ export class DefaultUriLabelProviderContribution implements LabelProviderContrib return 0; } - getIcon(uri: URI): MaybePromise { + getIcon(uri: URI): string { const iconClass = this.getFileIcon(uri); if (!iconClass) { if (uri.displayName.indexOf('.') === -1) { - return FOLDER_ICON; + return this.defaultFolderIcon; } else { - return FILE_ICON; + return this.defaultFileIcon; } } return iconClass; } + get defaultFolderIcon(): string { + return DEFAULT_FOLDER_ICON; + } + + get defaultFileIcon(): string { + return DEFAULT_FILE_ICON; + } + protected getFileIcon(uri: URI): string | undefined { - return fileIcons.getClassWithColor(uri.displayName); + const fileIcon = fileIcons.getClassWithColor(uri.displayName); + if (!fileIcon) { + return undefined; + } + return fileIcon + ' theia-file-icons-js'; } getName(uri: URI): string { @@ -114,52 +151,25 @@ export class LabelProvider implements FrontendApplicationContribution { */ initialize(): void { const contributions = this.contributionProvider.getContributions(); - for (const contribution of contributions) { - if (contribution.onDidChange) { - contribution.onDidChange(event => { - const affects = (uri: URI) => this.affects(uri, event, contribution); - this.onDidChangeEmitter.fire({ affects }); + for (const eventContribution of contributions) { + if (eventContribution.onDidChange) { + eventContribution.onDidChange(event => { + this.onDidChangeEmitter.fire({ + // TODO check eventContribution.canHandle as well + affects: element => this.affects(element, event) + }); }); } } } - /** - * When the given event occurs, determine if the given URI could in any - * way be affected. - * - * If the event directly indicates that it affects the URI then of course we - * return `true`. However there may be label provider contributions that delegate - * back to the label provider. These contributors do not, and should not, listen for - * label provider events because that would cause infinite recursion. - * - * @param uri - * @param event - */ - protected affects(element: object, event: DidChangeLabelEvent, originatingContribution: LabelProviderContribution): boolean { - - const contribs = this.findContribution(element); - const possibleContribsWithDups = [ - contribs.find(c => c.getIcon !== undefined), - contribs.find(c => c.getName !== undefined), - contribs.find(c => c.getLongName !== undefined), - ]; - const possibleContribsWithoutDups = [...new Set(possibleContribsWithDups)]; - for (const possibleContrib of possibleContribsWithoutDups) { - if (possibleContrib) { - if (possibleContrib === originatingContribution) { - if (event.affects(element)) { - return true; - } - } - if (possibleContrib.getConstituentUris) { - const constituentUris: URI[] = possibleContrib.getConstituentUris(element); - for (const constituentUri of constituentUris) { - if (this.affects(constituentUri, event, originatingContribution)) { - return true; - } - } - } + protected affects(element: object, event: DidChangeLabelEvent): boolean { + if (event.affects(element)) { + return true; + } + for (const contribution of this.findContribution(element)) { + if (contribution.affects && contribution.affects(element, event)) { + return true; } } return false; @@ -169,31 +179,54 @@ export class LabelProvider implements FrontendApplicationContribution { return this.onDidChangeEmitter.event; } - async getIcon(element: object): Promise { - const contribs = this.findContribution(element); - const contrib = contribs.find(c => c.getIcon !== undefined); - if (!contrib) { - return ''; + /** + * Return a default file icon for the current icon theme. + */ + get fileIcon(): string { + return this.getIcon(new URI('file:///foo/foo.txt')); + } + + /** + * Return a default folder icon for the current icon theme. + */ + get folderIcon(): string { + return this.getIcon(new URI('file:///foo')); + } + + getIcon(element: object): string { + const contributions = this.findContribution(element); + for (const contribution of contributions) { + const value = contribution.getIcon && contribution.getIcon(element); + if (value === undefined) { + continue; + } + return value; } - return contrib.getIcon!(element); + return ''; } getName(element: object): string { - const contribs = this.findContribution(element); - const contrib = contribs.find(c => c.getName !== undefined); - if (!contrib) { - return ''; + const contributions = this.findContribution(element); + for (const contribution of contributions) { + const value = contribution.getName && contribution.getName(element); + if (value === undefined) { + continue; + } + return value; } - return contrib.getName!(element); + return ''; } getLongName(element: object): string { - const contribs = this.findContribution(element); - const contrib = contribs.find(c => c.getLongName !== undefined); - if (!contrib) { - return ''; + const contributions = this.findContribution(element); + for (const contribution of contributions) { + const value = contribution.getLongName && contribution.getLongName(element); + if (value === undefined) { + continue; + } + return value; } - return contrib.getLongName!(element); + return ''; } protected findContribution(element: object): LabelProviderContribution[] { diff --git a/packages/core/src/browser/shell/tab-bars.ts b/packages/core/src/browser/shell/tab-bars.ts index b0962a267d207..5e870028ba7a8 100644 --- a/packages/core/src/browser/shell/tab-bars.ts +++ b/packages/core/src/browser/shell/tab-bars.ts @@ -27,6 +27,7 @@ import { TabBarToolbarRegistry, TabBarToolbar } from './tab-bar-toolbar'; import { TheiaDockPanel, MAIN_AREA_ID, BOTTOM_AREA_ID } from './theia-dock-panel'; import { WidgetDecoration } from '../widget-decoration'; import { TabBarDecoratorService } from './tab-bar-decorator'; +import { IconThemeService } from '../icon-theme-service'; /** The class name added to hidden content nodes, which are required to render vertical side bars. */ const HIDDEN_CONTENT_CLASS = 'theia-TabBar-hidden-content'; @@ -75,7 +76,8 @@ export class TabBarRenderer extends TabBar.Renderer { // right now it is mess: (1) client logic belong to renderer, (2) cyclic dependencies between renderes and clients constructor( protected readonly contextMenuRenderer?: ContextMenuRenderer, - protected readonly decoratorService?: TabBarDecoratorService + protected readonly decoratorService?: TabBarDecoratorService, + protected readonly iconThemeService?: IconThemeService ) { super(); if (this.decoratorService) { @@ -128,8 +130,11 @@ export class TabBarRenderer extends TabBar.Renderer { oncontextmenu: this.handleContextMenuEvent, ondblclick: this.handleDblClickEvent }, - this.renderIcon(data, isInSidePanel), - this.renderLabel(data, isInSidePanel), + h.div( + { className: 'theia-tab-icon-label' }, + this.renderIcon(data, isInSidePanel), + this.renderLabel(data, isInSidePanel) + ), this.renderCloseIcon(data) ); } @@ -348,6 +353,9 @@ export class TabBarRenderer extends TabBar.Renderer { * @param {boolean} isInSidePanel An optional check which determines if the tab is in the side-panel. */ renderIcon(data: SideBarRenderData, inSidePanel?: boolean): VirtualElement { + if (!inSidePanel && this.iconThemeService && this.iconThemeService.current === 'none') { + return h.div(); + } let top: string | undefined; if (data.paddingTop) { top = `${data.paddingTop || 0}px`; diff --git a/packages/core/src/browser/style/icons.css b/packages/core/src/browser/style/icons.css index c1d033277eea0..1df346c329c30 100644 --- a/packages/core/src/browser/style/icons.css +++ b/packages/core/src/browser/style/icons.css @@ -15,25 +15,25 @@ ********************************************************************************/ .theia-open-change-icon { - width: 16px; - height: 16px; + width: var(--theia-icon-size); + height: var(--theia-icon-size); background: var(--theia-icon-open-change) no-repeat; } .theia-open-file-icon { - width: 16px; - height: 16px; + width: var(--theia-icon-size); + height: var(--theia-icon-size); background: var(--theia-icon-open-file) no-repeat; } .theia-open-preview-icon { - width: 16px; - height: 16px; + width: var(--theia-icon-size); + height: var(--theia-icon-size); background: var(--theia-icon-preview) no-repeat; } .theia-open-json-icon { - width: 16px; - height: 16px; + width: var(--theia-icon-size); + height: var(--theia-icon-size); background: var(--theia-icon-open-json) no-repeat; } diff --git a/packages/core/src/browser/style/menus.css b/packages/core/src/browser/style/menus.css index d64d6820d16b0..0471c7f585e6e 100644 --- a/packages/core/src/browser/style/menus.css +++ b/packages/core/src/browser/style/menus.css @@ -150,7 +150,7 @@ .p-Menu-itemSubmenuIcon { - width: 16px; + width: var(--theia-icon-size); padding: 0px 4px 0px 0px; } diff --git a/packages/core/src/browser/style/quick-title-bar.css b/packages/core/src/browser/style/quick-title-bar.css index a90046adf3882..2bcd044d5fa14 100644 --- a/packages/core/src/browser/style/quick-title-bar.css +++ b/packages/core/src/browser/style/quick-title-bar.css @@ -37,8 +37,8 @@ } .theia-quick-title-button { - width: 16px; - height: 16px; + width: var(--theia-icon-size); + height: var(--theia-icon-size); display: flex; align-items: center; cursor: pointer; diff --git a/packages/core/src/browser/style/tabs.css b/packages/core/src/browser/style/tabs.css index 0d2eea1c7fd64..70fc66f1e2450 100644 --- a/packages/core/src/browser/style/tabs.css +++ b/packages/core/src/browser/style/tabs.css @@ -66,6 +66,12 @@ border-right: var(--theia-border-width) solid var(--theia-border-color0); } +.p-TabBar[data-orientation='horizontal'] .p-TabBar-tab .theia-tab-icon-label { + display: flex; + line-height: var(--theia-content-line-height); + align-items: center; +} + .p-TabBar[data-orientation='horizontal'] .p-TabBar-tab:hover:not(.p-mod-current) { background: var(--theia-accent-color3); } @@ -136,7 +142,6 @@ } .p-TabBar.theia-app-centers .p-TabBar-tabIcon { - height: 14px; background-size: 13px; background-position-y: 3px; background-color: var(--theia-tab-icon-color); @@ -144,26 +149,24 @@ -webkit-mask-size: 13px; mask-repeat: no-repeat; mask-size: 13px; - padding-right: 2px; + padding-right: calc(var(--theia-ui-padding)/2); } .p-TabBar[data-orientation='horizontal'] .file-icon.p-TabBar-tabIcon { background: none; padding-bottom: 0px; - padding-right: 0; min-height: 20px; } .p-TabBar[data-orientation='horizontal'] .fa.p-TabBar-tabIcon { background: none; - padding-bottom: 6px; min-height: 0; } .p-TabBar.theia-app-centers .p-TabBar-tab.p-mod-closable > .p-TabBar-tabCloseIcon { padding-left: 10px; - height: 16px; - width: 16px; + height: var(--theia-icon-size); + width: var(--theia-icon-size); background-size: 13px; background-position: center; background-repeat: no-repeat; diff --git a/packages/core/src/browser/style/tree-decorators.css b/packages/core/src/browser/style/tree-decorators.css index 7dff55b1161ec..3fde5064080a6 100644 --- a/packages/core/src/browser/style/tree-decorators.css +++ b/packages/core/src/browser/style/tree-decorators.css @@ -33,7 +33,7 @@ .theia-icon-wrapper { top: 0px !important; position: relative; - display: inline-block + display: inline-flex; } .theia-decorator-size { diff --git a/packages/core/src/browser/style/tree.css b/packages/core/src/browser/style/tree.css index bdd4842c18ccd..7dbe99cabfef3 100644 --- a/packages/core/src/browser/style/tree.css +++ b/packages/core/src/browser/style/tree.css @@ -42,7 +42,7 @@ } .theia-TreeNode { - line-height: 22px; + line-height: var(--theia-content-line-height); display: flex; } @@ -53,15 +53,16 @@ .theia-TreeNodeContent { display: flex; - align-items: baseline; + align-items: center; width: calc(100% - var(--theia-scrollbar-rail-width)); } .theia-ExpansionToggle { - padding-right: var(--theia-ui-padding); min-width: 10px; display: flex; justify-content: center; + padding-left: calc(var(--theia-ui-padding)*2/3); + padding-right: calc(var(--theia-ui-padding)*2/3); } .theia-ExpansionToggle:hover { diff --git a/packages/core/src/browser/style/variables-bright.useable.css b/packages/core/src/browser/style/variables-bright.useable.css index 8521a0ded3dac..ac55c26086389 100644 --- a/packages/core/src/browser/style/variables-bright.useable.css +++ b/packages/core/src/browser/style/variables-bright.useable.css @@ -65,7 +65,7 @@ is not optimized for dense, information rich UIs. */ --theia-content-font-size: 13px; - --theia-content-line-height: 1.5; + --theia-content-line-height: 22px; --theia-content-font-color0: black; --theia-content-font-color1: black; --theia-content-font-color2: var(--md-grey-700); @@ -191,6 +191,7 @@ is not optimized for dense, information rich UIs. --theia-icon-open-change: url(../icons/open-change-bright.svg); --theia-icon-preview: url(../icons/preview-bright.svg); --theia-icon-open-json: url(../icons/edit-json.svg); + --theia-icon-size: 16px; /* Scrollbars */ --theia-scrollbar-width: 10px; diff --git a/packages/core/src/browser/style/variables-dark.useable.css b/packages/core/src/browser/style/variables-dark.useable.css index 8d290a4ac6339..f952308ec67cb 100644 --- a/packages/core/src/browser/style/variables-dark.useable.css +++ b/packages/core/src/browser/style/variables-dark.useable.css @@ -65,7 +65,7 @@ is not optimized for dense, information rich UIs. */ --theia-content-font-size: 13px; - --theia-content-line-height: 1.5; + --theia-content-line-height: 22px; --theia-content-font-color0: white; --theia-content-font-color1: white; --theia-content-font-color2: var(--md-grey-500); @@ -191,6 +191,7 @@ is not optimized for dense, information rich UIs. --theia-icon-open-change: url(../icons/open-change-dark.svg); --theia-icon-preview: url(../icons/preview-dark.svg); --theia-icon-open-json: url(../icons/edit-json-dark.svg); + --theia-icon-size: 16px; /* Scrollbars */ --theia-scrollbar-width: 10px; diff --git a/packages/core/src/browser/style/view-container.css b/packages/core/src/browser/style/view-container.css index c01ae0b80e888..feecc2e8cc3f1 100644 --- a/packages/core/src/browser/style/view-container.css +++ b/packages/core/src/browser/style/view-container.css @@ -15,7 +15,7 @@ ********************************************************************************/ :root { - --theia-view-container-title-height: 22px; + --theia-view-container-title-height: var(--theia-content-line-height); --theia-view-container-content-height: calc(100% - var(--theia-view-container-title-height)); } @@ -33,7 +33,7 @@ .theia-view-container > .p-SplitPanel > .p-SplitPanel-child { min-width: 50px; - min-height: 22px; + min-height: var(--theia-content-line-height); } .theia-view-container > .p-SplitPanel > .p-SplitPanel-handle:after { @@ -104,7 +104,7 @@ .theia-view-container-drag-image { background: var(--theia-menu-color0); - line-height: 22px; + line-height: var(--theia-content-line-height); position: absolute; color: var(--theia-ui-font-color1); text-transform: uppercase; @@ -119,8 +119,8 @@ } .theia-view-container-part-title .item > div { - height: 16px; - width: 16px; - background-size: 16px; - line-height: 16px; + height: var(--theia-icon-size); + width: var(--theia-icon-size); + background-size: var(--theia-icon-size); + line-height: var(--theia-icon-size); } diff --git a/packages/core/src/browser/tree/test/tree-test-container.ts b/packages/core/src/browser/tree/test/tree-test-container.ts index bcb44d56027bd..d6c60adf3b073 100644 --- a/packages/core/src/browser/tree/test/tree-test-container.ts +++ b/packages/core/src/browser/tree/test/tree-test-container.ts @@ -24,7 +24,8 @@ import { TreeNavigationService } from '../tree-navigation'; import { TreeSearch } from '../tree-search'; import { FuzzySearch } from '../fuzzy-search'; import { MockLogger } from '../../../common/test/mock-logger'; -import { ILogger } from '../../../common'; +import { ILogger, bindContributionProvider } from '../../../common'; +import { LabelProviderContribution, LabelProvider } from '../../label-provider'; export function createTreeTestContainer(): Container { const container = new Container({ defaultScope: 'Singleton' }); @@ -41,5 +42,7 @@ export function createTreeTestContainer(): Container { container.bind(FuzzySearch).toSelf(); container.bind(MockLogger).toSelf(); container.bind(ILogger).to(MockLogger); + bindContributionProvider(container, LabelProviderContribution); + container.bind(LabelProvider).toSelf().inSingletonScope(); return container; } diff --git a/packages/core/src/browser/tree/tree-iterator.spec.ts b/packages/core/src/browser/tree/tree-iterator.spec.ts index 392ef888d8c27..6468f97dd7487 100644 --- a/packages/core/src/browser/tree/tree-iterator.spec.ts +++ b/packages/core/src/browser/tree/tree-iterator.spec.ts @@ -15,20 +15,12 @@ ********************************************************************************/ import { expect } from 'chai'; -import { Container } from 'inversify'; import { notEmpty } from '../../common/objects'; -import { ILogger } from '../../common/logger'; -import { MockLogger } from '../../common/test/mock-logger'; -import { TreeSearch } from './tree-search'; -import { FuzzySearch } from './fuzzy-search'; -import { Tree, TreeImpl } from './tree'; import { MockTreeModel } from './test/mock-tree-model'; -import { TreeNavigationService } from './tree-navigation'; -import { TreeModel, TreeModelImpl } from './tree-model'; -import { TreeSelectionService } from './tree-selection'; -import { TreeSelectionServiceImpl } from './tree-selection-impl'; -import { TreeExpansionService, TreeExpansionServiceImpl, ExpandableTreeNode } from './tree-expansion'; +import { TreeModel } from './tree-model'; import { DepthFirstTreeIterator, BreadthFirstTreeIterator, BottomUpTreeIterator, TopDownTreeIterator, Iterators } from './tree-iterator'; +import { createTreeTestContainer } from './test/tree-test-container'; +import { ExpandableTreeNode } from './tree-expansion'; // tslint:disable:no-unused-expression // tslint:disable:max-line-length @@ -119,21 +111,7 @@ describe('tree-iterator', () => { } function createTreeModel(): TreeModel { - const container = new Container({ defaultScope: 'Singleton' }); - container.bind(TreeImpl).toSelf(); - container.bind(Tree).toService(TreeImpl); - container.bind(TreeSelectionServiceImpl).toSelf(); - container.bind(TreeSelectionService).toService(TreeSelectionServiceImpl); - container.bind(TreeExpansionServiceImpl).toSelf(); - container.bind(TreeExpansionService).toService(TreeExpansionServiceImpl); - container.bind(TreeNavigationService).toSelf(); - container.bind(TreeModelImpl).toSelf(); - container.bind(TreeModel).toService(TreeModelImpl); - container.bind(TreeSearch).toSelf(); - container.bind(FuzzySearch).toSelf(); - container.bind(MockLogger).toSelf(); - container.bind(ILogger).to(MockLogger).inSingletonScope(); - return container.get(TreeModel); + return createTreeTestContainer().get(TreeModel); } }); diff --git a/packages/core/src/browser/tree/tree-label-provider.ts b/packages/core/src/browser/tree/tree-label-provider.ts new file mode 100644 index 0000000000000..b223c08f14acb --- /dev/null +++ b/packages/core/src/browser/tree/tree-label-provider.ts @@ -0,0 +1,40 @@ +/******************************************************************************** + * Copyright (C) 2019 TypeFox 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 'inversify'; +import { LabelProviderContribution } from '../label-provider'; +import { TreeNode } from './tree'; + +@injectable() +export class TreeLabelProvider implements LabelProviderContribution { + + canHandle(element: object): number { + return TreeNode.is(element) ? 50 : 0; + } + + getIcon(node: TreeNode): string | undefined { + return node.icon; + } + + getName(node: TreeNode): string | undefined { + return node.name; + } + + getLongName(node: TreeNode): string | undefined { + return node.description; + } + +} diff --git a/packages/core/src/browser/tree/tree-search.ts b/packages/core/src/browser/tree/tree-search.ts index 2dd74127532c5..bdba29eade864 100644 --- a/packages/core/src/browser/tree/tree-search.ts +++ b/packages/core/src/browser/tree/tree-search.ts @@ -21,6 +21,7 @@ import { Tree, TreeNode } from './tree'; import { TreeDecoration } from './tree-decorator'; import { FuzzySearch } from './fuzzy-search'; import { TopDownTreeIterator } from './tree-iterator'; +import { LabelProvider } from '../label-provider'; @injectable() export class TreeSearch implements Disposable { @@ -31,6 +32,9 @@ export class TreeSearch implements Disposable { @inject(FuzzySearch) protected readonly fuzzySearch: FuzzySearch; + @inject(LabelProvider) + protected readonly labelProvider: LabelProvider; + protected readonly disposables = new DisposableCollection(); protected readonly filteredNodesEmitter = new Emitter>>(); @@ -38,7 +42,7 @@ export class TreeSearch implements Disposable { protected _filteredNodes: ReadonlyArray> = []; @postConstruct() - init(): void { + protected init(): void { this.disposables.push(this.filteredNodesEmitter); } @@ -58,7 +62,7 @@ export class TreeSearch implements Disposable { return []; } const items = [...new TopDownTreeIterator(root, { pruneCollapsed: true })]; - const transform = (node: TreeNode) => node.name; + const transform = (node: TreeNode) => this.labelProvider.getName(node); this._filterResult = await this.fuzzySearch.filter({ items, pattern, diff --git a/packages/core/src/browser/tree/tree-selection-state.spec.ts b/packages/core/src/browser/tree/tree-selection-state.spec.ts index 3eb2c9e6f029b..c4d6669185f1d 100644 --- a/packages/core/src/browser/tree/tree-selection-state.spec.ts +++ b/packages/core/src/browser/tree/tree-selection-state.spec.ts @@ -15,19 +15,11 @@ ********************************************************************************/ import { expect } from 'chai'; -import { Container } from 'inversify'; -import { TreeSearch } from './tree-search'; -import { FuzzySearch } from './fuzzy-search'; -import { Tree, TreeImpl } from './tree'; -import { ILogger } from '../../common/logger'; -import { MockLogger } from '../../common/test/mock-logger'; import { MockTreeModel } from './test/mock-tree-model'; import { TreeSelectionState } from './tree-selection-state'; -import { TreeNavigationService } from './tree-navigation'; -import { TreeModel, TreeModelImpl } from './tree-model'; -import { TreeSelectionServiceImpl } from './tree-selection-impl'; -import { TreeExpansionService, TreeExpansionServiceImpl } from './tree-expansion'; -import { TreeSelection, TreeSelectionService, SelectableTreeNode } from './tree-selection'; +import { createTreeTestContainer } from './test/tree-test-container'; +import { SelectableTreeNode, TreeSelection } from './tree-selection'; +import { TreeModel } from './tree-model'; // tslint:disable:no-unused-expression @@ -439,21 +431,7 @@ describe('tree-selection-state', () => { } function createTreeModel(): TreeModel { - const container = new Container({ defaultScope: 'Singleton' }); - container.bind(TreeImpl).toSelf(); - container.bind(Tree).toService(TreeImpl); - container.bind(TreeSelectionServiceImpl).toSelf(); - container.bind(TreeSelectionService).toService(TreeSelectionServiceImpl); - container.bind(TreeExpansionServiceImpl).toSelf(); - container.bind(TreeExpansionService).toService(TreeExpansionServiceImpl); - container.bind(TreeNavigationService).toSelf(); - container.bind(TreeModelImpl).toSelf(); - container.bind(TreeModel).toService(TreeModelImpl); - container.bind(TreeSearch).toSelf(); - container.bind(FuzzySearch).toSelf(); - container.bind(MockLogger).toSelf(); - container.bind(ILogger).to(MockLogger).inSingletonScope(); - return container.get(TreeModel); + return createTreeTestContainer().get(TreeModel); } }); diff --git a/packages/core/src/browser/tree/tree-widget.tsx b/packages/core/src/browser/tree/tree-widget.tsx index fb8e06973c030..62eac121c9e9a 100644 --- a/packages/core/src/browser/tree/tree-widget.tsx +++ b/packages/core/src/browser/tree/tree-widget.tsx @@ -37,6 +37,7 @@ import { TreeSearch } from './tree-search'; import { ElementExt } from '@phosphor/domutils'; import { TreeWidgetSelection } from './tree-widget-selection'; import { MaybePromise } from '../../common/types'; +import { LabelProvider } from '../label-provider'; const debounce = require('lodash.debounce'); @@ -70,6 +71,8 @@ export interface TreeProps { */ readonly leftPadding: number; + readonly expansionTogglePadding: number; + /** * `true` if the tree widget support multi-selection. Otherwise, `false`. Defaults to `false`. */ @@ -112,7 +115,8 @@ export interface NodeProps { * The default tree properties. */ export const defaultTreeProps: TreeProps = { - leftPadding: 8 + leftPadding: 8, + expansionTogglePadding: 18 }; export namespace TreeWidget { @@ -155,6 +159,9 @@ export class TreeWidget extends ReactWidget implements StatefulWidget { @inject(SelectionService) protected readonly selectionService: SelectionService; + @inject(LabelProvider) + protected readonly labelProvider: LabelProvider; + protected shouldScrollToRow = true; constructor( @@ -214,7 +221,15 @@ export class TreeWidget extends ReactWidget implements StatefulWidget { this.model.onNodeRefreshed(() => this.updateDecorations()), this.model.onExpansionChanged(() => this.updateDecorations()), this.decoratorService, - this.decoratorService.onDidChangeDecorations(() => this.updateDecorations()) + this.decoratorService.onDidChangeDecorations(() => this.updateDecorations()), + this.labelProvider.onDidChange(e => { + for (const row of this.rows.values()) { + if (e.affects(row)) { + this.forceUpdate(); + return; + } + } + }) ]); setTimeout(() => { this.updateRows(); @@ -510,7 +525,6 @@ export class TreeWidget extends ReactWidget implements StatefulWidget { return
; } @@ -537,7 +551,7 @@ export class TreeWidget extends ReactWidget implements StatefulWidget { }; } const children: React.ReactNode[] = []; - const caption = node.name; + const caption = this.toNodeName(node); const highlight = this.getDecorationData(node, 'highlight')[0]; if (highlight) { children.push(this.toReactNode(caption, highlight)); @@ -825,11 +839,20 @@ export class TreeWidget extends ReactWidget implements StatefulWidget { * @returns the CSS properties if available. */ protected getDefaultNodeStyle(node: TreeNode, props: NodeProps): React.CSSProperties | undefined { - // If the node is a composite, a toggle will be rendered. Otherwise we need to add the width and the left, right padding => 18px - const paddingLeft = `${props.depth * this.props.leftPadding + (this.isExpandable(node) ? 0 : 18)}px`; - return { - paddingLeft - }; + const paddingLeft = this.getPaddingLeft(node, props) + 'px'; + return { paddingLeft }; + } + + protected getPaddingLeft(node: TreeNode, props: NodeProps): number { + return props.depth * this.props.leftPadding + (this.needsExpansionTogglePadding(node) ? this.props.expansionTogglePadding : 0); + } + + /** + * If the node is a composite, a toggle will be rendered. + * Otherwise we need to add the width and the left, right padding => 18px + */ + protected needsExpansionTogglePadding(node: TreeNode): boolean { + return !this.isExpandable(node); } /** @@ -1213,6 +1236,18 @@ export class TreeWidget extends ReactWidget implements StatefulWidget { } } + protected toNodeIcon(node: TreeNode): string { + return this.labelProvider.getIcon(node); + } + + protected toNodeName(node: TreeNode): string { + return this.labelProvider.getName(node); + } + + protected toNodeDescription(node: TreeNode): string { + return this.labelProvider.getLongName(node); + } + } export namespace TreeWidget { /** diff --git a/packages/core/src/browser/tree/tree.ts b/packages/core/src/browser/tree/tree.ts index 51e5dec302005..330b3a53d1098 100644 --- a/packages/core/src/browser/tree/tree.ts +++ b/packages/core/src/browser/tree/tree.ts @@ -69,14 +69,20 @@ export interface TreeNode { readonly id: string; /** * A human-readable name of this tree node. + * + * @deprecated use `LabelProvider.getName` instead or move this property to your tree node type */ - readonly name: string; + readonly name?: string; /** * A css string for this tree node icon. + * + * @deprecated use `LabelProvider.getIcon` instead or move this property to your tree node type */ readonly icon?: string; /** * A human-readable description of this tree node. + * + * @deprecated use `LabelProvider.getLongName` instead or move this property to your tree node type */ readonly description?: string; /** @@ -100,6 +106,10 @@ export interface TreeNode { } export namespace TreeNode { + export function is(node: Object | undefined): node is TreeNode { + return !!node && typeof node === 'object' && 'id' in node && 'parent' in node; + } + export function equals(left: TreeNode | undefined, right: TreeNode | undefined): boolean { return left === right || (!!left && !!right && left.id === right.id); } diff --git a/packages/debug/src/browser/style/index.css b/packages/debug/src/browser/style/index.css index f8ba29024f53a..03c26aeafb751 100644 --- a/packages/debug/src/browser/style/index.css +++ b/packages/debug/src/browser/style/index.css @@ -138,8 +138,8 @@ pointer-events: all; padding-left: var(--theia-ui-padding); padding-right: var(--theia-ui-padding); - min-width: 16px; - min-height: 16px; + min-width: var(--theia-icon-size); + min-height: var(--theia-icon-size); } .debug-toolbar .debug-action:not(:focus) { diff --git a/packages/editor/src/browser/editor-command.ts b/packages/editor/src/browser/editor-command.ts index 8e1d4945f0f1d..0b121916d08d9 100644 --- a/packages/editor/src/browser/editor-command.ts +++ b/packages/editor/src/browser/editor-command.ts @@ -191,9 +191,9 @@ export class EditorCommandContribution implements CommandContribution { const items: QuickPickItem<'autoDetect' | Language>[] = [ { label: 'Auto Detect', value: 'autoDetect' }, { type: 'separator', label: 'languages (identifier)' }, - ... (await Promise.all(this.languages.languages.map( + ... (this.languages.languages.map( language => this.toQuickPickLanguage(language, current) - ))).sort((e, e2) => e.label.localeCompare(e2.label)) + )).sort((e, e2) => e.label.localeCompare(e2.label)) ]; const selected = await this.quickPick.show(items, { placeholder: 'Select Language Mode' @@ -275,9 +275,10 @@ export class EditorCommandContribution implements CommandContribution { } } - protected async toQuickPickLanguage(value: Language, current: string): Promise> { + protected toQuickPickLanguage(value: Language, current: string): QuickPickValue { const languageUri = this.toLanguageUri(value); - const iconClass = await this.labelProvider.getIcon(languageUri) + ' file-icon'; + const icon = this.labelProvider.getIcon(languageUri); + const iconClass = icon !== '' ? icon + ' file-icon' : undefined; return { value, label: value.name, diff --git a/packages/editor/src/browser/editor-quick-open-service.ts b/packages/editor/src/browser/editor-quick-open-service.ts index bbf05ad9ad41f..e2df18766c9ab 100644 --- a/packages/editor/src/browser/editor-quick-open-service.ts +++ b/packages/editor/src/browser/editor-quick-open-service.ts @@ -22,7 +22,6 @@ import { } from '@theia/core/lib/browser'; import URI from '@theia/core/lib/common/uri'; import { LabelProvider } from '@theia/core/lib/browser/label-provider'; -import { CancellationTokenSource } from '@theia/core/lib/common'; import { EditorManager } from './editor-manager'; import { EditorWidget } from './editor-widget'; @@ -58,9 +57,6 @@ export class EditorQuickOpenService implements QuickOpenModel, QuickOpenHandler }, fuzzyMatchDescription: { enableSeparateSubstringMatching: true - }, - onClose: () => { - this.cancelIndicator.cancel(); } }; } @@ -69,13 +65,7 @@ export class EditorQuickOpenService implements QuickOpenModel, QuickOpenHandler this.prefixQuickOpenService.open(this.prefix); } - private cancelIndicator = new CancellationTokenSource(); - - public async onType(lookFor: string, acceptor: (items: QuickOpenItem[]) => void): Promise { - this.cancelIndicator.cancel(); - this.cancelIndicator = new CancellationTokenSource(); - const token = this.cancelIndicator.token; - + onType(lookFor: string, acceptor: (items: QuickOpenItem[]) => void): void { const editorItems: QuickOpenItem[] = []; // Get the alphabetically sorted list of URIs of all currently opened editor widgets. @@ -93,22 +83,21 @@ export class EditorQuickOpenService implements QuickOpenModel, QuickOpenHandler } for (const uri of widgets) { - const item = await this.toItem(uri); - if (!!token.isCancellationRequested) { - return; - } + const item = this.toItem(uri); editorItems.push(item); acceptor(editorItems); } return; } - protected async toItem(uri: URI): Promise> { + protected toItem(uri: URI): QuickOpenItem { const description = this.labelProvider.getLongName(uri.parent); + const icon = this.labelProvider.getIcon(uri); + const iconClass = icon === '' ? undefined : icon + ' file-icon'; const options: QuickOpenItemOptions = { label: this.labelProvider.getName(uri), - iconClass: await this.labelProvider.getIcon(uri) + ' file-icon', + iconClass, description: description, tooltip: uri.path.toString(), uri: uri, diff --git a/packages/editor/src/browser/editor-widget-factory.ts b/packages/editor/src/browser/editor-widget-factory.ts index 0a01b0b37ae1c..88156f1c36c4c 100644 --- a/packages/editor/src/browser/editor-widget-factory.ts +++ b/packages/editor/src/browser/editor-widget-factory.ts @@ -46,9 +46,9 @@ export class EditorWidgetFactory implements WidgetFactory { const textEditor = await this.editorProvider(uri); const newEditor = new EditorWidget(textEditor, this.selectionService); - await this.setLabels(newEditor, uri); - const labelListener = this.labelProvider.onDidChange(async event => { - if (uri && event.affects(uri)) { + this.setLabels(newEditor, uri); + const labelListener = this.labelProvider.onDidChange(event => { + if (event.affects(uri)) { this.setLabels(newEditor, uri); } }); @@ -60,8 +60,8 @@ export class EditorWidgetFactory implements WidgetFactory { return newEditor; } - private async setLabels(editor: EditorWidget, uri: URI): Promise { - const icon = await this.labelProvider.getIcon(uri); + private setLabels(editor: EditorWidget, uri: URI): void { + const icon = this.labelProvider.getIcon(uri); editor.title.label = this.labelProvider.getName(uri); editor.title.iconClass = icon + ' file-icon'; diff --git a/packages/file-search/src/browser/quick-file-open.ts b/packages/file-search/src/browser/quick-file-open.ts index 393df7214ee9c..ccbd1efe142bb 100644 --- a/packages/file-search/src/browser/quick-file-open.ts +++ b/packages/file-search/src/browser/quick-file-open.ts @@ -159,10 +159,7 @@ export class QuickFileOpenService implements QuickOpenModel, QuickOpenHandler { for (const location of locations) { const uriString = location.uri.toString(); if (location.uri.scheme === 'file' && !alreadyCollected.has(uriString) && fuzzy.test(lookFor, uriString)) { - const item = await this.toItem(location.uri, { groupLabel: recentlyUsedItems.length === 0 ? 'recently opened' : undefined, showBorder: false }); - if (token.isCancellationRequested) { - return; - } + const item = this.toItem(location.uri, { groupLabel: recentlyUsedItems.length === 0 ? 'recently opened' : undefined, showBorder: false }); recentlyUsedItems.push(item); alreadyCollected.add(uriString); } @@ -175,10 +172,7 @@ export class QuickFileOpenService implements QuickOpenModel, QuickOpenHandler { const fileSearchResultItems: QuickOpenItem[] = []; for (const fileUri of results) { if (!alreadyCollected.has(fileUri)) { - const item = await this.toItem(fileUri); - if (token.isCancellationRequested) { - return; - } + const item = this.toItem(fileUri); fileSearchResultItems.push(item); alreadyCollected.add(fileUri); } @@ -192,10 +186,7 @@ export class QuickFileOpenService implements QuickOpenModel, QuickOpenHandler { const first = sortedResults[0]; sortedResults.shift(); if (first) { - const item = await this.toItem(first.getUri()!, { groupLabel: 'file results', showBorder: !!recentlyUsedItems.length }); - if (token.isCancellationRequested) { - return; - } + const item = this.toItem(first.getUri()!, { groupLabel: 'file results', showBorder: !!recentlyUsedItems.length }); sortedResults.unshift(item); } // Return the recently used items, followed by the search results. @@ -316,7 +307,7 @@ export class QuickFileOpenService implements QuickOpenModel, QuickOpenHandler { .catch(error => this.messageService.error(error)); } - private async toItem(uriOrString: URI | string, group?: QuickOpenGroupItemOptions): Promise> { + private toItem(uriOrString: URI | string, group?: QuickOpenGroupItemOptions): QuickOpenItem { const uri = uriOrString instanceof URI ? uriOrString : new URI(uriOrString); let description = this.labelProvider.getLongName(uri.parent); if (this.workspaceService.isMultiRootWorkspaceOpened) { @@ -325,9 +316,11 @@ export class QuickFileOpenService implements QuickOpenModel, QuickOpenHandler { description = `${rootUri.displayName} • ${description}`; } } + const icon = this.labelProvider.getIcon(uri); + const iconClass = icon === '' ? undefined : icon + ' file-icon'; const options: QuickOpenItemOptions = { label: this.labelProvider.getName(uri), - iconClass: await this.labelProvider.getIcon(uri) + ' file-icon', + iconClass, description, tooltip: this.labelProvider.getLongName(uri), uri: uri, diff --git a/packages/filesystem/src/browser/file-dialog/file-dialog-service.ts b/packages/filesystem/src/browser/file-dialog/file-dialog-service.ts index 2a740057287e0..ef8dc048af9de 100644 --- a/packages/filesystem/src/browser/file-dialog/file-dialog-service.ts +++ b/packages/filesystem/src/browser/file-dialog/file-dialog-service.ts @@ -76,11 +76,9 @@ export class DefaultFileDialogService { if (folder) { const folderUri = new URI(folder.uri); const rootUri = folder.isDirectory ? folderUri : folderUri.parent; - const name = this.labelProvider.getName(rootUri); const rootStat = await this.fileSystem.getFileStat(rootUri.toString()); if (rootStat) { - const label = await this.labelProvider.getIcon(rootStat); - return DirNode.createRoot(rootStat, name, label); + return DirNode.createRoot(rootStat); } } return undefined; diff --git a/packages/filesystem/src/browser/file-dialog/file-dialog.ts b/packages/filesystem/src/browser/file-dialog/file-dialog.ts index b62b0fb1660db..0688b71069700 100644 --- a/packages/filesystem/src/browser/file-dialog/file-dialog.ts +++ b/packages/filesystem/src/browser/file-dialog/file-dialog.ts @@ -17,7 +17,7 @@ import { injectable, inject } from 'inversify'; import { Message } from '@phosphor/messaging'; import { Disposable, MaybeArray } from '@theia/core/lib/common'; -import { Key } from '@theia/core/lib/browser'; +import { Key, LabelProvider } from '@theia/core/lib/browser'; import { AbstractDialog, DialogProps, setEnabled, createIconButton, Widget } from '@theia/core/lib/browser'; import { FileStatNode } from '../file-tree'; import { LocationListRenderer } from '../location'; @@ -283,6 +283,9 @@ export class SaveFileDialog extends FileDialog { protected fileNameField: HTMLInputElement | undefined; + @inject(LabelProvider) + protected readonly labelProvider: LabelProvider; + constructor( @inject(SaveFileDialogProps) readonly props: SaveFileDialogProps, @inject(FileDialogWidget) readonly widget: FileDialogWidget @@ -299,9 +302,9 @@ export class SaveFileDialog extends FileDialog { // Update file name field when changing a selection if (this.fileNameField) { if (this.widget.model.selectedFileStatNodes.length === 1) { - const fileStat = this.widget.model.selectedFileStatNodes[0]; - if (!fileStat.fileStat.isDirectory) { - this.fileNameField.value = fileStat.name; + const node = this.widget.model.selectedFileStatNodes[0]; + if (!node.fileStat.isDirectory) { + this.fileNameField.value = this.labelProvider.getName(node); } } else { this.fileNameField.value = ''; diff --git a/packages/filesystem/src/browser/file-tree/file-tree-label-provider.ts b/packages/filesystem/src/browser/file-tree/file-tree-label-provider.ts new file mode 100644 index 0000000000000..091fd07b2dbd0 --- /dev/null +++ b/packages/filesystem/src/browser/file-tree/file-tree-label-provider.ts @@ -0,0 +1,53 @@ +/******************************************************************************** + * Copyright (C) 2019 TypeFox 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, inject } from 'inversify'; +import { LabelProviderContribution, DidChangeLabelEvent, LabelProvider } from '@theia/core/lib/browser/label-provider'; +import { FileStatNode } from './file-tree'; +import { TreeLabelProvider } from '@theia/core/lib/browser/tree/tree-label-provider'; + +@injectable() +export class FileTreeLabelProvider implements LabelProviderContribution { + + @inject(LabelProvider) + protected readonly labelProvider: LabelProvider; + + @inject(TreeLabelProvider) + protected readonly treeLabelProvider: TreeLabelProvider; + + canHandle(element: object): number { + return FileStatNode.is(element) ? + this.treeLabelProvider.canHandle(element) + 1 : + 0; + } + + getIcon(node: FileStatNode): string { + return this.labelProvider.getIcon(node.fileStat); + } + + getName(node: FileStatNode): string { + return this.labelProvider.getName(node.fileStat); + } + + getDescription(node: FileStatNode): string { + return this.labelProvider.getLongName(node.fileStat); + } + + affects(node: FileStatNode, event: DidChangeLabelEvent): boolean { + return event.affects(node.fileStat); + } + +} diff --git a/packages/filesystem/src/browser/file-tree/file-tree-model.ts b/packages/filesystem/src/browser/file-tree/file-tree-model.ts index cfc08138c7bb6..9896969dfa890 100644 --- a/packages/filesystem/src/browser/file-tree/file-tree-model.ts +++ b/packages/filesystem/src/browser/file-tree/file-tree-model.ts @@ -49,9 +49,7 @@ export class FileTreeModel extends TreeModelImpl implements LocationService { if (uri) { this.fileSystem.getFileStat(uri.toString()).then(async fileStat => { if (fileStat) { - const label = this.labelProvider.getName(uri); - const icon = await this.labelProvider.getIcon(fileStat); - const node = DirNode.createRoot(fileStat, label, icon); + const node = DirNode.createRoot(fileStat); this.navigateTo(node); } }); @@ -167,10 +165,11 @@ export class FileTreeModel extends TreeModelImpl implements LocationService { if (target.uri.toString() === sourceUri) { /* Folder on itself */ return; } - const targetUri = target.uri.resolve(source.name).toString(); + const name = source.uri.displayName; + const targetUri = target.uri.resolve(name).toString(); if (sourceUri !== targetUri) { /* File not on itself */ const fileExistsInTarget = await this.fileSystem.exists(targetUri); - if (!fileExistsInTarget || await this.shouldReplace(source.name)) { + if (!fileExistsInTarget || await this.shouldReplace(name)) { await this.fileSystem.move(sourceUri, targetUri, { overwrite: true }); } } diff --git a/packages/filesystem/src/browser/file-tree/file-tree-widget.tsx b/packages/filesystem/src/browser/file-tree/file-tree-widget.tsx index 4e76033aac1c6..e29d975298f0f 100644 --- a/packages/filesystem/src/browser/file-tree/file-tree-widget.tsx +++ b/packages/filesystem/src/browser/file-tree/file-tree-widget.tsx @@ -23,6 +23,7 @@ import { ContextMenuRenderer, NodeProps, TreeProps, TreeNode, TreeWidget, Compos import { FileUploadService } from '../file-upload-service'; import { DirNode, FileStatNode } from './file-tree'; import { FileTreeModel } from './file-tree-model'; +import { IconThemeService } from '@theia/core/lib/browser/icon-theme-service'; export const FILE_TREE_CLASS = 'theia-FileTree'; export const FILE_STAT_NODE_CLASS = 'theia-FileStatNode'; @@ -37,6 +38,9 @@ export class FileTreeWidget extends TreeWidget { @inject(FileUploadService) protected readonly uploadService: FileUploadService; + @inject(IconThemeService) + protected readonly iconThemeService: IconThemeService; + constructor( @inject(TreeProps) readonly props: TreeProps, @inject(FileTreeModel) readonly model: FileTreeModel, @@ -59,8 +63,9 @@ export class FileTreeWidget extends TreeWidget { } protected renderIcon(node: TreeNode, props: NodeProps): React.ReactNode { - if (FileStatNode.is(node)) { - return
; + const icon = this.toNodeIcon(node); + if (icon) { + return
; } // tslint:disable-next-line:no-null-keyword return null; @@ -108,7 +113,7 @@ export class FileTreeWidget extends TreeWidget { if (event.dataTransfer) { let label: string; if (selectedNodes.length === 1) { - label = node.name; + label = this.toNodeName(node); } else { label = String(selectedNodes.length); } @@ -208,4 +213,34 @@ export class FileTreeWidget extends TreeWidget { const ids: string[] = JSON.parse(resources); return ids.map(id => this.model.getNode(id)).filter(node => node !== undefined) as TreeNode[]; } + + protected get hidesExplorerArrows(): boolean { + const theme = this.iconThemeService.getDefinition(this.iconThemeService.current); + return !!theme && !!theme.hidesExplorerArrows; + } + + protected renderExpansionToggle(node: TreeNode, props: NodeProps): React.ReactNode { + if (this.hidesExplorerArrows) { + // tslint:disable-next-line:no-null-keyword + return null; + } + return super.renderExpansionToggle(node, props); + } + + protected getPaddingLeft(node: TreeNode, props: NodeProps): number { + if (this.hidesExplorerArrows) { + // aditional left padding instead of top-level expansion toggle + return super.getPaddingLeft(node, props) + this.props.leftPadding; + } + return super.getPaddingLeft(node, props); + } + + protected needsExpansionTogglePadding(node: TreeNode): boolean { + const theme = this.iconThemeService.getDefinition(this.iconThemeService.current); + if (theme && (theme.hidesExplorerArrows || (theme.hasFileIcons && !theme.hasFolderIcons))) { + return false; + } + return super.needsExpansionTogglePadding(node); + } + } diff --git a/packages/filesystem/src/browser/file-tree/file-tree.ts b/packages/filesystem/src/browser/file-tree/file-tree.ts index 8d78df4c0638b..2f0efb3ac8599 100644 --- a/packages/filesystem/src/browser/file-tree/file-tree.ts +++ b/packages/filesystem/src/browser/file-tree/file-tree.ts @@ -14,11 +14,10 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ -import { injectable, inject, postConstruct } from 'inversify'; +import { injectable, inject } from 'inversify'; import URI from '@theia/core/lib/common/uri'; import { TreeNode, CompositeTreeNode, SelectableTreeNode, ExpandableTreeNode, TreeImpl } from '@theia/core/lib/browser'; import { FileSystem, FileStat } from '../../common'; -import { LabelProvider, DidChangeLabelEvent } from '@theia/core/lib/browser/label-provider'; import { UriSelection } from '@theia/core/lib/common/selection'; import { FileSelection } from '../file-selection'; @@ -26,35 +25,6 @@ import { FileSelection } from '../file-selection'; export class FileTree extends TreeImpl { @inject(FileSystem) protected readonly fileSystem: FileSystem; - @inject(LabelProvider) protected readonly labelProvider: LabelProvider; - - @postConstruct() - protected initFileTree(): void { - this.toDispose.push( - this.labelProvider.onDidChange((event: DidChangeLabelEvent) => this.doUpdateElement(event)) - ); - } - - protected async doUpdateElement(event: DidChangeLabelEvent): Promise { - let isAnyAffectedNodes = false; - for (const nodeId of Object.keys(this.nodes)) { - const mutableNode = this.nodes[nodeId]; - - const nodeWithPossibleUri = mutableNode; - if (mutableNode && FileStatNode.is(nodeWithPossibleUri)) { - const uri = nodeWithPossibleUri.uri; - if (event.affects(uri)) { - mutableNode.name = this.labelProvider.getName(uri); - mutableNode.description = this.labelProvider.getLongName(uri); - mutableNode.icon = await this.labelProvider.getIcon(uri); - isAnyAffectedNodes = true; - } - } - } - if (isAnyAffectedNodes) { - this.fireChanged(); - } - } async resolveChildren(parent: CompositeTreeNode): Promise { if (FileStatNode.is(parent)) { @@ -87,10 +57,8 @@ export class FileTree extends TreeImpl { return result.sort(DirNode.compare); } - protected async toNode(fileStat: FileStat, parent: CompositeTreeNode): Promise { + protected toNode(fileStat: FileStat, parent: CompositeTreeNode): FileNode | DirNode { const uri = new URI(fileStat.uri); - const name = this.labelProvider.getName(uri); - const icon = await this.labelProvider.getIcon(fileStat); const id = this.toNodeId(uri, parent); const node = this.getNode(id); if (fileStat.isDirectory) { @@ -99,7 +67,7 @@ export class FileTree extends TreeImpl { return node; } return { - id, uri, fileStat, name, icon, parent, + id, uri, fileStat, parent, expanded: false, selected: false, children: [] @@ -110,7 +78,7 @@ export class FileTree extends TreeImpl { return node; } return { - id, uri, fileStat, name, icon, parent, + id, uri, fileStat, parent, selected: false }; } @@ -137,19 +105,32 @@ export namespace FileStatNode { export type FileNode = FileStatNode; export namespace FileNode { - export function is(node: TreeNode | undefined): node is FileNode { + export function is(node: Object | undefined): node is FileNode { return FileStatNode.is(node) && !node.fileStat.isDirectory; } } export type DirNode = FileStatNode & ExpandableTreeNode; export namespace DirNode { - export function is(node: TreeNode | undefined): node is DirNode { + export function is(node: Object | undefined): node is DirNode { return FileStatNode.is(node) && node.fileStat.isDirectory; } export function compare(node: TreeNode, node2: TreeNode): number { - return DirNode.dirCompare(node, node2) || node.name.localeCompare(node2.name); + return DirNode.dirCompare(node, node2) || uriCompare(node, node2); + } + + export function uriCompare(node: TreeNode, node2: TreeNode): number { + if (FileNode.is(node)) { + if (FileNode.is(node2)) { + return node.uri.displayName.localeCompare(node2.uri.displayName); + } + return 1; + } + if (FileNode.is(node2)) { + return -1; + } + return 0; } export function dirCompare(node: TreeNode, node2: TreeNode): number { @@ -158,13 +139,11 @@ export namespace DirNode { return b - a; } - export function createRoot(fileStat: FileStat, name: string, icon: string): DirNode { + export function createRoot(fileStat: FileStat): DirNode { const uri = new URI(fileStat.uri); const id = fileStat.uri; return { id, uri, fileStat, - name, - icon, visible: true, parent: undefined, children: [], diff --git a/packages/filesystem/src/browser/filesystem-frontend-module.ts b/packages/filesystem/src/browser/filesystem-frontend-module.ts index 618fefa59c3ef..3da73512178fa 100644 --- a/packages/filesystem/src/browser/filesystem-frontend-module.ts +++ b/packages/filesystem/src/browser/filesystem-frontend-module.ts @@ -18,7 +18,7 @@ import '../../src/browser/style/index.css'; import { ContainerModule, interfaces } from 'inversify'; import { ResourceResolver, CommandContribution } from '@theia/core/lib/common'; -import { WebSocketConnectionProvider, FrontendApplicationContribution, ConfirmDialog } from '@theia/core/lib/browser'; +import { WebSocketConnectionProvider, FrontendApplicationContribution, ConfirmDialog, LabelProviderContribution } from '@theia/core/lib/browser'; import { FileSystem, fileSystemPath, FileShouldOverwrite, FileStat } from '../common'; import { fileSystemWatcherPath, FileSystemWatcherServer, @@ -30,6 +30,7 @@ import { FileSystemWatcher } from './filesystem-watcher'; import { FileSystemFrontendContribution } from './filesystem-frontend-contribution'; import { FileSystemProxyFactory } from './filesystem-proxy-factory'; import { FileUploadService } from './file-upload-service'; +import { FileTreeLabelProvider } from './file-tree/file-tree-label-provider'; export default new ContainerModule(bind => { bindFileSystemPreferences(bind); @@ -62,6 +63,9 @@ export default new ContainerModule(bind => { bind(FileSystemFrontendContribution).toSelf().inSingletonScope(); bind(CommandContribution).toService(FileSystemFrontendContribution); bind(FrontendApplicationContribution).toService(FileSystemFrontendContribution); + + bind(FileTreeLabelProvider).toSelf().inSingletonScope(); + bind(LabelProviderContribution).toService(FileTreeLabelProvider); }); export function bindFileResource(bind: interfaces.Bind): void { diff --git a/packages/filesystem/src/browser/style/file-icons.css b/packages/filesystem/src/browser/style/file-icons.css index 0627fbc315480..39523ab780315 100644 --- a/packages/filesystem/src/browser/style/file-icons.css +++ b/packages/filesystem/src/browser/style/file-icons.css @@ -14,7 +14,7 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ - .file-icon { + .theia-file-icons-js { /* Here, the `line-height` ensures that FontAwesome and `file-icons-js` container has the same height. Ideally, it would be 1 em, but since we set the max height above (and other places too) with 0.8 @@ -23,18 +23,23 @@ line-height: 0.8em; } -.file-icon:before { +.theia-file-icons-js:before { font-size: calc(var(--theia-content-font-size) * 0.8); +} + +.fa-file:before, +.fa-folder:before, +.theia-file-icons-js:before { text-align: center; margin-right: 4px; } -.theia-app-sides .file-icon { +.theia-app-sides .theia-file-icons-js { max-height: none; line-height: inherit; } -.theia-app-sides .file-icon:before { +.theia-app-sides .theia-file-icons-js:before { font-size: var(--theia-private-sidebar-icon-size); margin-right: 0px; } diff --git a/packages/git/src/browser/diff/git-diff-widget.tsx b/packages/git/src/browser/diff/git-diff-widget.tsx index d49d62c88f0d7..4aad153daa8b3 100644 --- a/packages/git/src/browser/diff/git-diff-widget.tsx +++ b/packages/git/src/browser/diff/git-diff-widget.tsx @@ -16,12 +16,12 @@ import { inject, injectable, postConstruct } from 'inversify'; import URI from '@theia/core/lib/common/uri'; -import { StatefulWidget, SELECTED_CLASS, DiffUris, Message } from '@theia/core/lib/browser'; +import { StatefulWidget, DiffUris, Message } from '@theia/core/lib/browser'; import { EditorManager, EditorOpenerOptions, EditorWidget, DiffNavigatorProvider, DiffNavigator } from '@theia/editor/lib/browser'; import { GitFileChange, GitFileStatus, Git, WorkingDirectoryStatus } from '../../common'; import { GitWatcher } from '../../common'; import { GIT_RESOURCE_SCHEME } from '../git-resource'; -import { GitNavigableListWidget } from '../git-navigable-list-widget'; +import { GitNavigableListWidget, GitItemComponent } from '../git-navigable-list-widget'; import { GitFileChangeNode } from '../git-file-change-node'; import { Deferred } from '@theia/core/lib/common/promise-util'; import * as React from 'react'; @@ -96,21 +96,7 @@ export class GitDiffWidget extends GitNavigableListWidget imp range: options.range, uri: options.uri }); - const fileChangeNodes: GitFileChangeNode[] = []; - for (const fileChange of fileChanges) { - const fileChangeUri = new URI(fileChange.uri); - const [icon, label, description] = await Promise.all([ - this.labelProvider.getIcon(fileChangeUri), - this.labelProvider.getName(fileChangeUri), - this.relativePath(fileChangeUri.parent) - ]); - - const caption = this.computeCaption(fileChange); - fileChangeNodes.push({ - ...fileChange, icon, label, description, caption - }); - } - this.fileChangeNodes = fileChangeNodes; + this.fileChangeNodes = fileChanges; this.update(); } } @@ -173,7 +159,7 @@ export class GitDiffWidget extends GitNavigableListWidget imp } protected renderPath(): React.ReactNode { if (this.options.uri) { - const path = this.relativePath(this.options.uri); + const path = this.gitLabelProvider.relativePath(this.options.uri); if (path.length > 0) { return '/' + path; } else { @@ -260,32 +246,13 @@ export class GitDiffWidget extends GitNavigableListWidget imp } protected renderGitItem(change: GitFileChangeNode): React.ReactNode { - return
-
{ - this.revealChange(change); - }} - onClick={() => { - this.selectNode(change); - }}> - - {change.label + ' '} - {change.description} -
- { - change.extraIconClassName ?
- : '' - } -
- {this.getStatusCaption(change.status, true).charAt(0)} -
-
; + return this.revealChange(change), + selectNode: () => this.selectNode(change) + }} />; } protected navigateRight(): void { diff --git a/packages/git/src/browser/git-file-change-label-provider.ts b/packages/git/src/browser/git-file-change-label-provider.ts new file mode 100644 index 0000000000000..d89a2f19820d8 --- /dev/null +++ b/packages/git/src/browser/git-file-change-label-provider.ts @@ -0,0 +1,75 @@ +/******************************************************************************** + * Copyright (C) 2019 TypeFox 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, inject } from 'inversify'; +import { LabelProviderContribution, DidChangeLabelEvent, LabelProvider } from '@theia/core/lib/browser/label-provider'; +import { GitFileChangeNode } from './git-file-change-node'; +import URI from '@theia/core/lib/common/uri'; +import { GitRepositoryProvider } from './git-repository-provider'; +import { Repository, GitFileStatus } from '../common'; + +@injectable() +export class GitFileChangeLabelProvider implements LabelProviderContribution { + + @inject(LabelProvider) + protected readonly labelProvider: LabelProvider; + + @inject(GitRepositoryProvider) + protected readonly repositoryProvider: GitRepositoryProvider; + + canHandle(element: object): number { + return GitFileChangeNode.is(element) ? 100 : 0; + } + + getIcon(node: GitFileChangeNode): string { + return this.labelProvider.getIcon(new URI(node.uri)); + } + + getName(node: GitFileChangeNode): string { + return this.labelProvider.getName(new URI(node.uri)); + } + + getDescription(node: GitFileChangeNode): string { + return this.relativePath(new URI(node.uri).parent); + } + + affects(node: GitFileChangeNode, event: DidChangeLabelEvent): boolean { + return event.affects(new URI(node.uri)); + } + + getCaption(fileChange: GitFileChangeNode): string { + let result = `${this.relativePath(fileChange.uri)} - ${this.getStatusCaption(fileChange.status, true)}`; + if (fileChange.oldUri) { + result = `${this.relativePath(fileChange.oldUri)} -> ${result}`; + } + return result; + } + + relativePath(uri: URI | string): string { + const parsedUri = typeof uri === 'string' ? new URI(uri) : uri; + const repo = this.repositoryProvider.findRepository(parsedUri); + const relativePath = repo && Repository.relativePath(repo, parsedUri); + if (relativePath) { + return relativePath.toString(); + } + return this.labelProvider.getLongName(parsedUri); + } + + getStatusCaption(status: GitFileStatus, staged?: boolean): string { + return GitFileStatus.toString(status, staged); + } + +} diff --git a/packages/git/src/browser/git-file-change-node.ts b/packages/git/src/browser/git-file-change-node.ts index d1adeb7e8ac6b..8b108a4861007 100644 --- a/packages/git/src/browser/git-file-change-node.ts +++ b/packages/git/src/browser/git-file-change-node.ts @@ -17,16 +17,11 @@ import { GitFileChange } from '../common/git-model'; export interface GitFileChangeNode extends GitFileChange { - readonly icon: string; - readonly label: string; - readonly description: string; - readonly caption?: string; - readonly extraIconClassName?: string; readonly commitSha?: string; selected?: boolean; } export namespace GitFileChangeNode { export function is(node: Object | undefined): node is GitFileChangeNode { - return !!node && 'uri' in node && 'status' in node && 'description' in node && 'label' in node && 'icon' in node; + return !!node && 'uri' in node && 'status' in node; } } diff --git a/packages/git/src/browser/git-frontend-module.ts b/packages/git/src/browser/git-frontend-module.ts index a71b0f71c5a80..d755ea76ab71e 100644 --- a/packages/git/src/browser/git-frontend-module.ts +++ b/packages/git/src/browser/git-frontend-module.ts @@ -42,6 +42,7 @@ import { GitCommitMessageValidator } from './git-commit-message-validator'; import { GitSyncService } from './git-sync-service'; import { GitErrorHandler } from './git-error-handler'; import { GitScmProvider } from './git-scm-provider'; +import { GitFileChangeLabelProvider } from './git-file-change-label-provider'; export default new ContainerModule(bind => { bindGitPreferences(bind); @@ -75,4 +76,7 @@ export default new ContainerModule(bind => { bind(GitSyncService).toSelf().inSingletonScope(); bind(GitErrorHandler).toSelf().inSingletonScope(); + + bind(GitFileChangeLabelProvider).toSelf().inSingletonScope(); + bind(LabelProviderContribution).toService(GitFileChangeLabelProvider); }); diff --git a/packages/git/src/browser/git-navigable-list-widget.tsx b/packages/git/src/browser/git-navigable-list-widget.tsx index e28f3a4d5a0e8..8533904eb9c8c 100644 --- a/packages/git/src/browser/git-navigable-list-widget.tsx +++ b/packages/git/src/browser/git-navigable-list-widget.tsx @@ -15,7 +15,7 @@ ********************************************************************************/ import { SELECTED_CLASS, Key, Widget } from '@theia/core/lib/browser'; -import { GitFileStatus, Repository, GitFileChange } from '../common'; +import { GitFileStatus } from '../common'; import URI from '@theia/core/lib/common/uri'; import { GitRepositoryProvider } from './git-repository-provider'; import { LabelProvider } from '@theia/core/lib/browser/label-provider'; @@ -24,6 +24,8 @@ import { ElementExt } from '@phosphor/domutils'; import { inject, injectable } from 'inversify'; import { ReactWidget } from '@theia/core/lib/browser/widgets/react-widget'; import * as React from 'react'; +import { GitFileChangeLabelProvider } from './git-file-change-label-provider'; +import { GitFileChangeNode } from './git-file-change-node'; @injectable() export abstract class GitNavigableListWidget extends ReactWidget { @@ -33,6 +35,8 @@ export abstract class GitNavigableListWidget e @inject(GitRepositoryProvider) protected readonly repositoryProvider: GitRepositoryProvider; @inject(LabelProvider) protected readonly labelProvider: LabelProvider; + @inject(GitFileChangeLabelProvider) + protected readonly gitLabelProvider: GitFileChangeLabelProvider; constructor() { super(); @@ -74,38 +78,15 @@ export abstract class GitNavigableListWidget e this.update(); } - protected getStatusCaption(status: GitFileStatus, staged?: boolean): string { - return GitFileStatus.toString(status, staged); - } - protected getAbbreviatedStatusCaption(status: GitFileStatus, staged?: boolean): string { return GitFileStatus.toAbbreviation(status, staged); } - - protected relativePath(uri: URI | string): string { - const parsedUri = typeof uri === 'string' ? new URI(uri) : uri; - const repo = this.repositoryProvider.findRepository(parsedUri); - const relativePath = repo && Repository.relativePath(repo, parsedUri); - if (relativePath) { - return relativePath.toString(); - } - return this.labelProvider.getLongName(parsedUri); - } - protected getRepositoryLabel(uri: string): string | undefined { const repository = this.repositoryProvider.findRepository(new URI(uri)); const isSelectedRepo = this.repositoryProvider.selectedRepository && repository && this.repositoryProvider.selectedRepository.localUri === repository.localUri; return repository && !isSelectedRepo ? this.labelProvider.getLongName(new URI(repository.localUri)) : undefined; } - protected computeCaption(fileChange: GitFileChange): string { - let result = `${this.relativePath(fileChange.uri)} - ${this.getStatusCaption(fileChange.status, true)}`; - if (fileChange.oldUri) { - result = `${this.relativePath(fileChange.oldUri)} -> ${result}`; - } - return result; - } - protected renderHeaderRow({ name, value, classNames, title }: { name: string, value: React.ReactNode, classNames?: string[], title?: string }): React.ReactNode { if (!value) { return; @@ -181,3 +162,41 @@ export abstract class GitNavigableListWidget e return -1; } } + +export namespace GitItemComponent { + export interface Props { + labelProvider: LabelProvider; + gitLabelProvider: GitFileChangeLabelProvider; + change: GitFileChangeNode; + revealChange: (change: GitFileChangeNode) => void + selectNode: (change: GitFileChangeNode) => void + } +} +export class GitItemComponent extends React.Component { + + render(): JSX.Element { + const { labelProvider, gitLabelProvider, change } = this.props; + const icon = labelProvider.getIcon(change); + const label = labelProvider.getName(change); + const description = labelProvider.getLongName(change); + const caption = gitLabelProvider.getCaption(change); + const statusCaption = gitLabelProvider.getStatusCaption(change.status, true); + return
+ +
+ {label + ' '} + {description} +
+
+ {statusCaption.charAt(0)} +
+
; + } + + protected readonly revealChange = () => this.props.revealChange(this.props.change); + protected readonly selectNode = () => this.props.selectNode(this.props.change); +} diff --git a/packages/git/src/browser/git-repository-tracker.ts b/packages/git/src/browser/git-repository-tracker.ts index 5dd7933dbcf78..3c96e0cb5de8f 100644 --- a/packages/git/src/browser/git-repository-tracker.ts +++ b/packages/git/src/browser/git-repository-tracker.ts @@ -65,14 +65,11 @@ export class GitRepositoryTracker { } }, 50); - protected async setStatus(event: GitStatusChangeEvent | undefined, token: CancellationToken): Promise { + protected setStatus(event: GitStatusChangeEvent | undefined, token: CancellationToken): void { const status = event && event.status; const scmProvider = this.repositoryProvider.selectedScmProvider; if (scmProvider) { - await scmProvider.setStatus(status, token); - } - if (token.isCancellationRequested) { - return; + scmProvider.setStatus(status); } this.workingDirectoryStatus = status; this.onGitEventEmitter.fire(event); diff --git a/packages/git/src/browser/git-scm-provider.ts b/packages/git/src/browser/git-scm-provider.ts index a8ac340e6aa1b..db2a573e5f46e 100644 --- a/packages/git/src/browser/git-scm-provider.ts +++ b/packages/git/src/browser/git-scm-provider.ts @@ -18,10 +18,8 @@ import { injectable, inject, postConstruct, interfaces } from 'inversify'; import URI from '@theia/core/lib/common/uri'; import { DiffUris } from '@theia/core/lib/browser/diff-uris'; import { Emitter } from '@theia/core/lib/common/event'; -import { CancellationToken } from '@theia/core/lib/common/cancellation'; import { DisposableCollection } from '@theia/core/lib/common/disposable'; import { CommandService } from '@theia/core/lib/common/command'; -import { LabelProvider } from '@theia/core/lib/browser/label-provider'; import { ConfirmDialog } from '@theia/core/lib/browser/dialogs'; import { EditorOpenerOptions, EditorManager } from '@theia/editor/lib/browser/editor-manager'; import { FileSystem } from '@theia/filesystem/lib/common'; @@ -69,9 +67,6 @@ export class GitScmProvider implements ScmProvider { @inject(CommandService) protected readonly commands: CommandService; - @inject(LabelProvider) - protected readonly labelProvider: LabelProvider; - @inject(GitScmProviderOptions) protected readonly options: GitScmProviderOptions; @@ -134,7 +129,7 @@ export class GitScmProvider implements ScmProvider { getStatus(): WorkingDirectoryStatus | undefined { return this.state.status; } - async setStatus(status: WorkingDirectoryStatus | undefined, token: CancellationToken): Promise { + setStatus(status: WorkingDirectoryStatus | undefined): void { const state = GitScmProvider.initState(status); if (status) { for (const change of status.changes) { @@ -151,23 +146,14 @@ export class GitScmProvider implements ScmProvider { } } } - state.groups.push(await this.createGroup('merge', 'Merge Changes', state.mergeChanges, true)); - if (token.isCancellationRequested) { - return; - } - state.groups.push(await this.createGroup('index', 'Staged changes', state.stagedChanges, true)); - if (token.isCancellationRequested) { - return; - } - state.groups.push(await this.createGroup('workingTree', 'Changes', state.unstagedChanges, false)); - if (token.isCancellationRequested) { - return; - } + state.groups.push(this.createGroup('merge', 'Merge Changes', state.mergeChanges, true)); + state.groups.push(this.createGroup('index', 'Staged changes', state.stagedChanges, true)); + state.groups.push(this.createGroup('workingTree', 'Changes', state.unstagedChanges, false)); this.state = state; this.fireDidChange(); } - protected async createGroup(id: string, label: string, changes: GitFileChange[], hideWhenEmpty?: boolean): Promise { + protected createGroup(id: string, label: string, changes: GitFileChange[], hideWhenEmpty?: boolean): ScmResourceGroup { const group: ScmResourceGroup = { id, label, @@ -176,22 +162,18 @@ export class GitScmProvider implements ScmProvider { resources: [], dispose: () => { } }; - const creatingResources: Promise[] = []; for (const change of changes) { - creatingResources.push(this.addScmResource(group, change)); + this.addScmResource(group, change); } - await Promise.all(creatingResources); return group; } - protected async addScmResource(group: ScmResourceGroup, change: GitFileChange): Promise { + protected addScmResource(group: ScmResourceGroup, change: GitFileChange): void { const sourceUri = new URI(change.uri); - const icon = await this.labelProvider.getIcon(sourceUri); group.resources.push({ group, sourceUri, decorations: { - icon, letter: GitFileStatus.toAbbreviation(change.status, change.staged), color: GitFileStatus.getColor(change.status, change.staged), tooltip: GitFileStatus.toString(change.status) diff --git a/packages/git/src/browser/git-uri-label-contribution.ts b/packages/git/src/browser/git-uri-label-contribution.ts index aad6c49b1f032..8648af4f3a20f 100644 --- a/packages/git/src/browser/git-uri-label-contribution.ts +++ b/packages/git/src/browser/git-uri-label-contribution.ts @@ -15,10 +15,9 @@ ********************************************************************************/ import { injectable, inject } from 'inversify'; -import { LabelProviderContribution, LabelProvider } from '@theia/core/lib/browser/label-provider'; +import { LabelProviderContribution, LabelProvider, DidChangeLabelEvent } from '@theia/core/lib/browser/label-provider'; import URI from '@theia/core/lib/common/uri'; import { GIT_RESOURCE_SCHEME } from './git-resource'; -import { MaybePromise } from '@theia/core'; @injectable() export class GitUriLabelProviderContribution implements LabelProviderContribution { @@ -41,16 +40,13 @@ export class GitUriLabelProviderContribution implements LabelProviderContributio return this.labelProvider.getName(this.toFileUri(uri)) + this.getTagSuffix(uri); } - getIcon(uri: URI): MaybePromise { + getIcon(uri: URI): string { return this.labelProvider.getIcon(this.toFileUri(uri)); } - getConstituentUris(element: URI): URI[] { - const fileUri = this.toFileUri(element); - return [ - fileUri, - fileUri.withoutQuery().withoutFragment(), - ]; + affects(uri: URI, event: DidChangeLabelEvent): boolean { + const fileUri = this.toFileUri(uri); + return event.affects(fileUri) || event.affects(fileUri.withoutQuery().withoutFragment()); } protected toFileUri(uri: URI): URI { diff --git a/packages/git/src/browser/history/git-history-widget.tsx b/packages/git/src/browser/history/git-history-widget.tsx index 6052f7438bd93..ae19a65151baf 100644 --- a/packages/git/src/browser/history/git-history-widget.tsx +++ b/packages/git/src/browser/history/git-history-widget.tsx @@ -29,11 +29,10 @@ import { GitDiffContribution } from '../diff/git-diff-contribution'; import { ScmAvatarService } from '@theia/scm/lib/browser/scm-avatar-service'; import { GitCommitDetailUri, GitCommitDetailOpenerOptions, GitCommitDetailOpenHandler } from './git-commit-detail-open-handler'; import { GitCommitDetails } from './git-commit-detail-widget'; -import { GitNavigableListWidget } from '../git-navigable-list-widget'; +import { GitNavigableListWidget, GitItemComponent } from '../git-navigable-list-widget'; import { GitFileChangeNode } from '../git-file-change-node'; import * as React from 'react'; import { AlertMessage } from '@theia/core/lib/browser/widgets/alert-message'; -import { DidChangeLabelEvent } from '@theia/core/lib/browser/label-provider'; export interface GitCommitNode extends GitCommitDetails { fileChanges?: GitFileChange[]; @@ -92,26 +91,11 @@ export class GitHistoryWidget extends GitNavigableListWidget @postConstruct() protected init(): void { - this.toDispose.push(this.labelProvider.onDidChange(event => this.refreshLabels(event))); - } - - protected async refreshLabels(event: DidChangeLabelEvent): Promise { - let isAnyAffectedNodes = false; - for (let i = 0; i < this.gitNodes.length; i++) { - const gitNode = this.gitNodes[i]; - if (GitFileChangeNode.is(gitNode)) { - const uri = new URI(gitNode.uri); - if (event.affects(uri)) { - const label = this.labelProvider.getName(uri); - const icon = await this.labelProvider.getIcon(uri); - this.gitNodes[i] = { ...gitNode, label, icon }; - isAnyAffectedNodes = true; - } + this.toDispose.push(this.labelProvider.onDidChange(event => { + if (this.gitNodes.some(node => GitFileChangeNode.is(node) && event.affects(new URI(node.uri)))) { + this.update(); } - } - if (isAnyAffectedNodes) { - this.update(); - } + })); } protected onAfterAttach(msg: Message): void { @@ -229,18 +213,9 @@ export class GitHistoryWidget extends GitNavigableListWidget protected async addFileChangeNodes(commit: GitCommitNode, gitNodesArrayIndex: number): Promise { if (commit.fileChanges) { - const fileChangeNodes: GitFileChangeNode[] = []; - await Promise.all(commit.fileChanges.map(async fileChange => { - const fileChangeUri = new URI(fileChange.uri); - const icon = await this.labelProvider.getIcon(fileChangeUri); - const label = this.labelProvider.getName(fileChangeUri); - const description = this.relativePath(fileChangeUri.parent); - const caption = this.computeCaption(fileChange); - fileChangeNodes.push({ - ...fileChange, icon, label, description, caption, commitSha: commit.commitSha - }); - })); - this.gitNodes.splice(gitNodesArrayIndex + 1, 0, ...fileChangeNodes); + this.gitNodes.splice(gitNodesArrayIndex + 1, 0, ...commit.fileChanges.map(fileChange => + Object.assign(fileChange, { commitSha: commit.commitSha }) + )); } } @@ -287,7 +262,7 @@ export class GitHistoryWidget extends GitNavigableListWidget let reason: React.ReactNode; reason = this.status.errorMessage; if (this.options.uri) { - const relPathEncoded = this.relativePath(this.options.uri); + const relPathEncoded = this.gitLabelProvider.relativePath(this.options.uri); const relPath = relPathEncoded ? `${decodeURIComponent(relPathEncoded)}` : ''; const repo = this.repositoryProvider.findRepository(new URI(this.options.uri)); @@ -316,7 +291,7 @@ export class GitHistoryWidget extends GitNavigableListWidget protected renderHistoryHeader(): React.ReactNode { if (this.options.uri) { - const path = this.relativePath(this.options.uri); + const path = this.gitLabelProvider.relativePath(this.options.uri); const fileName = path.split('/').pop(); return
{ @@ -440,32 +415,13 @@ export class GitHistoryWidget extends GitNavigableListWidget } protected renderGitItem(change: GitFileChangeNode, commitSha: string): React.ReactNode { - return
-
{ - this.openFile(change, commitSha); - }} - onClick={() => { - this.selectNode(change); - }}> - - {change.label + ' '} - {change.description} -
- { - change.extraIconClassName ?
- : '' - } -
- {this.getStatusCaption(change.status, true).charAt(0)} -
-
; + return this.openFile(change, commitSha), + selectNode: () => this.selectNode(change) + }} />; } protected navigateLeft(): void { diff --git a/packages/git/src/browser/style/index.css b/packages/git/src/browser/style/index.css index 4efa3e0da41f0..ee4cb3ac7861c 100644 --- a/packages/git/src/browser/style/index.css +++ b/packages/git/src/browser/style/index.css @@ -39,11 +39,15 @@ } .theia-git .gitItem { - margin: 1px 0 1px 3px; - padding: 2px; font-size: var(--theia-ui-font-size1); - display: flex; + display: inline-flex; justify-content: space-between; + align-items: center; + width: 100%; + height: var(--theia-content-line-height); + line-height: var(--theia-content-line-height); + padding: 0px; + padding-right: var(--theia-ui-padding); } .theia-git .gitItem .file-icon { diff --git a/packages/java/src/browser/java-label-provider.ts b/packages/java/src/browser/java-label-provider.ts index 86fb99228aeba..f113226cc4f79 100644 --- a/packages/java/src/browser/java-label-provider.ts +++ b/packages/java/src/browser/java-label-provider.ts @@ -17,7 +17,6 @@ import { LabelProviderContribution } from '@theia/core/lib/browser/label-provider'; import URI from '@theia/core/lib/common/uri'; import { JAVA_SCHEME } from '../common/index'; -import { MaybePromise } from '@theia/core/lib/common'; import { injectable } from 'inversify'; @injectable() @@ -34,7 +33,7 @@ export class JavaLabelProviderContribution implements LabelProviderContribution /** * returns an icon class for the given element. */ - getIcon(element: URI): MaybePromise { + getIcon(element: URI): string { return 'java-icon'; } diff --git a/packages/keymaps/src/browser/style/index.css b/packages/keymaps/src/browser/style/index.css index 76145db074a4f..ca8eb2f9c319f 100644 --- a/packages/keymaps/src/browser/style/index.css +++ b/packages/keymaps/src/browser/style/index.css @@ -49,7 +49,7 @@ } .kb table tr { - min-height: 16px; + min-height: var(--theia-icon-size); } .th-action, .th-keybinding, diff --git a/packages/markers/src/browser/marker-tree-label-provider.ts b/packages/markers/src/browser/marker-tree-label-provider.ts new file mode 100644 index 0000000000000..f51e69c8dad43 --- /dev/null +++ b/packages/markers/src/browser/marker-tree-label-provider.ts @@ -0,0 +1,53 @@ +/******************************************************************************** + * Copyright (C) 2019 TypeFox 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, inject } from 'inversify'; +import { LabelProvider, LabelProviderContribution, DidChangeLabelEvent } from '@theia/core/lib/browser/label-provider'; +import { MarkerInfoNode } from './marker-tree'; +import { TreeLabelProvider } from '@theia/core/lib/browser/tree/tree-label-provider'; + +@injectable() +export class MarkerTreeLabelProvider implements LabelProviderContribution { + + @inject(LabelProvider) + protected readonly labelProvider: LabelProvider; + + @inject(TreeLabelProvider) + protected readonly treeLabelProvider: TreeLabelProvider; + + canHandle(element: object): number { + return MarkerInfoNode.is(element) ? + this.treeLabelProvider.canHandle(element) + 1 : + 0; + } + + getIcon(node: MarkerInfoNode): string { + return this.labelProvider.getIcon(node.uri); + } + + getName(node: MarkerInfoNode): string { + return this.labelProvider.getName(node.uri); + } + + getDescription(node: MarkerInfoNode): string { + return this.labelProvider.getLongName(node.uri.parent); + } + + affects(node: MarkerInfoNode, event: DidChangeLabelEvent): boolean { + return event.affects(node.uri) || event.affects(node.uri.parent); + } + +} diff --git a/packages/markers/src/browser/marker-tree.ts b/packages/markers/src/browser/marker-tree.ts index 96e3727d7228d..a2deb11de3ba1 100644 --- a/packages/markers/src/browser/marker-tree.ts +++ b/packages/markers/src/browser/marker-tree.ts @@ -20,7 +20,6 @@ import { MarkerManager } from './marker-manager'; import { Marker } from '../common/marker'; import { UriSelection } from '@theia/core/lib/common/selection'; import URI from '@theia/core/lib/common/uri'; -import { LabelProvider } from '@theia/core/lib/browser/label-provider'; import { ProblemSelection } from './problem/problem-selection'; export const MarkerOptions = Symbol('MarkerOptions'); @@ -33,30 +32,11 @@ export abstract class MarkerTree extends TreeImpl { constructor( protected readonly markerManager: MarkerManager, - protected readonly markerOptions: MarkerOptions, - protected readonly labelProvider: LabelProvider + protected readonly markerOptions: MarkerOptions ) { super(); this.toDispose.push(markerManager.onDidChangeMarkers(uri => this.refreshMarkerInfo(uri))); - this.toDispose.push(labelProvider.onDidChange(async event => { - let isAnyAffectedNodes = false; - for (const nodeId of Object.keys(this.nodes)) { - const node = this.nodes[nodeId]; - const markerInfoNode = node; - if (node && MarkerInfoNode.is(markerInfoNode)) { - const uri = markerInfoNode.uri; - if (event.affects(uri)) { - node.name = this.labelProvider.getName(uri); - node.icon = await this.labelProvider.getIcon(uri); - isAnyAffectedNodes = true; - } - } - } - if (isAnyAffectedNodes) { - this.fireChanged(); - } - })); this.root = { visible: false, @@ -80,7 +60,7 @@ export abstract class MarkerTree extends TreeImpl { } return; } - const node = MarkerInfoNode.is(existing) ? existing : await this.createMarkerInfo(id, uri); + const node = MarkerInfoNode.is(existing) ? existing : this.createMarkerInfo(id, uri); CompositeTreeNode.addChild(node.parent, node); const children = this.getMarkerNodes(node, markers); node.numberOfMarkers = markers.length; @@ -94,7 +74,7 @@ export abstract class MarkerTree extends TreeImpl { const uri = new URI(id); const existing = this.getNode(id); const markers = this.markerManager.findMarkers({ uri }); - const node = MarkerInfoNode.is(existing) ? existing : await this.createMarkerInfo(id, uri); + const node = MarkerInfoNode.is(existing) ? existing : this.createMarkerInfo(id, uri); node.children = this.getMarkerNodes(node, markers); node.numberOfMarkers = node.children.length; nodes.push(node); @@ -104,18 +84,12 @@ export abstract class MarkerTree extends TreeImpl { return super.resolveChildren(parent); } - protected async createMarkerInfo(id: string, uri: URI): Promise { - const label = await this.labelProvider.getName(uri); - const icon = await this.labelProvider.getIcon(uri); - const description = await this.labelProvider.getLongName(uri.parent); + protected createMarkerInfo(id: string, uri: URI): MarkerInfoNode { return { children: [], expanded: true, uri, id, - name: label, - icon, - description, parent: this.root as MarkerRootNode, selected: false, numberOfMarkers: 0 @@ -159,8 +133,8 @@ export interface MarkerInfoNode extends UriSelection, SelectableTreeNode, Expand numberOfMarkers: number; } export namespace MarkerInfoNode { - export function is(node: TreeNode | undefined): node is MarkerInfoNode { - return ExpandableTreeNode.is(node) && UriSelection.is(node); + export function is(node: Object | undefined): node is MarkerInfoNode { + return ExpandableTreeNode.is(node) && UriSelection.is(node) && 'numberOfMarkers' in node; } } diff --git a/packages/markers/src/browser/problem/problem-frontend-module.ts b/packages/markers/src/browser/problem/problem-frontend-module.ts index 788460e88e911..f846723f30166 100644 --- a/packages/markers/src/browser/problem/problem-frontend-module.ts +++ b/packages/markers/src/browser/problem/problem-frontend-module.ts @@ -20,7 +20,7 @@ import { ContainerModule } from 'inversify'; import { ProblemWidget, PROBLEMS_WIDGET_ID } from './problem-widget'; import { ProblemContribution } from './problem-contribution'; import { createProblemWidget } from './problem-container'; -import { FrontendApplicationContribution, bindViewContribution, ApplicationShellLayoutMigration } from '@theia/core/lib/browser'; +import { FrontendApplicationContribution, bindViewContribution, ApplicationShellLayoutMigration, LabelProviderContribution } from '@theia/core/lib/browser'; import { ProblemManager } from './problem-manager'; import { WidgetFactory } from '@theia/core/lib/browser/widget-manager'; import { NavigatorTreeDecorator } from '@theia/navigator/lib/browser/navigator-decorator-service'; @@ -30,6 +30,7 @@ import { TabBarToolbarContribution } from '@theia/core/lib/browser/shell/tab-bar import { ProblemLayoutVersion3Migration } from './problem-layout-migrations'; import { TabBarDecorator } from '@theia/core/lib/browser/shell/tab-bar-decorator'; import { bindProblemPreferences } from './problem-preferences'; +import { MarkerTreeLabelProvider } from '../marker-tree-label-provider'; export default new ContainerModule(bind => { bindProblemPreferences(bind); @@ -53,4 +54,7 @@ export default new ContainerModule(bind => { bind(NavigatorTreeDecorator).toService(ProblemDecorator); bind(ProblemTabBarDecorator).toSelf().inSingletonScope(); bind(TabBarDecorator).toService(ProblemTabBarDecorator); + + bind(MarkerTreeLabelProvider).toSelf().inSingletonScope(); + bind(LabelProviderContribution).toService(MarkerTreeLabelProvider); }); diff --git a/packages/markers/src/browser/problem/problem-tree-model.ts b/packages/markers/src/browser/problem/problem-tree-model.ts index 92d8aea3a95c9..acb153504a8a3 100644 --- a/packages/markers/src/browser/problem/problem-tree-model.ts +++ b/packages/markers/src/browser/problem/problem-tree-model.ts @@ -21,15 +21,13 @@ import { MarkerTreeModel } from '../marker-tree-model'; import { injectable, inject } from 'inversify'; import { OpenerOptions, TreeNode } from '@theia/core/lib/browser'; import { Diagnostic } from 'vscode-languageserver-types'; -import { LabelProvider } from '@theia/core/lib/browser/label-provider'; @injectable() export class ProblemTree extends MarkerTree { constructor( @inject(ProblemManager) protected readonly problemManager: ProblemManager, - @inject(MarkerOptions) protected readonly markerOptions: MarkerOptions, - @inject(LabelProvider) protected readonly labelProvider: LabelProvider) { - super(problemManager, markerOptions, labelProvider); + @inject(MarkerOptions) protected readonly markerOptions: MarkerOptions) { + super(problemManager, markerOptions); } } diff --git a/packages/markers/src/browser/problem/problem-widget.tsx b/packages/markers/src/browser/problem/problem-widget.tsx index b5f9ff25c41e3..9fa4e1d75c37b 100644 --- a/packages/markers/src/browser/problem/problem-widget.tsx +++ b/packages/markers/src/browser/problem/problem-widget.tsx @@ -157,10 +157,13 @@ export class ProblemWidget extends TreeWidget { } protected decorateMarkerFileNode(node: MarkerInfoNode): React.ReactNode { + const icon = this.toNodeIcon(node); + const name = this.toNodeName(node); + const description = this.toNodeDescription(node); return
-
-
{node.name}
-
{node.description || ''}
+ {icon &&
} +
{name}
+
{description}
{node.numberOfMarkers.toString()}
diff --git a/packages/mini-browser/src/browser/mini-browser-open-handler.ts b/packages/mini-browser/src/browser/mini-browser-open-handler.ts index 73f1868670628..be664c324116d 100644 --- a/packages/mini-browser/src/browser/mini-browser-open-handler.ts +++ b/packages/mini-browser/src/browser/mini-browser-open-handler.ts @@ -134,7 +134,7 @@ export class MiniBrowserOpenHandler extends NavigatableWidgetOpenHandler this.refresh())); } @@ -52,7 +51,7 @@ export class FileNavigatorTree extends FileTree { } async createWorkspaceRoot(rootFolder: FileStat, workspaceNode: WorkspaceNode): Promise { - const node = (await this.toNode(rootFolder, workspaceNode)) as WorkspaceRootNode; + const node = this.toNode(rootFolder, workspaceNode) as WorkspaceRootNode; Object.assign(node, { visible: workspaceNode.name !== WorkspaceNode.name, }); @@ -87,7 +86,7 @@ export interface WorkspaceRootNode extends DirNode { parent: WorkspaceNode; } export namespace WorkspaceRootNode { - export function is(node: TreeNode | undefined): node is WorkspaceRootNode { + export function is(node: Object | undefined): node is WorkspaceRootNode { return DirNode.is(node) && WorkspaceNode.is(node.parent); } diff --git a/packages/navigator/src/browser/navigator-widget.tsx b/packages/navigator/src/browser/navigator-widget.tsx index 9c04da1145523..99af46bf95e98 100644 --- a/packages/navigator/src/browser/navigator-widget.tsx +++ b/packages/navigator/src/browser/navigator-widget.tsx @@ -18,7 +18,7 @@ import { injectable, inject, postConstruct } from 'inversify'; import { Message } from '@phosphor/messaging'; import URI from '@theia/core/lib/common/uri'; import { CommandService, SelectionService } from '@theia/core/lib/common'; -import { CommonCommands, CorePreferences, LabelProvider, ViewContainerTitleOptions, Key } from '@theia/core/lib/browser'; +import { CommonCommands, CorePreferences, ViewContainerTitleOptions, Key } from '@theia/core/lib/browser'; import { ContextMenuRenderer, ExpandableTreeNode, TreeProps, TreeModel, TreeNode @@ -49,8 +49,6 @@ export class FileNavigatorWidget extends FileTreeWidget { @inject(CorePreferences) protected readonly corePreferences: CorePreferences; - @inject(LabelProvider) protected readonly labelProvider: LabelProvider; - @inject(NavigatorContextKeyService) protected readonly contextKeyService: NavigatorContextKeyService; @@ -96,11 +94,11 @@ export class FileNavigatorWidget extends FileTreeWidget { if (this.model.root.name === WorkspaceNode.name) { const rootNode = this.model.root.children[0]; if (WorkspaceRootNode.is(rootNode)) { - this.title.label = rootNode.name; + this.title.label = this.toNodeName(rootNode); this.title.caption = this.labelProvider.getLongName(rootNode.uri); } } else { - this.title.label = this.model.root.name; + this.title.label = this.toNodeName(this.model.root); this.title.caption = this.title.label; } } else { diff --git a/packages/plugin-dev/src/browser/hosted-plugin-manager-client.ts b/packages/plugin-dev/src/browser/hosted-plugin-manager-client.ts index 023e461b68205..e1cf1ea06967d 100644 --- a/packages/plugin-dev/src/browser/hosted-plugin-manager-client.ts +++ b/packages/plugin-dev/src/browser/hosted-plugin-manager-client.ts @@ -262,9 +262,7 @@ export class HostedPluginManagerClient { throw new Error('Unable to find the root'); } - const name = this.labelProvider.getName(workspaceFolder); - const label = await this.labelProvider.getIcon(workspaceFolder); - const rootNode = DirNode.createRoot(workspaceFolder, name, label); + const rootNode = DirNode.createRoot(workspaceFolder); const dialog = this.openFileDialogFactory({ title: HostedPluginCommands.SELECT_PATH.label!, diff --git a/packages/plugin-ext/src/common/plugin-api-rpc.ts b/packages/plugin-ext/src/common/plugin-api-rpc.ts index a76ef57fc5ebd..398e40294a6fb 100644 --- a/packages/plugin-ext/src/common/plugin-api-rpc.ts +++ b/packages/plugin-ext/src/common/plugin-api-rpc.ts @@ -527,7 +527,7 @@ export interface TreeViewItem { label: string; - description?: string; + description?: string | boolean; /* font-awesome icon for compatibility */ icon?: string; diff --git a/packages/plugin-ext/src/common/plugin-protocol.ts b/packages/plugin-ext/src/common/plugin-protocol.ts index 94f9d0f941a15..226d5b0ace56c 100644 --- a/packages/plugin-ext/src/common/plugin-protocol.ts +++ b/packages/plugin-ext/src/common/plugin-protocol.ts @@ -78,6 +78,7 @@ export interface PluginPackageContribution { debuggers?: PluginPackageDebuggersContribution[]; snippets: PluginPackageSnippetsContribution[]; themes?: PluginThemeContribution[]; + iconThemes?: PluginIconThemeContribution[]; colors?: PluginColorContribution[]; taskDefinitions?: PluginTaskDefinitionContribution[]; problemMatchers?: PluginProblemMatcherContribution[]; @@ -143,12 +144,22 @@ export interface PluginColorContribution { defaults?: { light?: string, dark?: string, highContrast?: string }; } +export type PluginUiTheme = 'vs' | 'vs-dark' | 'hc-black'; + export interface PluginThemeContribution { id?: string; label?: string; description?: string; path?: string; - uiTheme?: 'vs' | 'vs-dark' | 'hc-black'; + uiTheme?: PluginUiTheme; +} + +export interface PluginIconThemeContribution { + id?: string; + label?: string; + description?: string; + path?: string; + uiTheme?: PluginUiTheme; } export interface PlatformSpecificAdapterContribution { @@ -426,6 +437,7 @@ export interface PluginContribution { debuggers?: DebuggerContribution[]; snippets?: SnippetContribution[]; themes?: ThemeContribution[]; + iconThemes?: IconThemeContribution[]; colors?: ColorDefinition[]; taskDefinitions?: TaskDefinition[]; problemMatchers?: ProblemMatcherContribution[]; @@ -438,12 +450,22 @@ export interface SnippetContribution { language?: string } +export type UiTheme = 'vs' | 'vs-dark' | 'hc-black'; + export interface ThemeContribution { id?: string; label?: string; description?: string; uri: string; - uiTheme?: 'vs' | 'vs-dark' | 'hc-black'; + uiTheme?: UiTheme; +} + +export interface IconThemeContribution { + id: string; + label?: string; + description?: string; + uri: string; + uiTheme?: UiTheme; } export interface GrammarsContribution { 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 f4302c85fd8e7..09a88f5c6667d 100644 --- a/packages/plugin-ext/src/hosted/node/scanners/scanner-theia.ts +++ b/packages/plugin-ext/src/hosted/node/scanners/scanner-theia.ts @@ -44,7 +44,8 @@ import { PluginPackageCommand, PluginCommand, IconUrl, - ThemeContribution + ThemeContribution, + IconThemeContribution } from '../../../common/plugin-protocol'; import * as fs from 'fs'; import * as path from 'path'; @@ -282,6 +283,12 @@ export class TheiaPluginScanner implements PluginScanner { console.error(`Could not read '${rawPlugin.name}' contribution 'themes'.`, rawPlugin.contributes.themes, err); } + try { + contributions.iconThemes = this.readIconThemes(rawPlugin); + } catch (err) { + console.error(`Could not read '${rawPlugin.name}' contribution 'iconThemes'.`, rawPlugin.contributes.iconThemes, err); + } + try { contributions.colors = this.readColors(rawPlugin); } catch (err) { @@ -364,6 +371,31 @@ export class TheiaPluginScanner implements PluginScanner { return result; } + protected readIconThemes(pck: PluginPackage): IconThemeContribution[] | undefined { + if (!pck.contributes || !pck.contributes.iconThemes) { + return undefined; + } + const result: IconThemeContribution[] = []; + for (const contribution of pck.contributes.iconThemes) { + if (typeof contribution.id !== 'string') { + console.error('Expected string in `contributes.iconThemes.id`. Provided value:', contribution.id); + continue; + } + if (typeof contribution.path !== 'string') { + console.error('Expected string in `contributes.iconThemes.path`. Provided value:', contribution.path); + continue; + } + result.push({ + id: contribution.id, + uri: FileUri.create(path.join(pck.packagePath, contribution.path)).toString(), + description: contribution.description, + label: contribution.label, + uiTheme: contribution.uiTheme + }); + } + 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/dialogs-main.ts b/packages/plugin-ext/src/main/browser/dialogs-main.ts index 4d69dba8a3e5b..3acbee37bdb5e 100644 --- a/packages/plugin-ext/src/main/browser/dialogs-main.ts +++ b/packages/plugin-ext/src/main/browser/dialogs-main.ts @@ -17,11 +17,9 @@ import { interfaces } from 'inversify'; import { RPCProtocol } from '../../common/rpc-protocol'; import { OpenDialogOptionsMain, SaveDialogOptionsMain, DialogsMain, UploadDialogOptionsMain } from '../../common/plugin-api-rpc'; -import URI from '@theia/core/lib/common/uri'; import { DirNode, OpenFileDialogProps, SaveFileDialogProps, OpenFileDialogFactory, SaveFileDialogFactory } from '@theia/filesystem/lib/browser'; import { WorkspaceService } from '@theia/workspace/lib/browser'; import { FileSystem, FileStat } from '@theia/filesystem/lib/common'; -import { LabelProvider } from '@theia/core/lib/browser'; import { UriSelection } from '@theia/core/lib/common/selection'; import { FileUploadService } from '@theia/filesystem/lib/browser/file-upload-service'; @@ -29,7 +27,6 @@ export class DialogsMainImpl implements DialogsMain { private workspaceService: WorkspaceService; private fileSystem: FileSystem; - private labelProvider: LabelProvider; private openFileDialogFactory: OpenFileDialogFactory; private saveFileDialogFactory: SaveFileDialogFactory; @@ -38,7 +35,6 @@ export class DialogsMainImpl implements DialogsMain { constructor(rpc: RPCProtocol, container: interfaces.Container) { this.workspaceService = container.get(WorkspaceService); this.fileSystem = container.get(FileSystem); - this.labelProvider = container.get(LabelProvider); this.openFileDialogFactory = container.get(OpenFileDialogFactory); this.saveFileDialogFactory = container.get(SaveFileDialogFactory); @@ -75,10 +71,7 @@ export class DialogsMainImpl implements DialogsMain { } // Take the info for root node - const rootUri = new URI(rootStat.uri); - const name = this.labelProvider.getName(rootUri); - const icon = await this.labelProvider.getIcon(rootUri); - const rootNode = DirNode.createRoot(rootStat, name, icon); + const rootNode = DirNode.createRoot(rootStat); try { // Determine proper title for the dialog @@ -133,10 +126,7 @@ export class DialogsMainImpl implements DialogsMain { } // Take the info for root node - const rootUri = new URI(rootStat.uri); - const name = this.labelProvider.getName(rootUri); - const icon = await this.labelProvider.getIcon(rootUri); - const rootNode = DirNode.createRoot(rootStat, name, icon); + const rootNode = DirNode.createRoot(rootStat); try { // Create save file dialog props 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 c43e8b8cf9c01..23bad9fb16bb0 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 { 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 { PluginIconThemeService } from './plugin-icon-theme-service'; @injectable() export class PluginContributionHandler { @@ -87,6 +88,9 @@ export class PluginContributionHandler { @inject(ColorRegistry) protected readonly colors: ColorRegistry; + @inject(PluginIconThemeService) + protected readonly iconThemeService: PluginIconThemeService; + protected readonly commandHandlers = new Map(); protected readonly onDidRegisterCommandHandlerEmitter = new Emitter(); @@ -245,6 +249,12 @@ export class PluginContributionHandler { } } + if (contributions.iconThemes && contributions.iconThemes.length) { + for (const iconTheme of contributions.iconThemes) { + pushContribution(`iconThemes.${iconTheme.uri}`, () => this.iconThemeService.register(iconTheme, plugin)); + } + } + if (contributions.colors) { pushContribution('colors', () => this.colors.register(...contributions.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 ca0daed42b0e6..499866465a556 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 @@ -20,7 +20,7 @@ import '../../../src/main/browser/style/index.css'; import { ContainerModule } from 'inversify'; import { FrontendApplicationContribution, FrontendApplication, WidgetFactory, bindViewContribution, - ViewContainerIdentifier, ViewContainer, createTreeContainer, TreeImpl, TreeWidget, TreeModelImpl, OpenHandler + ViewContainerIdentifier, ViewContainer, createTreeContainer, TreeImpl, TreeWidget, TreeModelImpl, OpenHandler, LabelProviderContribution } from '@theia/core/lib/browser'; import { MaybePromise, CommandContribution, ResourceResolver, bindContributionProvider } from '@theia/core/lib/common'; import { WebSocketConnectionProvider } from '@theia/core/lib/browser/messaging'; @@ -70,6 +70,8 @@ import { PluginCommandOpenHandler } from './plugin-command-open-handler'; import { bindWebviewPreferences } from './webview/webview-preferences'; import { WebviewResourceLoader, WebviewResourceLoaderPath } from '../common/webview-protocol'; import { WebviewResourceCache } from './webview/webview-resource-cache'; +import { PluginIconThemeService, PluginIconThemeFactory, PluginIconThemeDefinition, PluginIconTheme } from './plugin-icon-theme-service'; +import { PluginTreeViewNodeLabelProvider } from './view/plugin-tree-view-node-label-provider'; export default new ContainerModule((bind, unbind, isBound, rebind) => { @@ -135,6 +137,8 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { bind(ViewContextKeyService).toSelf().inSingletonScope(); + bind(PluginTreeViewNodeLabelProvider).toSelf().inSingletonScope(); + bind(LabelProviderContribution).toService(PluginTreeViewNodeLabelProvider); bind(WidgetFactory).toDynamicValue(({ container }) => ({ id: PLUGIN_VIEW_DATA_FACTORY_ID, createWidget: (identifier: TreeViewWidgetIdentifier) => { @@ -198,10 +202,18 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { bind(PluginSharedStyle).toSelf().inSingletonScope(); bind(PluginViewRegistry).toSelf().inSingletonScope(); bind(FrontendApplicationContribution).toService(PluginViewRegistry); - bind(MenusContributionPointHandler).toSelf().inSingletonScope(); - bind(KeybindingsContributionPointHandler).toSelf().inSingletonScope(); + bind(PluginIconThemeFactory).toFactory(({ container }) => (definition: PluginIconThemeDefinition) => { + const child = container.createChild(); + child.bind(PluginIconThemeDefinition).toConstantValue(definition); + child.bind(PluginIconTheme).toSelf().inSingletonScope(); + return child.get(PluginIconTheme); + }); + bind(PluginIconThemeService).toSelf().inSingletonScope(); + bind(LabelProviderContribution).toService(PluginIconThemeService); + bind(MenusContributionPointHandler).toSelf().inSingletonScope(); + bind(KeybindingsContributionPointHandler).toSelf().inSingletonScope(); bind(PluginContributionHandler).toSelf().inSingletonScope(); bind(InPluginFileSystemWatcherManager).toSelf().inSingletonScope(); diff --git a/packages/plugin-ext/src/main/browser/plugin-icon-theme-service.ts b/packages/plugin-ext/src/main/browser/plugin-icon-theme-service.ts new file mode 100644 index 0000000000000..fd4c71b9130f2 --- /dev/null +++ b/packages/plugin-ext/src/main/browser/plugin-icon-theme-service.ts @@ -0,0 +1,571 @@ +/******************************************************************************** + * Copyright (C) 2019 TypeFox 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 + ********************************************************************************/ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// some code is copied and modified from: +// https://github.com/microsoft/vscode/blob/7cf4cca47aa025a590fc939af54932042302be63/src/vs/workbench/services/themes/browser/fileIconThemeData.ts + +import debounce = require('lodash.debounce'); +import * as jsoncparser from 'jsonc-parser'; +import { injectable, inject, postConstruct } from 'inversify'; +import { FileSystem, FileStat } from '@theia/filesystem/lib/common'; +import { IconThemeService, IconTheme, IconThemeDefinition } from '@theia/core/lib/browser/icon-theme-service'; +import { IconThemeContribution, DeployedPlugin, UiTheme, getPluginId } from '../../common/plugin-protocol'; +import URI from '@theia/core/lib/common/uri'; +import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable'; +import { Emitter } from '@theia/core/lib/common/event'; +import { RecursivePartial } from '@theia/core/lib/common/types'; +import { LabelProviderContribution, DidChangeLabelEvent, LabelProvider } from '@theia/core/lib/browser/label-provider'; +import { ThemeType } from '@theia/core/lib/browser/theming'; +import { FileStatNode, DirNode, FileSystemWatcher, FileChangeEvent } from '@theia/filesystem/lib/browser'; +import { WorkspaceRootNode } from '@theia/navigator/lib/browser/navigator-tree'; + +export interface PluginIconDefinition { + iconPath: string; + fontColor: string; + fontCharacter: string; + fontSize: string; + fontId: string; +} + +export interface PluginFontDefinition { + id: string; + weight: string; + style: string; + size: string; + src: { path: string; format: string; }[]; +} + +export interface PluginIconsAssociation { + folder?: string; + file?: string; + folderExpanded?: string; + rootFolder?: string; + rootFolderExpanded?: string; + folderNames?: { [folderName: string]: string; }; + folderNamesExpanded?: { [folderName: string]: string; }; + fileExtensions?: { [extension: string]: string; }; + fileNames?: { [fileName: string]: string; }; + languageIds?: { [languageId: string]: string; }; +} + +export interface PluginIconDefinitions { + [key: string]: PluginIconDefinition +} + +export interface PluginIconThemeDocument extends PluginIconsAssociation { + iconDefinitions: PluginIconDefinitions; + fonts: PluginFontDefinition[]; + light?: PluginIconsAssociation; + highContrast?: PluginIconsAssociation; + hidesExplorerArrows?: boolean; +} + +export const PluginIconThemeFactory = Symbol('PluginIconThemeFactory'); +export type PluginIconThemeFactory = (definition: PluginIconThemeDefinition) => PluginIconTheme; + +@injectable() +export class PluginIconThemeDefinition implements IconThemeDefinition, IconThemeContribution { + id: string; + label: string; + description?: string; + uri: string; + uiTheme?: UiTheme; + pluginId: string; + packagePath: string; + hasFileIcons?: boolean; + hasFolderIcons?: boolean; + hidesExplorerArrows?: boolean; +} + +@injectable() +export class PluginIconTheme extends PluginIconThemeDefinition implements IconTheme, Disposable { + + @inject(FileSystem) + protected readonly fileSystem: FileSystem; + + @inject(FileSystemWatcher) + protected readonly fsWatcher: FileSystemWatcher; + + @inject(LabelProvider) + protected readonly labelProvider: LabelProvider; + + @inject(PluginIconThemeDefinition) + protected readonly definition: PluginIconThemeDefinition; + + protected readonly onDidChangeEmitter = new Emitter(); + readonly onDidChange = this.onDidChangeEmitter.event; + + protected readonly toDeactivate = new DisposableCollection(); + protected readonly toUnload = new DisposableCollection(); + protected readonly toDisposeStyleElement = new DisposableCollection(); + protected readonly toDispose = new DisposableCollection( + this.toDeactivate, this.toDisposeStyleElement, this.toUnload, this.onDidChangeEmitter + ); + + protected packageUri: URI; + protected locationUri: URI; + + protected styleSheetContent: string | undefined; + protected readonly icons = new Set(); + + @postConstruct() + protected init(): void { + Object.assign(this, this.definition); + this.packageUri = new URI(this.packagePath); + this.locationUri = new URI(this.uri).parent; + } + + dispose(): void { + this.toDispose.dispose(); + } + + protected fireDidChange(): void { + this.onDidChangeEmitter.fire({ affects: () => true }); + } + + activate(): Disposable { + if (!this.toDeactivate.disposed) { + return this.toDeactivate; + } + this.toDeactivate.push(Disposable.create(() => this.fireDidChange())); + this.doActivate(); + return this.toDeactivate; + } + + protected async doActivate(): Promise { + await this.load(); + this.updateStyleElement(); + } + + protected updateStyleElement(): void { + this.toDisposeStyleElement.dispose(); + if (this.toDeactivate.disposed || !this.styleSheetContent) { + return; + } + const styleElement = document.createElement('style'); + styleElement.type = 'text/css'; + styleElement.className = 'theia-icon-theme'; + styleElement.innerHTML = this.styleSheetContent; + document.head.appendChild(styleElement); + const toRemoveStyleElement = Disposable.create(() => styleElement.remove()); + this.toDisposeStyleElement.push(toRemoveStyleElement); + this.toDeactivate.push(toRemoveStyleElement); + this.fireDidChange(); + } + + protected reload = debounce(() => { + this.toUnload.dispose(); + this.doActivate(); + }, 50); + + /** + * This should be aligned with + * https://github.com/microsoft/vscode/blob/7cf4cca47aa025a590fc939af54932042302be63/src/vs/workbench/services/themes/browser/fileIconThemeData.ts#L201 + */ + protected async load(): Promise { + if (this.styleSheetContent !== undefined) { + return; + } + this.styleSheetContent = ''; + this.toUnload.push(Disposable.create(() => { + this.styleSheetContent = undefined; + this.hasFileIcons = undefined; + this.hasFolderIcons = undefined; + this.hidesExplorerArrows = undefined; + this.icons.clear(); + })); + + const { content } = await this.fileSystem.resolveContent(this.uri); + const json: RecursivePartial = jsoncparser.parse(content, undefined, { disallowComments: false }); + this.hidesExplorerArrows = !!json.hidesExplorerArrows; + + const uri = new URI(this.uri); + const toUnwatch = await this.fsWatcher.watchFileChanges(uri); + if (this.toUnload.disposed) { + toUnwatch.dispose(); + } else { + this.toUnload.push(toUnwatch); + this.toUnload.push(this.fsWatcher.onFilesChanged(e => { + if (FileChangeEvent.isChanged(e, uri)) { + this.reload(); + } + })); + } + + const iconDefinitions = json.iconDefinitions; + if (!iconDefinitions) { + return; + } + const definitionSelectors = new Map(); + const acceptSelector = (themeType: ThemeType, definitionId: string, ...icons: string[]) => { + if (!iconDefinitions[definitionId]) { + return; + } + let selector = ''; + for (const icon of icons) { + if (icon) { + selector += '.' + icon; + this.icons.add(icon); + } + } + if (!selector) { + return; + } + const selectors = definitionSelectors.get(definitionId) || []; + if (themeType !== 'dark') { + selector = '.theia-' + themeType + ' ' + selector; + } + selectors.push(selector); + selectors.push(selector + '::before'); + definitionSelectors.set(definitionId, selectors); + }; + this.collectSelectors(json, acceptSelector.bind(undefined, 'dark')); + if (json.light) { + this.collectSelectors(json.light, acceptSelector.bind(undefined, 'light')); + } + if (json.highContrast) { + this.collectSelectors(json.highContrast, acceptSelector.bind(undefined, 'hc')); + } + + if (!this.icons.size) { + return; + } + + const fonts = json.fonts; + if (Array.isArray(fonts)) { + for (const font of fonts) { + if (font) { + let src = ''; + if (Array.isArray(font.src)) { + for (const srcLocation of font.src) { + if (srcLocation && srcLocation.path) { + const cssUrl = this.toCSSUrl(srcLocation.path); + if (cssUrl) { + if (src) { + src += ', '; + } + src += `${cssUrl} format('${srcLocation.format}')`; + } + } + } + } + if (src) { + this.styleSheetContent += `@font-face { + src: ${src}; + font-family: '${font.id}'; + font-weight: ${font.weight}; + font-style: ${font.style}; +} +`; + } + } + } + const firstFont = fonts[0]; + if (firstFont && firstFont.id) { + this.styleSheetContent += `.${this.fileIcon}::before, .${this.folderIcon}::before, .${this.rootFolderIcon}::before { + font-family: '${firstFont.id}'; + font-size: ${firstFont.size || '150%'}; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + vertical-align: top; +} +`; + } + } + + for (const definitionId of definitionSelectors.keys()) { + const iconDefinition = iconDefinitions[definitionId]; + const selectors = definitionSelectors.get(definitionId); + if (selectors && iconDefinition) { + const cssUrl = this.toCSSUrl(iconDefinition.iconPath); + if (cssUrl) { + this.styleSheetContent += `${selectors.join(', ')} { + content: ' '; + background-image: ${cssUrl}; + background-size: 16px; + background-position: left center; + background-repeat: no-repeat; +} +`; + } + if (iconDefinition.fontCharacter || iconDefinition.fontColor) { + let body = ''; + if (iconDefinition.fontColor) { + body += ` color: ${iconDefinition.fontColor};`; + } + if (iconDefinition.fontCharacter) { + body += ` content: '${iconDefinition.fontCharacter}';`; + } + if (iconDefinition.fontSize) { + body += ` font-size: ${iconDefinition.fontSize};`; + } + if (iconDefinition.fontId) { + body += ` font-family: ${iconDefinition.fontId};`; + } + this.styleSheetContent += `${selectors.join(', ')} {${body} }\n`; + } + } + } + } + + protected toCSSUrl(iconPath: string | undefined): string | undefined { + if (!iconPath) { + return undefined; + } + const iconUri = this.locationUri.resolve(iconPath); + const relativePath = this.packageUri.path.relative(iconUri.path.normalize()); + return relativePath && `url('hostedPlugin/${this.pluginId}/${encodeURIComponent(relativePath.normalize().toString())}')`; + } + + protected escapeCSS(value: string): string { + try { + return CSS.escape(value); + } catch { + // Edge and Safari on iOS does not support `CSS.escape` yet, remove it when they do + value = value.replace(/[^\-a-zA-Z0-9]/g, '-'); + if (value.charAt(0).match(/[0-9\-]/)) { + value = '-' + value; + } + return value; + } + } + + protected readonly fileIcon = 'theia-plugin-file-icon'; + protected readonly folderIcon = 'theia-plugin-folder-icon'; + protected readonly folderExpandedIcon = 'theia-plugin-folder-expanded-icon'; + protected readonly rootFolderIcon = 'theia-plugin-root-folder-icon'; + protected readonly rootFolderExpandedIcon = 'theia-plugin-root-folder-expanded-icon'; + protected folderNameIcon(folderName: string): string { + return 'theia-plugin-' + this.escapeCSS(folderName.toLowerCase()) + '-folder-name-icon'; + } + protected expandedFolderNameIcon(folderName: string): string { + return 'theia-plugin-' + this.escapeCSS(folderName.toLowerCase()) + '-expanded-folder-name-icon'; + } + protected fileNameIcon(fileName: string): string[] { + fileName = fileName.toLowerCase(); + const extIndex = fileName.indexOf('.'); + const icons = extIndex !== -1 ? this.fileExtensionIcon(fileName.substr(extIndex + 1)) : []; + icons.unshift('theia-plugin-' + this.escapeCSS(fileName) + '-file-name-icon'); + return icons; + } + protected fileExtensionIcon(fileExtension: string): string[] { + fileExtension = fileExtension.toString(); + const icons = []; + const segments = fileExtension.split('.'); + if (segments.length) { + if (segments.length) { + for (let i = 0; i < segments.length; i++) { + icons.push('theia-plugin-' + this.escapeCSS(segments.slice(i).join('.')) + '-ext-file-icon'); + } + icons.push('theia-plugin-ext-file-icon'); // extra segment to increase file-ext score + } + } + return icons; + } + protected languageIcon(languageId: string): string { + return 'theia-plugin-' + this.escapeCSS(languageId) + '-lang-file-icon'; + } + + protected collectSelectors( + associations: RecursivePartial, + accept: (definitionId: string, ...icons: string[]) => void + ): void { + if (associations.folder) { + accept(associations.folder, this.folderIcon); + this.hasFolderIcons = true; + } + if (associations.folderExpanded) { + accept(associations.folderExpanded, this.folderExpandedIcon); + this.hasFolderIcons = true; + } + const rootFolder = associations.rootFolder || associations.folder; + if (rootFolder) { + accept(rootFolder, this.rootFolderIcon); + this.hasFolderIcons = true; + } + const rootFolderExpanded = associations.rootFolderExpanded || associations.folderExpanded; + if (rootFolderExpanded) { + accept(rootFolderExpanded, this.rootFolderExpandedIcon); + this.hasFolderIcons = true; + } + if (associations.file) { + accept(associations.file, this.fileIcon); + this.hasFileIcons = true; + } + const folderNames = associations.folderNames; + if (folderNames) { + // tslint:disable-next-line:forin + for (const folderName in folderNames) { + accept(folderNames[folderName]!, this.folderNameIcon(folderName), this.folderIcon); + this.hasFolderIcons = true; + } + } + const folderNamesExpanded = associations.folderNamesExpanded; + if (folderNamesExpanded) { + // tslint:disable-next-line:forin + for (const folderName in folderNamesExpanded) { + accept(folderNamesExpanded[folderName]!, this.expandedFolderNameIcon(folderName), this.folderExpandedIcon); + this.hasFolderIcons = true; + } + } + const languageIds = associations.languageIds; + if (languageIds) { + if (!languageIds.jsonc && languageIds.json) { + languageIds.jsonc = languageIds.json; + } + // tslint:disable-next-line:forin + for (const languageId in languageIds) { + accept(languageIds[languageId]!, this.languageIcon(languageId), this.fileIcon); + this.hasFileIcons = true; + } + } + const fileExtensions = associations.fileExtensions; + if (fileExtensions) { + // tslint:disable-next-line:forin + for (const fileExtension in fileExtensions) { + accept(fileExtensions[fileExtension]!, ...this.fileExtensionIcon(fileExtension), this.fileIcon); + this.hasFileIcons = true; + } + } + const fileNames = associations.fileNames; + if (fileNames) { + // tslint:disable-next-line:forin + for (const fileName in fileNames) { + accept(fileNames[fileName]!, ...this.fileNameIcon(fileName), this.fileIcon); + this.hasFileIcons = true; + } + } + } + + /** + * This should be aligned with + * https://github.com/microsoft/vscode/blob/7cf4cca47aa025a590fc939af54932042302be63/src/vs/editor/common/services/getIconClasses.ts#L5 + */ + getIcon(element: URI | FileStat | FileStatNode | WorkspaceRootNode): string { + let icon = ''; + for (const className of this.getClassNames(element)) { + if (this.icons.has(className)) { + if (icon) { + icon += ' '; + } + icon += className; + } + } + return icon; + } + + protected getClassNames(element: URI | FileStat | FileStatNode | WorkspaceRootNode): string[] { + if (WorkspaceRootNode.is(element)) { + const name = this.labelProvider.getName(element); + if (element.expanded) { + return [this.rootFolderExpandedIcon, this.expandedFolderNameIcon(name)]; + } + return [this.rootFolderIcon, this.folderNameIcon(name)]; + } if (DirNode.is(element)) { + if (element.expanded) { + const name = this.labelProvider.getName(element); + return [this.folderExpandedIcon, this.expandedFolderNameIcon(name)]; + } + return this.getFolderClassNames(element); + } + if (FileStatNode.is(element)) { + return this.getFileClassNames(element, element.fileStat.uri); + } + if (FileStat.is(element)) { + if (element.isDirectory) { + return this.getFolderClassNames(element); + } + return this.getFileClassNames(element, element.uri); + } + if (!element.path.ext) { + return this.getFolderClassNames(element); + } + return this.getFileClassNames(element, element.toString()); + } + + protected getFolderClassNames(element: object): string[] { + const name = this.labelProvider.getName(element); + return [this.folderIcon, this.folderNameIcon(name)]; + } + + protected getFileClassNames(element: URI | FileStat | FileStatNode, uri: string): string[] { + const name = this.labelProvider.getName(element); + const classNames = this.fileNameIcon(name); + classNames.unshift(this.fileIcon); + const language = monaco.services.StaticServices.modeService.get().createByFilepathOrFirstLine(monaco.Uri.parse(uri)); + classNames.push(this.languageIcon(language.languageIdentifier.language)); + return classNames; + } + +} + +@injectable() +export class PluginIconThemeService implements LabelProviderContribution { + + @inject(IconThemeService) + protected readonly iconThemeService: IconThemeService; + + @inject(PluginIconThemeFactory) + protected readonly iconThemeFactory: PluginIconThemeFactory; + + protected readonly onDidChangeEmitter = new Emitter(); + readonly onDidChange = this.onDidChangeEmitter.event; + + protected fireDidChange(): void { + this.onDidChangeEmitter.fire({ affects: () => true }); + } + + register(contribution: IconThemeContribution, plugin: DeployedPlugin): Disposable { + const pluginId = getPluginId(plugin.metadata.model); + const packagePath = plugin.metadata.model.packagePath; + const iconTheme = this.iconThemeFactory({ + id: pluginId + '-' + contribution.id, + label: contribution.label || new URI(contribution.uri).path.base, + description: contribution.description, + uri: contribution.uri, + uiTheme: contribution.uiTheme, + pluginId, + packagePath + }); + return new DisposableCollection( + iconTheme, + iconTheme.onDidChange(() => this.fireDidChange()), + this.iconThemeService.register(iconTheme) + ); + } + + canHandle(element: object): number { + const current = this.iconThemeService.getDefinition(this.iconThemeService.current); + if (current instanceof PluginIconTheme && ( + (element instanceof URI && element.scheme === 'file') || FileStat.is(element) || FileStatNode.is(element) + )) { + return Number.MAX_SAFE_INTEGER; + } + return 0; + } + + getIcon(element: URI | FileStat | FileStatNode | WorkspaceRootNode): string | undefined { + const current = this.iconThemeService.getDefinition(this.iconThemeService.current); + if (current instanceof PluginIconTheme) { + return current.getIcon(element); + } + return undefined; + } + +} diff --git a/packages/plugin-ext/src/main/browser/quick-open-main.ts b/packages/plugin-ext/src/main/browser/quick-open-main.ts index b23830e990ed6..919ae356ca94e 100644 --- a/packages/plugin-ext/src/main/browser/quick-open-main.ts +++ b/packages/plugin-ext/src/main/browser/quick-open-main.ts @@ -34,7 +34,7 @@ import { TransferQuickPick } from '../../common/plugin-api-rpc'; import { MonacoQuickOpenService } from '@theia/monaco/lib/browser/monaco-quick-open-service'; -import { QuickInputService, FOLDER_ICON, FILE_ICON } from '@theia/core/lib/browser'; +import { QuickInputService, LabelProvider } from '@theia/core/lib/browser'; import { PluginSharedStyle } from './plugin-shared-style'; import URI from 'vscode-uri'; import { ThemeIcon, QuickInputButton } from '../../plugin/types-impl'; @@ -54,7 +54,8 @@ export class QuickOpenMainImpl implements QuickOpenMain, QuickOpenModel, Disposa private acceptor: ((items: QuickOpenItem[]) => void) | undefined; private items: QuickOpenItem[] | undefined; - private sharedStyle: PluginSharedStyle; + private readonly sharedStyle: PluginSharedStyle; + private readonly labelProvider: LabelProvider; private activeElement: HTMLElement | undefined; @@ -67,6 +68,7 @@ export class QuickOpenMainImpl implements QuickOpenMain, QuickOpenModel, Disposa this.quickTitleBar = container.get(QuickTitleBar); this.quickPick = container.get(QuickPickService); this.sharedStyle = container.get(PluginSharedStyle); + this.labelProvider = container.get(LabelProvider); } dispose(): void { @@ -196,10 +198,10 @@ export class QuickOpenMainImpl implements QuickOpenMain, QuickOpenModel, Disposa private resolveIconClassFromThemeIcon(themeIconID: ThemeIcon): string { switch (themeIconID.id) { case 'folder': { - return FOLDER_ICON; + return this.labelProvider.folderIcon; } case 'file': { - return FILE_ICON; + return this.labelProvider.fileIcon; } case 'Back': { return 'fa fa-arrow-left'; diff --git a/packages/plugin-ext/src/main/browser/scm-main.ts b/packages/plugin-ext/src/main/browser/scm-main.ts index 50fa67f16e8df..756fe4f2084d8 100644 --- a/packages/plugin-ext/src/main/browser/scm-main.ts +++ b/packages/plugin-ext/src/main/browser/scm-main.ts @@ -31,14 +31,12 @@ import { Emitter, Event } from '@theia/core/lib/common/event'; import { CancellationToken } from '@theia/core/lib/common/cancellation'; import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable'; import URI from '@theia/core/lib/common/uri'; -import { LabelProvider } from '@theia/core/lib/browser'; import { ColorRegistry } from '@theia/core/lib/browser/color-registry'; export class ScmMainImpl implements ScmMain, Disposable { private readonly proxy: ScmExt; private readonly scmService: ScmService; private readonly scmRepositoryMap = new Map(); - private readonly labelProvider: LabelProvider; private readonly colors: ColorRegistry; private lastSelectedSourceControlHandle: number | undefined; @@ -47,7 +45,6 @@ export class ScmMainImpl implements ScmMain, Disposable { constructor(rpc: RPCProtocol, container: interfaces.Container) { this.proxy = rpc.getProxy(MAIN_RPC_CONTEXT.SCM_EXT); this.scmService = container.get(ScmService); - this.labelProvider = container.get(LabelProvider); this.colors = container.get(ColorRegistry); this.toDispose.push(this.scmService.onDidChangeSelectedRepository(repository => this.updateSelectedRepository(repository))); } @@ -75,7 +72,7 @@ export class ScmMainImpl implements ScmMain, Disposable { } async $registerSourceControl(sourceControlHandle: number, id: string, label: string, rootUri: string): Promise { - const provider = new PluginScmProvider(this.proxy, sourceControlHandle, id, label, rootUri, this.labelProvider, this.colors); + const provider = new PluginScmProvider(this.proxy, sourceControlHandle, id, label, rootUri, this.colors); const repository = this.scmService.registerScmProvider(provider); repository.input.onDidChange(() => this.proxy.$updateInputBox(sourceControlHandle, repository.input.value) @@ -171,7 +168,6 @@ export class PluginScmProvider implements ScmProvider { readonly id: string, readonly label: string, readonly rootUri: string, - protected readonly labelProvider: LabelProvider, protected readonly colors: ColorRegistry ) { this.disposableCollection.push(this.onDidChangeEmitter); @@ -312,9 +308,7 @@ export class PluginScmProvider implements ScmProvider { const decorations = resource.decorations; if (decorations) { const colorVariable = resource.colorId && this.colors.toCssVariableName(resource.colorId); - const icon = decorations.iconPath ? decorations.iconPath : await this.labelProvider.getIcon(new URI(resource.resourceUri)); scmDecorations = { - icon, tooltip: decorations.tooltip, letter: resource.letter, color: colorVariable && `var(${colorVariable})` diff --git a/packages/plugin-ext/src/main/browser/style/index.css b/packages/plugin-ext/src/main/browser/style/index.css index 1946ad981546d..2724f2bc9317c 100644 --- a/packages/plugin-ext/src/main/browser/style/index.css +++ b/packages/plugin-ext/src/main/browser/style/index.css @@ -49,6 +49,41 @@ mask: url('test.svg'); } +.theia-plugin-file-icon, +.theia-plugin-file-icon::before, +.theia-plugin-folder-icon, +.theia-plugin-folder-icon::before, +.theia-plugin-folder-expanded-icon, +.theia-plugin-folder-expanded-icon::before, +.theia-plugin-root-folder-icon, +.theia-plugin-root-folder-icon::before, +.theia-plugin-root-folder-expanded-icon, +.theia-plugin-root-folder-expanded-icon::before { + padding-right: var(--theia-ui-padding); + width: var(--theia-icon-size); + height: var(--theia-content-line-height); + line-height: inherit !important; + display: inline-block; +} + +.p-TabBar.theia-app-sides .theia-plugin-file-icon, +.p-TabBar.theia-app-sides .theia-plugin-file-icon::before, +.p-TabBar.theia-app-sides .theia-plugin-folder-icon, +.p-TabBar.theia-app-sides .theia-plugin-folder-icon::before, +.p-TabBar.theia-app-sides .theia-plugin-folder-expanded-icon, +.p-TabBar.theia-app-sides .theia-plugin-folder-expanded-icon::before, +.p-TabBar.theia-app-sides .theia-plugin-root-folder-icon, +.p-TabBar.theia-app-sides .theia-plugin-root-folder-icon::before, +.p-TabBar.theia-app-sides .theia-plugin-root-folder-expanded-icon, +.p-TabBar.theia-app-sides .theia-plugin-root-folder-expanded-icon::before { + padding: 0px !important; + width: var(--theia-private-sidebar-icon-size) !important; + height: var(--theia-private-sidebar-icon-size) !important; + background-size: var(--theia-private-sidebar-icon-size) !important; + font-size: var(--theia-private-sidebar-icon-size) !important; +} + + @import './plugin-sidebar.css'; @import './webview.css'; @import './tree.css'; diff --git a/packages/plugin-ext/src/main/browser/view/plugin-tree-view-node-label-provider.ts b/packages/plugin-ext/src/main/browser/view/plugin-tree-view-node-label-provider.ts new file mode 100644 index 0000000000000..606f47151c545 --- /dev/null +++ b/packages/plugin-ext/src/main/browser/view/plugin-tree-view-node-label-provider.ts @@ -0,0 +1,78 @@ +/******************************************************************************** + * Copyright (C) 2019 TypeFox 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, inject } from 'inversify'; +import URI from '@theia/core/lib/common/uri'; +import { LabelProviderContribution, LabelProvider } from '@theia/core/lib/browser/label-provider'; +import { TreeLabelProvider } from '@theia/core/lib/browser/tree/tree-label-provider'; +import { TreeViewNode } from './tree-view-widget'; +import { TreeNode } from '@theia/core/lib/browser/tree/tree'; +import { FileStat } from '@theia/filesystem/lib/common'; + +@injectable() +export class PluginTreeViewNodeLabelProvider implements LabelProviderContribution { + + @inject(LabelProvider) + protected readonly labelProvider: LabelProvider; + + @inject(TreeLabelProvider) + protected readonly treeLabelProvider: TreeLabelProvider; + + // tslint:disable-next-line:no-any + canHandle(element: TreeViewNode | any): number { + if (TreeNode.is(element) && ('resourceUri' in element || 'themeIconId' in element)) { + return this.treeLabelProvider.canHandle(element) + 1; + } + return 0; + } + + getIcon(node: TreeViewNode): string | undefined { + if (node.icon) { + return node.icon; + } + if (node.themeIconId) { + const isDirectory = node.themeIconId === 'folder'; + const uri = node.resourceUri || (isDirectory ? 'file:///foo' : 'file:///foo.txt'); + const fileStat: FileStat = { uri, lastModification: 0, isDirectory }; + return this.labelProvider.getIcon(fileStat); + } + if (node.resourceUri) { + return this.labelProvider.getIcon(new URI(node.resourceUri)); + } + return undefined; + } + + getName(node: TreeViewNode): string | undefined { + if (node.name) { + return node.name; + } + if (node.resourceUri) { + return this.labelProvider.getName(new URI(node.resourceUri)); + } + return undefined; + } + + getLongName(node: TreeViewNode): string | undefined { + if (typeof node.description === 'string') { + return node.description; + } + if (node.description === true && node.resourceUri) { + return this.labelProvider.getLongName(new URI(node.resourceUri)); + } + return undefined; + } + +} diff --git a/packages/plugin-ext/src/main/browser/view/tree-view-widget.tsx b/packages/plugin-ext/src/main/browser/view/tree-view-widget.tsx index d739cc07b5f86..79dec87100ef8 100644 --- a/packages/plugin-ext/src/main/browser/view/tree-view-widget.tsx +++ b/packages/plugin-ext/src/main/browser/view/tree-view-widget.tsx @@ -14,6 +14,7 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ +import URI from 'vscode-uri'; import { injectable, inject, postConstruct } from 'inversify'; import { TreeViewsExt, TreeViewSelection } from '../../../common/plugin-api-rpc'; import { Command } from '../../../common/plugin-api-rpc-model'; @@ -27,8 +28,6 @@ import { TreeImpl, TREE_NODE_SEGMENT_CLASS, TREE_NODE_SEGMENT_GROW_CLASS, - FOLDER_ICON, - FILE_ICON, TREE_NODE_TAIL_CLASS, TreeModelImpl } from '@theia/core/lib/browser'; @@ -42,6 +41,7 @@ import { CommandRegistry } from '@theia/core/lib/common/command'; import { Emitter } from '@theia/core/lib/common/event'; import { MessageService } from '@theia/core/lib/common/message-service'; import { View } from '../../../common/plugin-protocol'; +import CoreURI from '@theia/core/lib/common/uri'; export const TREE_NODE_HYPERLINK = 'theia-TreeNodeHyperlink'; export const VIEW_ITEM_CONTEXT_MENU: MenuPath = ['view-item-context-menu']; @@ -55,6 +55,11 @@ export interface SelectionEventHandler { export interface TreeViewNode extends SelectableTreeNode { contextValue?: string; command?: Command; + resourceUri?: string; + themeIconId?: 'folder' | 'file'; + tooltip?: string; + // tslint:disable-next-line:no-any + description?: string | boolean | any; } export namespace TreeViewNode { export function is(arg: TreeNode | undefined): arg is TreeViewNode { @@ -63,6 +68,8 @@ export namespace TreeViewNode { } export interface CompositeTreeViewNode extends TreeViewNode, ExpandableTreeNode, CompositeTreeNode { + // tslint:disable-next-line:no-any + description?: string | boolean | any; } export namespace CompositeTreeViewNode { export function is(arg: TreeNode | undefined): arg is CompositeTreeViewNode { @@ -122,10 +129,14 @@ export class PluginTree extends TreeImpl { protected createTreeNode(item: TreeViewItem, parent: CompositeTreeNode): TreeNode { const icon = this.toIconClass(item); - const update = { + const resourceUri = item.resourceUri && URI.revive(item.resourceUri).toString(); + const themeIconId = item.themeIconId || item.collapsibleState !== TreeViewItemCollapsibleState.None ? 'folder' : 'file'; + const update: Partial = { name: item.label, icon, description: item.description, + themeIconId, + resourceUri, tooltip: item.tooltip, contextValue: item.contextValue }; @@ -164,12 +175,6 @@ export class PluginTree extends TreeImpl { this.toDispose.push(reference); return reference.object.iconClass; } - if (item.themeIconId) { - return item.themeIconId === 'folder' ? FOLDER_ICON : FILE_ICON; - } - if (item.resourceUri) { - return item.collapsibleState !== TreeViewItemCollapsibleState.None ? FOLDER_ICON : FILE_ICON; - } return undefined; } @@ -224,29 +229,27 @@ export class TreeViewWidget extends TreeWidget { } protected renderIcon(node: TreeNode, props: NodeProps): React.ReactNode { - if (node.icon) { - return
; + const icon = this.toNodeIcon(node); + if (icon) { + return
; } return undefined; } - protected renderCaption(node: TreeNode, props: NodeProps): React.ReactNode { + protected renderCaption(node: TreeViewNode, props: NodeProps): React.ReactNode { const classes = [TREE_NODE_SEGMENT_CLASS]; if (!this.hasTrailingSuffixes(node)) { classes.push(TREE_NODE_SEGMENT_GROW_CLASS); } const className = classes.join(' '); - let attrs = this.decorateCaption(node, { - className, id: node.id + const title = node.tooltip || + (node.resourceUri && this.labelProvider.getLongName(new CoreURI(node.resourceUri))) + || this.toNodeName(node); + const attrs = this.decorateCaption(node, { + className, id: node.id, + title }); - if (node.description) { - attrs = { - ...attrs, - title: 'tooltip' in node ? node['tooltip'] : '' - }; - } - const children = this.getCaption(node); return React.createElement('div', attrs, ...children); } @@ -254,7 +257,10 @@ export class TreeViewWidget extends TreeWidget { protected getCaption(node: TreeNode): React.ReactNode[] { const nodes: React.ReactNode[] = []; - let work = node.name || ''; + const name = this.toNodeName(node) || ''; + const description = this.toNodeDescription(node); + + let work = name; const regex = /\[([^\[]+)\]\(([^\)]+)\)/g; const matchResult = work.match(regex); @@ -264,7 +270,7 @@ export class TreeViewWidget extends TreeWidget { const part = work.substring(0, work.indexOf(match)); nodes.push(part); - const execResult = regex.exec(node.name); + const execResult = regex.exec(name); const link = {work}
); - if (node.description) { + if (description) { nodes.push(
- {node.description} + {description}
); } return nodes; diff --git a/packages/plugin-ext/src/plugin/tree/tree-views.ts b/packages/plugin-ext/src/plugin/tree/tree-views.ts index 1ecc7fd96a728..4ee502b7faffd 100644 --- a/packages/plugin-ext/src/plugin/tree/tree-views.ts +++ b/packages/plugin-ext/src/plugin/tree/tree-views.ts @@ -242,23 +242,19 @@ class TreeViewExtImpl implements Disposable { label = treeItem.label; } + let idLabel = label; // Use resource URI if label is not set - if (label === undefined && treeItem.resourceUri) { - label = treeItem.resourceUri.path.toString(); - label = decodeURIComponent(label); - if (label.indexOf('/') >= 0) { - label = label.substring(label.lastIndexOf('/') + 1); + if (idLabel === undefined && treeItem.resourceUri) { + idLabel = treeItem.resourceUri.path.toString(); + idLabel = decodeURIComponent(idLabel); + if (idLabel.indexOf('/') >= 0) { + idLabel = idLabel.substring(idLabel.lastIndexOf('/') + 1); } } // Generate the ID // ID is used for caching the element - const id = treeItem.id || `${parentId}/${index}:${label}`; - - // Use item ID if item label is still not set - if (label === undefined) { - label = treeItem.id; - } + const id = treeItem.id || `${parentId}/${index}:${idLabel}`; const toDisposeElement = new DisposableCollection(); const node: TreeExtNode = { diff --git a/packages/preview/src/browser/markdown/style/markdown.css b/packages/preview/src/browser/markdown/style/markdown.css index f5534625d3158..f15a86382926a 100644 --- a/packages/preview/src/browser/markdown/style/markdown.css +++ b/packages/preview/src/browser/markdown/style/markdown.css @@ -23,7 +23,7 @@ font-family: var(--theia-ui-font-family); font-size: 14px; padding: 0 26px; - line-height: 22px; + line-height: var(--theia-content-line-height); word-wrap: break-word; } diff --git a/packages/preview/src/browser/style/preview-widget.css b/packages/preview/src/browser/style/preview-widget.css index 3ed24f3e4bf25..abe30a37a4748 100644 --- a/packages/preview/src/browser/style/preview-widget.css +++ b/packages/preview/src/browser/style/preview-widget.css @@ -20,7 +20,7 @@ } .theia-preview-widget .scrollBeyondLastLine { - margin-bottom: calc(100vh - 22px); + margin-bottom: calc(100vh - var(--theia-content-line-height)); } .theia-preview-widget:focus { diff --git a/packages/scm/src/browser/scm-provider.ts b/packages/scm/src/browser/scm-provider.ts index 6c370bda7c02f..65dd792632494 100644 --- a/packages/scm/src/browser/scm-provider.ts +++ b/packages/scm/src/browser/scm-provider.ts @@ -54,7 +54,6 @@ export interface ScmResource { } export interface ScmResourceDecorations { - icon?: string; tooltip?: string; source?: string; letter?: string; diff --git a/packages/scm/src/browser/scm-widget.tsx b/packages/scm/src/browser/scm-widget.tsx index a5242d8f36165..8df8c3ac98682 100644 --- a/packages/scm/src/browser/scm-widget.tsx +++ b/packages/scm/src/browser/scm-widget.tsx @@ -88,7 +88,12 @@ export class ScmWidget extends ReactWidget implements StatefulWidget { protected init(): void { this.refresh(); this.toDispose.push(this.scmService.onDidChangeSelectedRepository(() => this.refresh())); - this.toDispose.push(this.labelProvider.onDidChange(() => this.update())); + this.toDispose.push(this.labelProvider.onDidChange(e => { + const repository = this.scmService.selectedRepository; + if (repository && repository.resources.some(resource => e.affects(resource.sourceUri))) { + this.update(); + } + })); } protected readonly toDisposeOnRefresh = new DisposableCollection(); @@ -446,7 +451,7 @@ export class ScmResourceComponent extends ScmElement return undefined; } const decorations = resource.decorations; - const icon = decorations && decorations.icon || ''; + const icon = labelProvider.getIcon(resource.sourceUri); const color = decorations && decorations.color || ''; const letter = decorations && decorations.letter || ''; const tooltip = decorations && decorations.tooltip || ''; @@ -460,8 +465,8 @@ export class ScmResourceComponent extends ScmElement ref={this.detectHover} onClick={this.handleClick} onDoubleClick={this.handleDoubleClick} > +
- {name} {path}
diff --git a/packages/scm/src/browser/style/index.css b/packages/scm/src/browser/style/index.css index cfd544d88881d..1fe0292ce179b 100644 --- a/packages/scm/src/browser/style/index.css +++ b/packages/scm/src/browser/style/index.css @@ -180,11 +180,13 @@ } .theia-scm .scmItem { - margin: 1px 0 1px 0; - padding: 2px 5px 2px 5px; font-size: var(--theia-ui-font-size1); display: flex; + align-items: center; justify-content: space-between; + height: var(--theia-content-line-height); + line-height: var(--theia-content-line-height); + padding: 0px calc(var(--theia-ui-padding)/2); } .theia-scm .scmItem .file-icon { @@ -214,7 +216,7 @@ } .scm-theia-header { - padding: 5px; + padding: calc(var(--theia-ui-padding)/2); display: flex; } @@ -250,7 +252,7 @@ } .theia-scm-inline-action .open-file { - height: 16px; + height: var(--theia-icon-size); width: 12px; background: var(--theia-icon-open-file) no-repeat center center; } diff --git a/packages/search-in-workspace/src/browser/search-in-workspace-frontend-module.ts b/packages/search-in-workspace/src/browser/search-in-workspace-frontend-module.ts index f8c4f51f9324a..fec6100d40470 100644 --- a/packages/search-in-workspace/src/browser/search-in-workspace-frontend-module.ts +++ b/packages/search-in-workspace/src/browser/search-in-workspace-frontend-module.ts @@ -19,7 +19,7 @@ import '../../src/browser/styles/index.css'; import { ContainerModule, interfaces } from 'inversify'; import { SearchInWorkspaceService, SearchInWorkspaceClientImpl } from './search-in-workspace-service'; import { SearchInWorkspaceServer, SIW_WS_PATH } from '../common/search-in-workspace-interface'; -import { WebSocketConnectionProvider, WidgetFactory, createTreeContainer, TreeWidget, bindViewContribution, FrontendApplicationContribution } from '@theia/core/lib/browser'; +import { WebSocketConnectionProvider, WidgetFactory, createTreeContainer, TreeWidget, bindViewContribution, FrontendApplicationContribution, LabelProviderContribution } from '@theia/core/lib/browser'; import { ResourceResolver } from '@theia/core'; import { SearchInWorkspaceWidget } from './search-in-workspace-widget'; import { SearchInWorkspaceResultTreeWidget } from './search-in-workspace-result-tree-widget'; @@ -28,6 +28,7 @@ import { InMemoryTextResourceResolver } from './in-memory-text-resource'; import { SearchInWorkspaceContextKeyService } from './search-in-workspace-context-key-service'; import { TabBarToolbarContribution } from '@theia/core/lib/browser/shell/tab-bar-toolbar'; import { bindSearchInWorkspacePreferences } from './search-in-workspace-preferences'; +import { SearchInWorkspaceLabelProvider } from './search-in-workspace-label-provider'; export default new ContainerModule(bind => { bind(SearchInWorkspaceContextKeyService).toSelf().inSingletonScope(); @@ -58,6 +59,9 @@ export default new ContainerModule(bind => { bind(ResourceResolver).toService(InMemoryTextResourceResolver); bindSearchInWorkspacePreferences(bind); + + bind(SearchInWorkspaceLabelProvider).toSelf().inSingletonScope(); + bind(LabelProviderContribution).toService(SearchInWorkspaceLabelProvider); }); export function createSearchTreeWidget(parent: interfaces.Container): SearchInWorkspaceResultTreeWidget { diff --git a/packages/search-in-workspace/src/browser/search-in-workspace-label-provider.ts b/packages/search-in-workspace/src/browser/search-in-workspace-label-provider.ts new file mode 100644 index 0000000000000..1632b6ae1f2f4 --- /dev/null +++ b/packages/search-in-workspace/src/browser/search-in-workspace-label-provider.ts @@ -0,0 +1,48 @@ +/******************************************************************************** + * Copyright (C) 2019 TypeFox 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, inject } from 'inversify'; +import { LabelProviderContribution, LabelProvider, DidChangeLabelEvent } from '@theia/core/lib/browser/label-provider'; +import { SearchInWorkspaceRootFolderNode, SearchInWorkspaceFileNode } from './search-in-workspace-result-tree-widget'; +import URI from '@theia/core/lib/common/uri'; + +@injectable() +export class SearchInWorkspaceLabelProvider implements LabelProviderContribution { + + @inject(LabelProvider) + protected readonly labelProvider: LabelProvider; + + canHandle(element: object): number { + return SearchInWorkspaceRootFolderNode.is(element) || SearchInWorkspaceFileNode.is(element) ? 100 : 0; + } + + getIcon(node: SearchInWorkspaceRootFolderNode | SearchInWorkspaceFileNode): string { + if (SearchInWorkspaceFileNode.is(node)) { + return this.labelProvider.getIcon(new URI(node.fileUri).withScheme('file')); + } + return this.labelProvider.folderIcon; + } + + getName(node: SearchInWorkspaceRootFolderNode | SearchInWorkspaceFileNode): string { + const uri = SearchInWorkspaceFileNode.is(node) ? node.fileUri : node.folderUri; + return new URI(uri).displayName; + } + + affects(node: SearchInWorkspaceRootFolderNode | SearchInWorkspaceFileNode, event: DidChangeLabelEvent): boolean { + return SearchInWorkspaceFileNode.is(node) && event.affects(new URI(node.fileUri).withScheme('file')); + } + +} diff --git a/packages/search-in-workspace/src/browser/search-in-workspace-result-tree-widget.tsx b/packages/search-in-workspace/src/browser/search-in-workspace-result-tree-widget.tsx index 82756e7287185..c479ac5ee21a5 100644 --- a/packages/search-in-workspace/src/browser/search-in-workspace-result-tree-widget.tsx +++ b/packages/search-in-workspace/src/browser/search-in-workspace-result-tree-widget.tsx @@ -25,13 +25,10 @@ import { TreeModel, TreeNode, NodeProps, - LabelProvider, TreeProps, TreeExpansionService, ApplicationShell, - DiffUris, - FOLDER_ICON, - FILE_ICON + DiffUris } from '@theia/core/lib/browser'; import { CancellationTokenSource, Emitter, Event } from '@theia/core'; import { EditorManager, EditorDecoration, TrackedRangeStickiness, OverviewRulerLane, EditorWidget, ReplaceOperation, EditorOpenerOptions } from '@theia/editor/lib/browser'; @@ -53,10 +50,12 @@ export interface SearchInWorkspaceRoot extends CompositeTreeNode { export namespace SearchInWorkspaceRoot { // tslint:disable-next-line:no-any export function is(node: any): node is SearchInWorkspaceRoot { - return CompositeTreeNode.is(node) && node.id === ROOT_ID && node.name === ROOT_ID; + return CompositeTreeNode.is(node) && node.id === ROOT_ID; } } export interface SearchInWorkspaceRootFolderNode extends ExpandableTreeNode, SelectableTreeNode { // root folder node + name?: undefined + icon?: undefined children: SearchInWorkspaceFileNode[]; parent: SearchInWorkspaceRoot; path: string; @@ -70,11 +69,12 @@ export namespace SearchInWorkspaceRootFolderNode { } export interface SearchInWorkspaceFileNode extends ExpandableTreeNode, SelectableTreeNode { // file node + name?: undefined + icon?: undefined children: SearchInWorkspaceResultLineNode[]; parent: SearchInWorkspaceRootFolderNode; path: string; fileUri: string; - icon?: string; } export namespace SearchInWorkspaceFileNode { // tslint:disable-next-line:no-any @@ -114,7 +114,6 @@ export class SearchInWorkspaceResultTreeWidget extends TreeWidget { @inject(EditorManager) protected readonly editorManager: EditorManager; @inject(FileResourceResolver) protected readonly fileResourceResolver: FileResourceResolver; @inject(ApplicationShell) protected readonly shell: ApplicationShell; - @inject(LabelProvider) protected readonly labelProvider: LabelProvider; @inject(WorkspaceService) protected readonly workspaceService: WorkspaceService; @inject(TreeExpansionService) protected readonly expansionService: TreeExpansionService; @inject(SearchInWorkspacePreferences) protected readonly searchInWorkspacePreferences: SearchInWorkspacePreferences; @@ -129,7 +128,6 @@ export class SearchInWorkspaceResultTreeWidget extends TreeWidget { model.root = { id: ROOT_ID, - name: ROOT_ID, parent: undefined, visible: false, children: [] @@ -215,7 +213,7 @@ export class SearchInWorkspaceResultTreeWidget extends TreeWidget { if (token.isCancellationRequested || aSearchId !== searchId) { return; } - const { name, path } = this.filenameAndPath(result.root, result.fileUri); + const { path } = this.filenameAndPath(result.root, result.fileUri); const tree = this.resultTree; const rootFolderNode = tree.get(result.root); @@ -228,7 +226,7 @@ export class SearchInWorkspaceResultTreeWidget extends TreeWidget { } this.collapseFileNode(fileNode, collapseValue); } else { - const newFileNode = this.createFileNode(result.root, name, path, result.fileUri, rootFolderNode); + const newFileNode = this.createFileNode(result.root, path, result.fileUri, rootFolderNode); this.collapseFileNode(newFileNode, collapseValue); const line = this.createResultLineNode(result, newFileNode); newFileNode.children.push(line); @@ -238,7 +236,7 @@ export class SearchInWorkspaceResultTreeWidget extends TreeWidget { } else { const newRootFolderNode = this.createRootFolderNode(result.root); tree.set(result.root, newRootFolderNode); - const newFileNode = this.createFileNode(result.root, name, path, result.fileUri, newRootFolderNode); + const newFileNode = this.createFileNode(result.root, path, result.fileUri, newRootFolderNode); this.collapseFileNode(newFileNode, collapseValue); newFileNode.children.push(this.createResultLineNode(result, newFileNode)); newRootFolderNode.children.push(newFileNode); @@ -302,7 +300,6 @@ export class SearchInWorkspaceResultTreeWidget extends TreeWidget { protected async refreshModelChildren(): Promise { if (SearchInWorkspaceRoot.is(this.model.root)) { - await this.updateFileIcons(); this.model.root.children = Array.from(this.resultTree.values()); this.model.refresh(); this.updateCurrentEditorDecorations(); @@ -338,40 +335,28 @@ export class SearchInWorkspaceResultTreeWidget extends TreeWidget { const uri = new URI(rootUri); return { selected: false, - name: uri.displayName, path: uri.path.toString(), folderUri: rootUri, children: [], expanded: true, id: rootUri, parent: this.model.root as SearchInWorkspaceRoot, - icon: FOLDER_ICON, visible: this.workspaceService.isMultiRootWorkspaceOpened }; } - protected createFileNode(rootUri: string, name: string, path: string, fileUri: string, parent: SearchInWorkspaceRootFolderNode): SearchInWorkspaceFileNode { + protected createFileNode(rootUri: string, path: string, fileUri: string, parent: SearchInWorkspaceRootFolderNode): SearchInWorkspaceFileNode { return { selected: false, - name, path, children: [], expanded: true, id: `${rootUri}::${fileUri}`, parent, - icon: FILE_ICON, // placeholder. updateFileIcons() will replace the placeholders with icons used in the tree rendering fileUri }; } - protected async updateFileIcons(): Promise { - for (const folderNode of this.resultTree.values()) { - for (const fileNode of folderNode.children) { - fileNode.icon = await this.labelProvider.getIcon(new URI(fileNode.fileUri).withScheme('file')); - } - } - } - protected createResultLineNode(result: SearchInWorkspaceResult, fileNode: SearchInWorkspaceFileNode): SearchInWorkspaceResultLineNode { return { ...result, @@ -596,17 +581,18 @@ export class SearchInWorkspaceResultTreeWidget extends TreeWidget { } protected renderRootFolderNode(node: SearchInWorkspaceRootFolderNode): React.ReactNode { - const icon = node.icon; return
- - - {node.name} - - - {node.path} - + +
+ + {this.toNodeName(node)} + + + {node.path} + +
@@ -618,18 +604,19 @@ export class SearchInWorkspaceResultTreeWidget extends TreeWidget { } protected renderFileNode(node: SearchInWorkspaceFileNode): React.ReactNode { - const icon = node.icon; return
- - - {node.name} - - - {node.path} - + +
+ + {this.toNodeName(node)} + + + {node.path} + +
diff --git a/packages/search-in-workspace/src/browser/styles/index.css b/packages/search-in-workspace/src/browser/styles/index.css index 906f4dce944e2..f58cf5ccad095 100644 --- a/packages/search-in-workspace/src/browser/styles/index.css +++ b/packages/search-in-workspace/src/browser/styles/index.css @@ -61,7 +61,7 @@ } .t-siw-search-container .searchHeader .controls.button-container { - height: 22px; + height: var(--theia-content-line-height); margin-bottom: 5px; } @@ -232,7 +232,8 @@ width: 7px; } -.t-siw-search-container .result .result-head .file-icon { +.t-siw-search-container .result .result-head .fa, +.t-siw-search-container .result .result-head .theia-file-icons-js { margin: 0 3px; } @@ -267,7 +268,8 @@ width: 100%; } -.result-head-info { +.t-siw-search-container .result-head-info { + display: inline-flex; align-items: center; } diff --git a/packages/workspace/src/browser/quick-open-workspace.ts b/packages/workspace/src/browser/quick-open-workspace.ts index 9ba657c4e49a6..1264fe12387e6 100644 --- a/packages/workspace/src/browser/quick-open-workspace.ts +++ b/packages/workspace/src/browser/quick-open-workspace.ts @@ -60,11 +60,13 @@ export class QuickOpenWorkspace implements QuickOpenModel { if (tempWorkspaceFile && uri.toString() === tempWorkspaceFile.toString()) { continue; // skip the temporary workspace files } + const icon = this.labelProvider.getIcon(stat); + const iconClass = icon === '' ? undefined : icon + ' file-icon'; this.items.push(new QuickOpenGroupItem({ label: uri.path.base, description: (home) ? FileSystemUtils.tildifyPath(uri.path.toString(), home) : uri.path.toString(), groupLabel: `last modified ${moment(stat.lastModification).fromNow()}`, - iconClass: await this.labelProvider.getIcon(stat) + ' file-icon', + iconClass, run: (mode: QuickOpenMode): boolean => { if (mode !== QuickOpenMode.OPEN) { return false; diff --git a/packages/workspace/src/browser/workspace-uri-contribution.spec.ts b/packages/workspace/src/browser/workspace-uri-contribution.spec.ts index 57ea62164ba79..1cc81fd11c861 100644 --- a/packages/workspace/src/browser/workspace-uri-contribution.spec.ts +++ b/packages/workspace/src/browser/workspace-uri-contribution.spec.ts @@ -24,7 +24,7 @@ import { Signal } from '@phosphor/signaling'; import { ApplicationShell } from '@theia/core/lib/browser'; import { FileStat, FileSystem } from '@theia/filesystem/lib/common/filesystem'; import { MockFilesystem } from '@theia/filesystem/lib/common/test'; -import { FOLDER_ICON, FILE_ICON, DefaultUriLabelProviderContribution } from '@theia/core/lib/browser/label-provider'; +import { DefaultUriLabelProviderContribution } from '@theia/core/lib/browser/label-provider'; import { WorkspaceUriLabelProviderContribution } from './workspace-uri-contribution'; import URI from '@theia/core/lib/common/uri'; import { WorkspaceVariableContribution } from './workspace-variable-contribution'; @@ -45,7 +45,7 @@ beforeEach(() => { container = new Container(); container.bind(ApplicationShell).toConstantValue({ currentChanged: new Signal({}) - // tslint:disable-next-line:no-any + // tslint:disable-next-line:no-any } as any); const workspaceService = new WorkspaceService(); workspaceService.tryGetRoots = () => roots; @@ -87,65 +87,50 @@ describe('WorkspaceUriLabelProviderContribution class', () => { }); describe('getIcon()', () => { - let fs: MockFilesystem; - - beforeEach(() => { - fs = container.get(FileSystem); - }); - - it('should return FOLDER_ICON from the FileStat of a folder', async () => { - expect(await labelProvider.getIcon({ + it('should return folder icon from the FileStat of a folder', async () => { + expect(labelProvider.getIcon({ uri: 'file:///home/', lastModification: 0, isDirectory: true - })).eq(FOLDER_ICON); + })).eq(labelProvider.defaultFolderIcon); }); - it('should return FILE_ICON from a non-folder FileStat', async () => { - const stat = { + it('should return file icon from a non-folder FileStat', async () => { + // tslint:disable-next-line:no-any + stubs.push(sinon.stub(DefaultUriLabelProviderContribution.prototype, 'getFileIcon').returns(undefined)); + expect(labelProvider.getIcon({ uri: 'file:///home/test', lastModification: 0, isDirectory: false - }; - stubs.push(sinon.stub(fs, 'getFileStat').resolves(stat)); - // tslint:disable-next-line:no-any - stubs.push(sinon.stub(DefaultUriLabelProviderContribution.prototype, 'getFileIcon').returns(undefined)); - expect(await labelProvider.getIcon(stat)).eq(FILE_ICON); + })).eq(labelProvider.defaultFileIcon); }); - it('should return FOLDER_ICON from a folder URI', async () => { - stubs.push(sinon.stub(fs, 'getFileStat').resolves({ + it('should return folder icon from a folder URI', async () => { + // tslint:disable-next-line:no-any + stubs.push(sinon.stub(DefaultUriLabelProviderContribution.prototype, 'getFileIcon').returns(undefined)); + expect(labelProvider.getIcon({ uri: 'file:///home/test', lastModification: 0, isDirectory: true - })); - // tslint:disable-next-line:no-any - stubs.push(sinon.stub(DefaultUriLabelProviderContribution.prototype, 'getFileIcon').returns(undefined)); - expect(await labelProvider.getIcon(new URI('file:///home/test'))).eq(FOLDER_ICON); + })).eq(labelProvider.defaultFolderIcon); }); - it('should return FILE_ICON from a file URI', async () => { - stubs.push(sinon.stub(fs, 'getFileStat').resolves({ + it('should return file icon from a file URI', async () => { + // tslint:disable-next-line:no-any + stubs.push(sinon.stub(DefaultUriLabelProviderContribution.prototype, 'getFileIcon').returns(undefined)); + expect(labelProvider.getIcon({ uri: 'file:///home/test', lastModification: 0, isDirectory: false - })); - // tslint:disable-next-line:no-any - stubs.push(sinon.stub(DefaultUriLabelProviderContribution.prototype, 'getFileIcon').returns(undefined)); - expect(await labelProvider.getIcon(new URI('file:///home/test'))).eq(FILE_ICON); - }); - - it('should return FILE_ICON from a URI when FileSystem.getFileStat() throws', async () => { - stubs.push(sinon.stub(fs, 'getFileStat').throws(new Error())); - expect(await labelProvider.getIcon(new URI('file:///home/test'))).eq(FILE_ICON); + })).eq(labelProvider.defaultFileIcon); }); it('should return what getFileIcon() returns from a URI or non-folder FileStat, if getFileIcon() does not return null or undefined', async () => { const ret = 'TestString'; // tslint:disable-next-line:no-any stubs.push(sinon.stub(DefaultUriLabelProviderContribution.prototype, 'getFileIcon').returns(ret)); - expect(await labelProvider.getIcon(new URI('file:///home/test'))).eq(ret); - expect(await labelProvider.getIcon({ + expect(labelProvider.getIcon(new URI('file:///home/test'))).eq(ret); + expect(labelProvider.getIcon({ uri: 'file:///home/test', lastModification: 0, isDirectory: false diff --git a/packages/workspace/src/browser/workspace-uri-contribution.ts b/packages/workspace/src/browser/workspace-uri-contribution.ts index af861a2c1352c..69337a189bc3d 100644 --- a/packages/workspace/src/browser/workspace-uri-contribution.ts +++ b/packages/workspace/src/browser/workspace-uri-contribution.ts @@ -14,19 +14,15 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ -import { DefaultUriLabelProviderContribution, FOLDER_ICON, FILE_ICON } from '@theia/core/lib/browser/label-provider'; +import { DefaultUriLabelProviderContribution } from '@theia/core/lib/browser/label-provider'; import URI from '@theia/core/lib/common/uri'; import { injectable, inject, postConstruct } from 'inversify'; -import { FileSystem, FileStat } from '@theia/filesystem/lib/common'; -import { MaybePromise } from '@theia/core'; +import { FileStat } from '@theia/filesystem/lib/common'; import { WorkspaceVariableContribution } from './workspace-variable-contribution'; @injectable() export class WorkspaceUriLabelProviderContribution extends DefaultUriLabelProviderContribution { - @inject(FileSystem) - protected readonly fileSystem: FileSystem; - @inject(WorkspaceVariableContribution) protected readonly workspaceVariable: WorkspaceVariableContribution; @@ -49,28 +45,15 @@ export class WorkspaceUriLabelProviderContribution extends DefaultUriLabelProvid return new URI(element.toString()); } - private getStat(element: URI | FileStat): MaybePromise { - if (FileStat.is(element)) { - return element; - } - return this.fileSystem.getFileStat(element.toString()); - } - - async getIcon(element: URI | FileStat): Promise { - if (FileStat.is(element) && element.isDirectory) { - return FOLDER_ICON; + getIcon(element: URI | FileStat): string { + if (!FileStat.is(element)) { + return super.getIcon(element); } - const uri = this.getUri(element); - const icon = super.getFileIcon(uri); - if (!icon) { - try { - const stat = await this.getStat(element); - return stat && stat.isDirectory ? FOLDER_ICON : FILE_ICON; - } catch (err) { - return FILE_ICON; - } + if (element.isDirectory) { + return this.defaultFolderIcon; } - return icon; + const icon = super.getFileIcon(new URI(element.uri)); + return icon || this.defaultFileIcon; } getName(element: URI | FileStat): string { From 940f8a8d6b58e17bdfe78b12f2ea91b1129d3e7a Mon Sep 17 00:00:00 2001 From: Jan Bicker Date: Mon, 9 Dec 2019 13:34:18 +0000 Subject: [PATCH 06/65] apply base and activity bar vscode colors Signed-off-by: Jan Bicker --- .../browser/common-frontend-contribution.ts | 36 ++++++++++++++----- .../browser/frontend-application-module.ts | 2 +- packages/core/src/browser/style/index.css | 4 +-- packages/core/src/browser/style/sidepanel.css | 19 +++++----- .../src/browser/styles/index.css | 2 +- 5 files changed, 41 insertions(+), 22 deletions(-) diff --git a/packages/core/src/browser/common-frontend-contribution.ts b/packages/core/src/browser/common-frontend-contribution.ts index 77346bf28edbe..81635c2c474c3 100644 --- a/packages/core/src/browser/common-frontend-contribution.ts +++ b/packages/core/src/browser/common-frontend-contribution.ts @@ -39,6 +39,8 @@ import { QuickViewService } from './quick-view-service'; import { PrefixQuickOpenService, QuickOpenItem, QuickOpenMode, QuickOpenService } from './quick-open'; import { environment } from '@theia/application-package/lib/environment'; import { IconThemeService } from './icon-theme-service'; +import { ColorContribution } from './color-application-contribution'; +import { ColorRegistry } from './color-registry'; export namespace CommonMenus { @@ -217,7 +219,7 @@ export const supportPaste = browser.isNative || (!browser.isChrome && document.q export const RECENT_COMMANDS_STORAGE_KEY = 'commands'; @injectable() -export class CommonFrontendContribution implements FrontendApplicationContribution, MenuContribution, CommandContribution, KeybindingContribution { +export class CommonFrontendContribution implements FrontendApplicationContribution, MenuContribution, CommandContribution, KeybindingContribution, ColorContribution { constructor( @inject(ApplicationShell) protected readonly shell: ApplicationShell, @@ -723,14 +725,30 @@ export class CommonFrontendContribution implements FrontendApplicationContributi this.quickOpenService.open({ onType: (_, accept) => accept(items) }, { - placeholder: 'Select File Icon Theme', - fuzzyMatchLabel: true, - selectIndex: () => items.findIndex(item => item.id === this.iconThemes.current), - onClose: () => { - if (resetTo) { - this.iconThemes.current = resetTo; - } + placeholder: 'Select File Icon Theme', + fuzzyMatchLabel: true, + selectIndex: () => items.findIndex(item => item.id === this.iconThemes.current), + onClose: () => { + if (resetTo) { + this.iconThemes.current = resetTo; } - }); + } + }); + } + + registerColors(colors: ColorRegistry): void { + colors.register( + // Base Colors + { id: 'selection.background', defaults: { dark: '#217daf', light: '#c0dbf1' }, description: 'Overall border color for focused elements. This color is only used if not overridden by a component.' }, + { id: 'icon.foreground', defaults: { dark: '#C5C5C5', light: '#424242', hc: '#FFFFFF' }, description: 'The default color for icons in the workbench.' }, + + // Activity Bar + { id: 'activityBar.background', defaults: { dark: '#333333', light: '#2C2C2C', hc: '#000000' }, description: 'Activity bar background color. The activity bar is showing on the far left or right and allows to switch between views of the side bar.' }, + { id: 'activityBar.border', defaults: { hc: '#6FC3DF' }, description: 'Activity bar border color separating to the side bar. The activity bar is showing on the far left or right and allows to switch between views of the side bar.' }, + { id: 'activityBar.activeBorder', defaults: { dark: '#FFFFFF', light: '#FFFFFF', hc: '#FFFFFF' }, description: 'Activity bar border color for the active item. The activity bar is showing on the far left or right and allows to switch between views of the side bar.' }, + { id: 'activityBar.foreground', defaults: { dark: '#FFFFFF', light: '#FFFFFF', hc: '#FFFFFF' }, description: 'Activity bar item foreground color when it is active. The activity bar is showing on the far left or right and allows to switch between views of the side bar.' }, + { id: 'activityBar.inactiveForeground', defaults: { dark: '#FFFFFF', light: '#FFFFFF', hc: '#FFFFFF' }, description: 'Activity bar item foreground color when it is active. The activity bar is showing on the far left or right and allows to switch between views of the side bar.' }, + // { id: '', defaults: { dark: '', light: '', hc: '' }, description: '' }, + ); } } diff --git a/packages/core/src/browser/frontend-application-module.ts b/packages/core/src/browser/frontend-application-module.ts index 5aa90abd3d998..bbcdae6668274 100644 --- a/packages/core/src/browser/frontend-application-module.ts +++ b/packages/core/src/browser/frontend-application-module.ts @@ -203,7 +203,7 @@ export const frontendApplicationModule = new ContainerModule((bind, unbind, isBo bind(ResourceContextKey).toSelf().inSingletonScope(); bind(CommonFrontendContribution).toSelf().inSingletonScope(); - [FrontendApplicationContribution, CommandContribution, KeybindingContribution, MenuContribution].forEach(serviceIdentifier => + [FrontendApplicationContribution, CommandContribution, KeybindingContribution, MenuContribution, ColorContribution].forEach(serviceIdentifier => bind(serviceIdentifier).toService(CommonFrontendContribution) ); diff --git a/packages/core/src/browser/style/index.css b/packages/core/src/browser/style/index.css index e6de16c4261fd..4ca509bec93f2 100644 --- a/packages/core/src/browser/style/index.css +++ b/packages/core/src/browser/style/index.css @@ -111,11 +111,11 @@ body { outline-style: solid; outline-offset: -1px; opacity: 1 !important; - outline-color: var(--theia-accent-color3); + outline-color: var(--theia-focusBorder); } ::selection { - background: var(--theia-selected-text-background); + background: var(--theia-selection-background); } .p-Widget:focus { diff --git a/packages/core/src/browser/style/sidepanel.css b/packages/core/src/browser/style/sidepanel.css index ee5287338744a..9625ce5761025 100644 --- a/packages/core/src/browser/style/sidepanel.css +++ b/packages/core/src/browser/style/sidepanel.css @@ -34,7 +34,7 @@ .p-TabBar.theia-app-sides { display: block; color: var(--theia-tab-font-color); - background: var(--theia-layout-color2); + background: var(--theia-activityBar-background); font-size: var(--theia-ui-font-size1); min-width: var(--theia-private-sidebar-tab-width); max-width: var(--theia-private-sidebar-tab-width); @@ -47,7 +47,7 @@ .p-TabBar.theia-app-sides .p-TabBar-tab { position: relative; padding: 11px 10px; - background: var(--theia-layout-color2); + background: var(--theia-activityBar-background); flex-direction: column; justify-content: center; align-items: center; @@ -56,12 +56,12 @@ } .p-TabBar.theia-app-left .p-TabBar-tab { - border-left: var(--theia-panel-border-width) solid var(--theia-layout-color2); + border-left: var(--theia-panel-border-width) solid var(--theia-activityBar-border); margin-right: var(--theia-panel-border-width); } .p-TabBar.theia-app-right .p-TabBar-tab { - border-right: var(--theia-panel-border-width) solid var(--theia-layout-color2); + border-right: var(--theia-panel-border-width) solid var(--theia-activityBar-border); margin-left: var(--theia-panel-border-width); } @@ -74,13 +74,13 @@ border-top: none; } -.p-TabBar.theia-app-left .p-TabBar-tab.p-mod-current.theia-mod-active { - border-left-color: var(--theia-accent-color2); +.p-TabBar.theia-app-left .p-TabBar-tab.p-mod-current { + border-left: var(--theia-panel-border-width) solid var(--theia-activityBar-activeBorder); border-top-color: transparent; } -.p-TabBar.theia-app-right .p-TabBar-tab.p-mod-current.theia-mod-active { - border-right-color: var(--theia-accent-color2); +.p-TabBar.theia-app-right .p-TabBar-tab.p-mod-current { + border-right-color: var(--theia-panel-border-width) solid var(--theia-activityBar-activeBorder); border-top-color: transparent; } @@ -92,7 +92,7 @@ .p-TabBar.theia-app-sides .p-TabBar-tabIcon { width: var(--theia-private-sidebar-icon-size); height: var(--theia-private-sidebar-icon-size); - background-color: var(--theia-tab-icon-color); + background-color: var(--theia-activityBar-inactiveForeground); opacity: 0.6; mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; @@ -105,6 +105,7 @@ .p-TabBar.theia-app-sides .p-mod-current .file-icon.p-TabBar-tabIcon, .p-TabBar.theia-app-sides .fa.p-TabBar-tabIcon:hover, .p-TabBar.theia-app-sides .p-mod-current .fa.p-TabBar-tabIcon { + background-color: var(--theia-activityBar-foreground); opacity: 1.0; background: none; } diff --git a/packages/search-in-workspace/src/browser/styles/index.css b/packages/search-in-workspace/src/browser/styles/index.css index f58cf5ccad095..dc8c9c34bff1b 100644 --- a/packages/search-in-workspace/src/browser/styles/index.css +++ b/packages/search-in-workspace/src/browser/styles/index.css @@ -73,7 +73,7 @@ } .t-siw-search-container .searchHeader .search-field-container.focused { - border-color: var(--theia-accent-color3); + border-color: var(--theia-focusBorder); } .t-siw-search-container .searchHeader .search-field { From 038e9a7513a1ce786576c29e1b11a2451c475109 Mon Sep 17 00:00:00 2001 From: Jan Bicker Date: Mon, 9 Dec 2019 16:49:27 +0000 Subject: [PATCH 07/65] Added color variables for sidebars and adapted regarding css files, so they make use of the new variables Signed-off-by: Jan Bicker --- .../core/src/browser/common-frontend-contribution.ts | 7 +++++++ packages/core/src/browser/style/sidepanel.css | 10 ++++++++-- packages/core/src/browser/style/view-container.css | 7 ++++--- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/packages/core/src/browser/common-frontend-contribution.ts b/packages/core/src/browser/common-frontend-contribution.ts index 81635c2c474c3..6d1ccb5b34f38 100644 --- a/packages/core/src/browser/common-frontend-contribution.ts +++ b/packages/core/src/browser/common-frontend-contribution.ts @@ -748,6 +748,13 @@ export class CommonFrontendContribution implements FrontendApplicationContributi { id: 'activityBar.activeBorder', defaults: { dark: '#FFFFFF', light: '#FFFFFF', hc: '#FFFFFF' }, description: 'Activity bar border color for the active item. The activity bar is showing on the far left or right and allows to switch between views of the side bar.' }, { id: 'activityBar.foreground', defaults: { dark: '#FFFFFF', light: '#FFFFFF', hc: '#FFFFFF' }, description: 'Activity bar item foreground color when it is active. The activity bar is showing on the far left or right and allows to switch between views of the side bar.' }, { id: 'activityBar.inactiveForeground', defaults: { dark: '#FFFFFF', light: '#FFFFFF', hc: '#FFFFFF' }, description: 'Activity bar item foreground color when it is active. The activity bar is showing on the far left or right and allows to switch between views of the side bar.' }, + + // Side Bar + { id: 'sideBar.background', defaults: { dark: '#252526', light: '#F3F3F3', hc: '#000000' }, description: 'Side bar background color. The side bar is the container for views like explorer and search.' }, + { id: 'sideBar.foreground', description: 'Side bar foreground color. The side bar is the container for views like explorer and search.' }, + { id: 'sideBarSectionHeader.background', defaults: { dark: '#80808033', light: '#80808033' }, description: 'Side bar section header background color. The side bar is the container for views like explorer and search.' }, + { id: 'sideBarSectionHeader.foreground', description: 'Side bar foreground color. The side bar is the container for views like explorer and search.' }, + { id: 'sideBarSectionHeader.border', defaults: { hc: '#6FC3DF' }, description: 'Side bar section header border color. The side bar is the container for views like explorer and search.' }, // { id: '', defaults: { dark: '', light: '', hc: '' }, description: '' }, ); } diff --git a/packages/core/src/browser/style/sidepanel.css b/packages/core/src/browser/style/sidepanel.css index 9625ce5761025..e0339107cfba1 100644 --- a/packages/core/src/browser/style/sidepanel.css +++ b/packages/core/src/browser/style/sidepanel.css @@ -142,9 +142,15 @@ } .theia-side-panel { - background-color: var(--theia-layout-color1); + background-color: var(--theia-sideBar-background); } +.p-Widget.theia-side-panel .p-Widget, +.p-Widget .theia-sidepanel-toolbar { + color: var(--theia-sideBar-foreground); +} + + /*----------------------------------------------------------------------------- | Perfect scrollbar @@ -212,7 +218,7 @@ display: flex; padding-left: 5px; align-items: center; - background-color: var(--theia-layout-color1); + background-color: var(--theia-sideBar-background); } .theia-sidepanel-toolbar .theia-sidepanel-title { diff --git a/packages/core/src/browser/style/view-container.css b/packages/core/src/browser/style/view-container.css index feecc2e8cc3f1..2343ca9cbe014 100644 --- a/packages/core/src/browser/style/view-container.css +++ b/packages/core/src/browser/style/view-container.css @@ -37,13 +37,13 @@ } .theia-view-container > .p-SplitPanel > .p-SplitPanel-handle:after { - background-color: var(--theia-menu-color0); + background-color: var(--theia-sideBarSectionHeader-border); min-height: 2px; min-width: 2px } .theia-view-container > .p-SplitPanel > .p-SplitPanel-handle { - background-color: var(--theia-menu-color0); + background-color: var(--theia-sideBarSectionHeader-border); } .theia-view-container .part { @@ -54,9 +54,10 @@ cursor: pointer; display: flex; align-items: center; - background: var(--theia-menu-color0); + background: var(--theia-sideBarSectionHeader-background); line-height: var(--theia-view-container-title-height); z-index: 10; + color: var(--theia-sideBarSectionHeader-foreground); } .theia-view-container .part > .header .theia-ExpansionToggle { From 77f66f63c628139960f33548a53bed4392443dad Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Mon, 9 Dec 2019 16:00:25 +0000 Subject: [PATCH 08/65] [git] apply vscode colors See https://code.visualstudio.com/api/references/theme-color#git-colors `gitDecoration.ignoredResourceForeground` and `gitDecoration.submoduleResourceForeground` are ignored, since they are not supported by git extension yet. Signed-off-by: Anton Kosyakov --- packages/git/src/browser/git-contribution.ts | 56 ++++++++++++++++++- .../git/src/browser/git-frontend-module.ts | 2 + packages/git/src/common/git-model.ts | 18 ++++-- 3 files changed, 70 insertions(+), 6 deletions(-) diff --git a/packages/git/src/browser/git-contribution.ts b/packages/git/src/browser/git-contribution.ts index 5dd8cf362b000..0f1c76a43099f 100644 --- a/packages/git/src/browser/git-contribution.ts +++ b/packages/git/src/browser/git-contribution.ts @@ -30,6 +30,8 @@ import { ScmWidget } from '@theia/scm/lib/browser/scm-widget'; import { ScmResource, ScmCommand } from '@theia/scm/lib/browser/scm-provider'; import { ProgressService } from '@theia/core/lib/common/progress-service'; import { GitPreferences } from './git-preferences'; +import { ColorContribution } from '@theia/core/lib/browser/color-application-contribution'; +import { ColorRegistry } from '@theia/core/lib/browser/color-registry'; export const EDITOR_CONTEXT_MENU_GIT = [...EDITOR_CONTEXT_MENU, '3_git']; @@ -191,7 +193,7 @@ export namespace GIT_COMMANDS { } @injectable() -export class GitContribution implements CommandContribution, MenuContribution, TabBarToolbarContribution { +export class GitContribution implements CommandContribution, MenuContribution, TabBarToolbarContribution, ColorContribution { static GIT_CHECKOUT = 'git.checkout'; static GIT_SYNC_STATUS = 'git-sync-status'; @@ -730,6 +732,58 @@ export class GitContribution implements CommandContribution, MenuContribution, T } } + + /** + * It should be aligned with https://code.visualstudio.com/api/references/theme-color#git-colors + */ + registerColors(colors: ColorRegistry): void { + colors.register({ + 'id': 'gitDecoration.addedResourceForeground', + 'description': 'Color for added resources.', + 'defaults': { + 'light': '#587c0c', + 'dark': '#81b88b', + 'hc': '#1b5225' + } + }, + { + 'id': 'gitDecoration.modifiedResourceForeground', + 'description': 'Color for modified resources.', + 'defaults': { + 'light': '#895503', + 'dark': '#E2C08D', + 'hc': '#E2C08D' + } + }, + { + 'id': 'gitDecoration.deletedResourceForeground', + 'description': 'Color for deleted resources.', + 'defaults': { + 'light': '#ad0707', + 'dark': '#c74e39', + 'hc': '#c74e39' + } + }, + { + 'id': 'gitDecoration.untrackedResourceForeground', + 'description': 'Color for untracked resources.', + 'defaults': { + 'light': '#007100', + 'dark': '#73C991', + 'hc': '#73C991' + } + }, + { + 'id': 'gitDecoration.conflictingResourceForeground', + 'description': 'Color for resources with conflicts.', + 'defaults': { + 'light': '#6c6cc4', + 'dark': '#6c6cc4', + 'hc': '#6c6cc4' + } + } + ); + } } export interface GitOpenFileOptions { readonly uri: URI diff --git a/packages/git/src/browser/git-frontend-module.ts b/packages/git/src/browser/git-frontend-module.ts index d755ea76ab71e..c375efb77edde 100644 --- a/packages/git/src/browser/git-frontend-module.ts +++ b/packages/git/src/browser/git-frontend-module.ts @@ -43,6 +43,7 @@ import { GitSyncService } from './git-sync-service'; import { GitErrorHandler } from './git-error-handler'; import { GitScmProvider } from './git-scm-provider'; import { GitFileChangeLabelProvider } from './git-file-change-label-provider'; +import { ColorContribution } from '@theia/core/lib/browser/color-application-contribution'; export default new ContainerModule(bind => { bindGitPreferences(bind); @@ -61,6 +62,7 @@ export default new ContainerModule(bind => { bind(MenuContribution).toService(GitContribution); bind(FrontendApplicationContribution).toService(GitContribution); bind(TabBarToolbarContribution).toService(GitContribution); + bind(ColorContribution).toService(GitContribution); bind(GitResourceResolver).toSelf().inSingletonScope(); bind(ResourceResolver).toService(GitResourceResolver); diff --git a/packages/git/src/common/git-model.ts b/packages/git/src/common/git-model.ts index 60bc971940ab1..3b5a32bd30df9 100644 --- a/packages/git/src/common/git-model.ts +++ b/packages/git/src/common/git-model.ts @@ -119,14 +119,22 @@ export namespace GitFileStatus { */ export const toAbbreviation = (status: GitFileStatus, staged?: boolean): string => GitFileStatus.toString(status, staged).charAt(0); + /** + * It should be aligned with https://github.com/microsoft/vscode/blob/0dfa355b3ad185a6289ba28a99c141ab9e72d2be/extensions/git/src/repository.ts#L197 + */ export function getColor(status: GitFileStatus, staged?: boolean): string { switch (status) { - case GitFileStatus.New: return 'var(--theia-success-color0)'; - case GitFileStatus.Renamed: // Fall through. + case GitFileStatus.New: { + if (!staged) { + return 'var(--theia-gitDecoration-untrackedResourceForeground)'; + } + return 'var(--theia-gitDecoration-addedResourceForeground)'; + } + case GitFileStatus.Renamed: return 'var(--theia-gitDecoration-untrackedResourceForeground)'; case GitFileStatus.Copied: // Fall through. - case GitFileStatus.Modified: return 'var(--theia-brand-color0)'; - case GitFileStatus.Deleted: return 'var(--theia-warn-color0)'; - case GitFileStatus.Conflicted: return 'var(--theia-error-color0)'; + case GitFileStatus.Modified: return 'var(--theia-gitDecoration-modifiedResourceForeground)'; + case GitFileStatus.Deleted: return 'var(--theia-gitDecoration-deletedResourceForeground)'; + case GitFileStatus.Conflicted: return 'var(--theia-gitDecoration-conflictingResourceForeground)'; } } From 7212ec85f2b2cb55825ef7df1497927dd673286b Mon Sep 17 00:00:00 2001 From: Jan Bicker Date: Mon, 9 Dec 2019 17:23:00 +0000 Subject: [PATCH 09/65] Added color variables for trees and adapted respecting css files by adding those variables. Signed-off-by: Jan Bicker --- .../core/src/browser/common-frontend-contribution.ts | 9 +++++++++ packages/core/src/browser/style/tree.css | 9 ++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/packages/core/src/browser/common-frontend-contribution.ts b/packages/core/src/browser/common-frontend-contribution.ts index 6d1ccb5b34f38..bda0d527d212d 100644 --- a/packages/core/src/browser/common-frontend-contribution.ts +++ b/packages/core/src/browser/common-frontend-contribution.ts @@ -755,6 +755,15 @@ export class CommonFrontendContribution implements FrontendApplicationContributi { id: 'sideBarSectionHeader.background', defaults: { dark: '#80808033', light: '#80808033' }, description: 'Side bar section header background color. The side bar is the container for views like explorer and search.' }, { id: 'sideBarSectionHeader.foreground', description: 'Side bar foreground color. The side bar is the container for views like explorer and search.' }, { id: 'sideBarSectionHeader.border', defaults: { hc: '#6FC3DF' }, description: 'Side bar section header border color. The side bar is the container for views like explorer and search.' }, + + // Lists and Trees + { id: 'list.activeSelectionBackground', defaults: { dark: '#094771', light: '#0074E8' }, description: 'List/Tree background color for the selected item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.' }, + { id: 'list.activeSelectionForeground', defaults: { dark: '#FFF', light: '#FFF' }, description: 'List/Tree foreground color for the selected item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.' }, + { id: 'list.inactiveSelectionBackground', defaults: { dark: '#37373D', light: '#E4E6F1' }, description: 'List/Tree background color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.' }, + { id: 'list.inactiveSelectionForeground', description: 'List/Tree foreground color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.' }, + + { id: 'list.hoverBackground', defaults: { dark: '#2A2D2E', light: '#F0F0F0' }, description: 'List/Tree background when hovering over items using the mouse.' }, + { id: 'list.hoverForeground', description: 'List/Tree foreground when hovering over items using the mouse.' }, // { id: '', defaults: { dark: '', light: '', hc: '' }, description: '' }, ); } diff --git a/packages/core/src/browser/style/tree.css b/packages/core/src/browser/style/tree.css index 7dbe99cabfef3..ac88ca7941804 100644 --- a/packages/core/src/browser/style/tree.css +++ b/packages/core/src/browser/style/tree.css @@ -47,7 +47,8 @@ } .theia-TreeNode:hover { - background: var(--theia-accent-color4); + background: var(--theia-list-hoverBackground); + color: var(--theia-list-hoverForeground); cursor: pointer; } @@ -84,11 +85,13 @@ .theia-Tree:focus .theia-TreeNode.theia-mod-selected, .theia-Tree .ReactVirtualized__List:focus .theia-TreeNode.theia-mod-selected { - background: var(--theia-accent-color3); + background: var(--theia-list-activeSelectionBackground); + color: var(--theia-list-activeSelectionForeground); } .theia-Tree .theia-TreeNode.theia-mod-selected { - background: var(--theia-layout-color4); + background: var(--theia-list-inactiveSelectionBackground); + color: var(--theia-list-inactiveSelectionForeground); } .theia-TreeNode.theia-mod-not-selectable { From 367820ddb8ed88c546143f3c54c695adb3cd44f0 Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Mon, 9 Dec 2019 19:51:23 +0000 Subject: [PATCH 10/65] apply welcome page vscode colors Signed-off-by: Anton Kosyakov --- packages/core/src/browser/color-registry.ts | 60 ++++++++++++++++++- .../browser/common-frontend-contribution.ts | 29 +++++---- .../src/browser/monaco-color-registry.ts | 24 +++++++- packages/monaco/src/browser/monaco-loader.ts | 5 +- packages/monaco/src/typings/monaco/index.d.ts | 15 ++++- 5 files changed, 112 insertions(+), 21 deletions(-) diff --git a/packages/core/src/browser/color-registry.ts b/packages/core/src/browser/color-registry.ts index 22d5519b10ba8..9025ec575b67e 100644 --- a/packages/core/src/browser/color-registry.ts +++ b/packages/core/src/browser/color-registry.ts @@ -18,10 +18,64 @@ import { injectable } from 'inversify'; import { DisposableCollection, Disposable } from '../common/disposable'; import { Emitter } from '../common/event'; +/** + * Either be a reference to an existing color or a color value as a hex string, rgba, or hsla. + */ +export type Color = string | RGBA | HSLA; +export namespace Color { + export function rgba(r: number, g: number, b: number, a: number = 1): Color { + return { r, g, b, a }; + } + export function hsla(h: number, s: number, l: number, a: number = 1): Color { + return { h, s, l, a }; + } + export const white = rgba(255, 255, 255, 1); + export const black = rgba(0, 0, 0, 1); +} +export interface RGBA { + /** + * Red: integer in [0-255] + */ + readonly r: number; + + /** + * Green: integer in [0-255] + */ + readonly g: number; + + /** + * Blue: integer in [0-255] + */ + readonly b: number; + + /** + * Alpha: float in [0-1] + */ + readonly a: number; +} +export interface HSLA { + /** + * Hue: integer in [0, 360] + */ + readonly h: number; + /** + * Saturation: float in [0, 1] + */ + readonly s: number; + /** + * Luminosity: float in [0, 1] + */ + readonly l: number; + /** + * Alpha: float in [0, 1] + */ + readonly a: number; +} + export interface ColorDefaults { - light?: string - dark?: string - hc?: string + light?: Color + dark?: Color + hc?: Color } export interface ColorDefinition { diff --git a/packages/core/src/browser/common-frontend-contribution.ts b/packages/core/src/browser/common-frontend-contribution.ts index bda0d527d212d..4a517ea76b48e 100644 --- a/packages/core/src/browser/common-frontend-contribution.ts +++ b/packages/core/src/browser/common-frontend-contribution.ts @@ -40,7 +40,7 @@ import { PrefixQuickOpenService, QuickOpenItem, QuickOpenMode, QuickOpenService import { environment } from '@theia/application-package/lib/environment'; import { IconThemeService } from './icon-theme-service'; import { ColorContribution } from './color-application-contribution'; -import { ColorRegistry } from './color-registry'; +import { ColorRegistry, Color } from './color-registry'; export namespace CommonMenus { @@ -725,24 +725,25 @@ export class CommonFrontendContribution implements FrontendApplicationContributi this.quickOpenService.open({ onType: (_, accept) => accept(items) }, { - placeholder: 'Select File Icon Theme', - fuzzyMatchLabel: true, - selectIndex: () => items.findIndex(item => item.id === this.iconThemes.current), - onClose: () => { - if (resetTo) { - this.iconThemes.current = resetTo; + placeholder: 'Select File Icon Theme', + fuzzyMatchLabel: true, + selectIndex: () => items.findIndex(item => item.id === this.iconThemes.current), + onClose: () => { + if (resetTo) { + this.iconThemes.current = resetTo; + } } - } - }); + }); } registerColors(colors: ColorRegistry): void { colors.register( - // Base Colors + // Base Colors should be aligned with https://code.visualstudio.com/api/references/theme-color#base-colors + // if not yet contributed by Monaco, check runtime css variables to learn { id: 'selection.background', defaults: { dark: '#217daf', light: '#c0dbf1' }, description: 'Overall border color for focused elements. This color is only used if not overridden by a component.' }, { id: 'icon.foreground', defaults: { dark: '#C5C5C5', light: '#424242', hc: '#FFFFFF' }, description: 'The default color for icons in the workbench.' }, - // Activity Bar + // Activity Bar colors should be aligned with https://code.visualstudio.com/api/references/theme-color#activity-bar { id: 'activityBar.background', defaults: { dark: '#333333', light: '#2C2C2C', hc: '#000000' }, description: 'Activity bar background color. The activity bar is showing on the far left or right and allows to switch between views of the side bar.' }, { id: 'activityBar.border', defaults: { hc: '#6FC3DF' }, description: 'Activity bar border color separating to the side bar. The activity bar is showing on the far left or right and allows to switch between views of the side bar.' }, { id: 'activityBar.activeBorder', defaults: { dark: '#FFFFFF', light: '#FFFFFF', hc: '#FFFFFF' }, description: 'Activity bar border color for the active item. The activity bar is showing on the far left or right and allows to switch between views of the side bar.' }, @@ -765,6 +766,12 @@ export class CommonFrontendContribution implements FrontendApplicationContributi { id: 'list.hoverBackground', defaults: { dark: '#2A2D2E', light: '#F0F0F0' }, description: 'List/Tree background when hovering over items using the mouse.' }, { id: 'list.hoverForeground', description: 'List/Tree foreground when hovering over items using the mouse.' }, // { id: '', defaults: { dark: '', light: '', hc: '' }, description: '' }, + + // Welcome Page colors should be aligned with https://code.visualstudio.com/api/references/theme-color#welcome-page + { id: 'welcomePage.background', description: 'Background color for the Welcome page.' }, + { id: 'welcomePage.buttonBackground', defaults: { dark: Color.rgba(0, 0, 0, .2), light: Color.rgba(0, 0, 0, .04), hc: Color.black }, description: 'Background color for the buttons on the Welcome page.' }, + { id: 'welcomePage.buttonHoverBackground', defaults: { dark: Color.rgba(200, 235, 255, .072), light: Color.rgba(0, 0, 0, .10) }, description: 'Hover background color for the buttons on the Welcome page.' }, + { id: 'walkThrough.embeddedEditorBackground', defaults: { dark: Color.rgba(0, 0, 0, .4), light: '#f4f4f4' }, description: 'Background color for the embedded editors on the Interactive Playground.' }, ); } } diff --git a/packages/monaco/src/browser/monaco-color-registry.ts b/packages/monaco/src/browser/monaco-color-registry.ts index c4f118665efad..96b5a179217a8 100644 --- a/packages/monaco/src/browser/monaco-color-registry.ts +++ b/packages/monaco/src/browser/monaco-color-registry.ts @@ -15,7 +15,7 @@ ********************************************************************************/ import { injectable } from 'inversify'; -import { ColorRegistry, ColorDefinition } from '@theia/core/lib/browser/color-registry'; +import { ColorRegistry, ColorDefinition, Color } from '@theia/core/lib/browser/color-registry'; import { Disposable } from '@theia/core/lib/common/disposable'; @injectable() @@ -36,8 +36,28 @@ export class MonacoColorRegistry extends ColorRegistry { } protected doRegister(definition: ColorDefinition): Disposable { - const identifier = this.monacoColorRegistry.registerColor(definition.id, definition.defaults, definition.description); + let defaults: monaco.color.ColorDefaults | undefined; + if (definition.defaults) { + defaults = {}; + defaults.dark = this.toColor(definition.defaults.dark); + defaults.light = this.toColor(definition.defaults.light); + defaults.hc = this.toColor(definition.defaults.hc); + } + const identifier = this.monacoColorRegistry.registerColor(definition.id, defaults, definition.description); return Disposable.create(() => this.monacoColorRegistry.deregisterColor(identifier)); } + protected toColor(value: Color | undefined): string | monaco.color.Color | undefined { + if (!value || typeof value === 'string') { + return value; + } + if ('r' in value) { + const { r, g, b, a } = value; + return new monaco.color.Color(new monaco.color.RGBA(r, g, b, a)); + } else { + const { h, s, l, a } = value; + return new monaco.color.Color(new monaco.color.HSLA(h, s, l, a)); + } + } + } diff --git a/packages/monaco/src/browser/monaco-loader.ts b/packages/monaco/src/browser/monaco-loader.ts index b7455839b92c7..cf97c381a36f1 100644 --- a/packages/monaco/src/browser/monaco-loader.ts +++ b/packages/monaco/src/browser/monaco-loader.ts @@ -62,6 +62,7 @@ export function loadMonaco(vsRequire: any): Promise { 'vs/base/common/filters', 'vs/platform/theme/common/styler', 'vs/platform/theme/common/colorRegistry', + 'vs/base/common/color', 'vs/base/common/platform', 'vs/editor/common/modes', 'vs/editor/contrib/suggest/suggest', @@ -77,7 +78,7 @@ export function loadMonaco(vsRequire: any): Promise { ], (css: any, html: any, commands: any, actions: any, keybindingsRegistry: any, keybindingResolver: any, resolvedKeybinding: any, keybindingLabels: any, keyCodes: any, mime: any, editorExtensions: any, simpleServices: any, standaloneServices: any, quickOpenWidget: any, quickOpenModel: any, - filters: any, styler: any, colorRegistry: any, + filters: any, styler: any, colorRegistry: any, color: any, platform: any, modes: any, suggest: any, snippetParser: any, configuration: any, configurationModels: any, codeEditorService: any, codeEditorServiceImpl: any, @@ -93,7 +94,7 @@ export function loadMonaco(vsRequire: any): Promise { global.monaco.quickOpen = Object.assign({}, quickOpenWidget, quickOpenModel); global.monaco.filters = filters; global.monaco.theme = styler; - global.monaco.color = colorRegistry; + global.monaco.color = Object.assign({}, colorRegistry, color); global.monaco.platform = platform; global.monaco.editorExtensions = editorExtensions; global.monaco.modes = modes; diff --git a/packages/monaco/src/typings/monaco/index.d.ts b/packages/monaco/src/typings/monaco/index.d.ts index 6e7653b6d5182..e0a14e20d5900 100644 --- a/packages/monaco/src/typings/monaco/index.d.ts +++ b/packages/monaco/src/typings/monaco/index.d.ts @@ -540,13 +540,22 @@ declare module monaco.theme { } declare module monaco.color { + export class RGBA { + constructor(r: number, g: number, b: number, a?: number); + } + export class HSLA { + constructor(h: number, s: number, l: number, a: number); + } + export class Color { + constructor(arg: RGBA | HSLA); + } export interface ColorContribution { readonly id: string; } export interface ColorDefaults { - light?: string; - dark?: string; - hc?: string; + light?: string | Color; + dark?: string | Color; + hc?: string | Color; } export interface IColorRegistry { getColors(): ColorContribution[]; From 5111c894281911f12285808cef6eaf60fabba399 Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Mon, 9 Dec 2019 20:39:36 +0000 Subject: [PATCH 11/65] apply debug vscode colors Signed-off-by: Anton Kosyakov --- ...debug-frontend-application-contribution.ts | 19 ++++++++++++++++++- .../src/browser/debug-frontend-module.ts | 2 ++ packages/debug/src/browser/style/index.css | 12 +++--------- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/packages/debug/src/browser/debug-frontend-application-contribution.ts b/packages/debug/src/browser/debug-frontend-application-contribution.ts index 91e58b29bb0c2..db410d2bad7da 100644 --- a/packages/debug/src/browser/debug-frontend-application-contribution.ts +++ b/packages/debug/src/browser/debug-frontend-application-contribution.ts @@ -43,6 +43,8 @@ import { DebugSchemaUpdater } from './debug-schema-updater'; import { DebugPreferences } from './debug-preferences'; import { TabBarToolbarContribution, TabBarToolbarRegistry, TabBarToolbarItem } from '@theia/core/lib/browser/shell/tab-bar-toolbar'; import { DebugSessionOptions } from './debug-session-options'; +import { ColorContribution } from '@theia/core/lib/browser/color-application-contribution'; +import { ColorRegistry } from '@theia/core/lib/browser/color-registry'; export namespace DebugMenus { export const DEBUG = [...MAIN_MENU_BAR, '6_debug']; @@ -323,7 +325,7 @@ updateTheme(); ThemeService.get().onThemeChange(() => updateTheme()); @injectable() -export class DebugFrontendApplicationContribution extends AbstractViewContribution implements TabBarToolbarContribution { +export class DebugFrontendApplicationContribution extends AbstractViewContribution implements TabBarToolbarContribution, ColorContribution { @inject(DebugService) protected readonly debug: DebugService; @@ -1019,4 +1021,19 @@ export class DebugFrontendApplicationContribution extends AbstractViewContributi protected isPosition(position: monaco.Position): boolean { return (position instanceof monaco.Position); } + + registerColors(colors: ColorRegistry): void { + colors.register( + { + id: 'editor.stackFrameHighlightBackground', + defaults: { dark: '#ffff0033', light: '#ffff6673', hc: '#fff600' }, + description: 'Background color for the highlight of line at the top stack frame position.' + }, { + id: 'editor.focusedStackFrameHighlightBackground', + defaults: { dark: '#7abd7a4d', light: '#cee7ce73', hc: '#cee7ce' }, + description: 'Background color for the highlight of line at focused stack frame position.' + } + ); + } + } diff --git a/packages/debug/src/browser/debug-frontend-module.ts b/packages/debug/src/browser/debug-frontend-module.ts index bc62cefce199c..c1c605514a8f2 100644 --- a/packages/debug/src/browser/debug-frontend-module.ts +++ b/packages/debug/src/browser/debug-frontend-module.ts @@ -51,6 +51,7 @@ import { bindLaunchPreferences } from './preferences/launch-preferences'; import { DebugPrefixConfiguration } from './debug-prefix-configuration'; import { CommandContribution } from '@theia/core/lib/common/command'; import { TabBarToolbarContribution } from '@theia/core/lib/browser/shell/tab-bar-toolbar'; +import { ColorContribution } from '@theia/core/lib/browser/color-application-contribution'; export default new ContainerModule((bind: interfaces.Bind) => { bind(DebugCallStackItemTypeKey).toDynamicValue(({ container }) => @@ -89,6 +90,7 @@ export default new ContainerModule((bind: interfaces.Bind) => { bindViewContribution(bind, DebugFrontendApplicationContribution); bind(FrontendApplicationContribution).toService(DebugFrontendApplicationContribution); bind(TabBarToolbarContribution).toService(DebugFrontendApplicationContribution); + bind(ColorContribution).toService(DebugFrontendApplicationContribution); bind(DebugSessionContributionRegistryImpl).toSelf().inSingletonScope(); bind(DebugSessionContributionRegistry).toService(DebugSessionContributionRegistryImpl); diff --git a/packages/debug/src/browser/style/index.css b/packages/debug/src/browser/style/index.css index 03c26aeafb751..03df2a91b6596 100644 --- a/packages/debug/src/browser/style/index.css +++ b/packages/debug/src/browser/style/index.css @@ -254,10 +254,7 @@ background: url('current-and-breakpoint.svg') center center no-repeat; } .monaco-editor .view-overlays .theia-debug-top-stack-frame-line { - background: #ffff6673; -} -.monaco-editor.vs-dark .view-overlays .theia-debug-top-stack-frame-line { - background: #ffff0033; + background: var(--theia-editor-stackFrameHighlightBackground); } .monaco-editor .theia-debug-focused-stack-frame { @@ -267,11 +264,8 @@ background: url('stackframe-and-breakpoint.svg') center center no-repeat; } .monaco-editor .view-overlays .theia-debug-focused-stack-frame-line { - background: #cee7ce73; - } -.monaco-editor.vs-dark .view-overlays .theia-debug-focused-stack-frame-line { - background: #7abd7a4d; - } + background: var(--theia-editor-focusedStackFrameHighlightBackground); +} /** Toolbars */ From 11a389a47f8fdb207b2d167bf3c9c4267442bdd7 Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Tue, 10 Dec 2019 14:12:34 +0000 Subject: [PATCH 12/65] apply panel vscode colors Signed-off-by: Anton Kosyakov --- .../browser/common-frontend-contribution.ts | 41 +++++++++++++++++++ packages/core/src/browser/style/dockpanel.css | 4 ++ packages/core/src/browser/style/sidepanel.css | 37 ++++++++++++++++- packages/core/src/browser/style/tabs.css | 27 ------------ 4 files changed, 81 insertions(+), 28 deletions(-) diff --git a/packages/core/src/browser/common-frontend-contribution.ts b/packages/core/src/browser/common-frontend-contribution.ts index 4a517ea76b48e..62df2078b0b65 100644 --- a/packages/core/src/browser/common-frontend-contribution.ts +++ b/packages/core/src/browser/common-frontend-contribution.ts @@ -767,6 +767,47 @@ export class CommonFrontendContribution implements FrontendApplicationContributi { id: 'list.hoverForeground', description: 'List/Tree foreground when hovering over items using the mouse.' }, // { id: '', defaults: { dark: '', light: '', hc: '' }, description: '' }, + // Panel colors should be aligned with https://code.visualstudio.com/api/references/theme-color#panel-colors + { + id: 'panel.background', defaults: { + dark: 'editor.background', light: 'editor.background', hc: 'editor.background' + }, description: 'Panel background color. Panels are shown below the editor area and contain views like output and integrated terminal.' + }, + { + id: 'panel.border', defaults: { + dark: Color.rgba(128, 128, 128, 0.35), light: Color.rgba(128, 128, 128, 0.35), hc: 'contrastBorder' + }, description: 'Panel border color to separate the panel from the editor. Panels are shown below the editor area and contain views like output and integrated terminal.' + }, + { + id: 'panel.dropBackground', defaults: { + dark: Color.rgba(255, 255, 255, 0.12), light: Color.rgba(38, 119, 203, 0.18), hc: Color.rgba(255, 255, 255, 0.12) + }, description: 'Drag and drop feedback color for the panel title items. The color should have transparency so that the panel entries can still shine through. Panels are shown below the editor area and contain views like output and integrated terminal.' + }, + { + id: 'panelTitle.activeForeground', defaults: { + dark: '#E7E7E7', light: '#424242', hc: Color.white + }, description: 'Title color for the active panel. Panels are shown below the editor area and contain views like output and integrated terminal.' + }, + { + id: 'panelTitle.inactiveForeground', defaults: { + dark: Color.rgba(231, 231, 231, 0.6), light: Color.rgba(66, 66, 66, 0.75), hc: Color.white + }, description: 'Title color for the inactive panel. Panels are shown below the editor area and contain views like output and integrated terminal.' + }, + { + id: 'panelTitle.activeBorder', defaults: { + dark: Color.rgba(231, 231, 231, 0.6), light: Color.rgba(66, 66, 66, 0.75), hc: 'contrastBorder' + }, description: 'Border color for the active panel title. Panels are shown below the editor area and contain views like output and integrated terminal.' + }, + { + id: 'panelInput.border', defaults: { light: '#ddd' }, + description: 'Input box border for inputs in the panel.' + }, + { + id: 'imagePreview.border', defaults: { + dark: Color.rgba(128, 128, 128, 0.35), light: Color.rgba(128, 128, 128, 0.35), hc: 'contrastBorder' + }, description: 'Border color for image in image preview.' + }, + // Welcome Page colors should be aligned with https://code.visualstudio.com/api/references/theme-color#welcome-page { id: 'welcomePage.background', description: 'Background color for the Welcome page.' }, { id: 'welcomePage.buttonBackground', defaults: { dark: Color.rgba(0, 0, 0, .2), light: Color.rgba(0, 0, 0, .04), hc: Color.black }, description: 'Background color for the buttons on the Welcome page.' }, diff --git a/packages/core/src/browser/style/dockpanel.css b/packages/core/src/browser/style/dockpanel.css index e55e30e435339..1c73e2f7b20eb 100644 --- a/packages/core/src/browser/style/dockpanel.css +++ b/packages/core/src/browser/style/dockpanel.css @@ -57,3 +57,7 @@ .p-DockPanel-overlay.p-mod-root-center { border-width: 2px; } + +.p-DockPanel-overlay.p-mod-root-bottom { + background: var(--theia-panel-dropBackground); +} diff --git a/packages/core/src/browser/style/sidepanel.css b/packages/core/src/browser/style/sidepanel.css index e0339107cfba1..43c9c091d9754 100644 --- a/packages/core/src/browser/style/sidepanel.css +++ b/packages/core/src/browser/style/sidepanel.css @@ -183,9 +183,44 @@ |----------------------------------------------------------------------------*/ #theia-bottom-content-panel { - border-top: var(--theia-panel-border-width) solid var(--theia-border-color1); + background: var(--theia-panel-background); } +#theia-bottom-content-panel input { + border-color: var(--theia-panelInput-border); +} + +#theia-bottom-content-panel .p-DockPanel-handle, +#theia-bottom-content-panel .p-DockPanel-handle::after { + background: none; + border: none; +} + +#theia-bottom-content-panel .p-DockPanel-handle[data-orientation='horizontal'] { + border-left: var(--theia-border-width) solid var(--theia-panel-border); +} + +#theia-bottom-content-panel .p-TabBar { + border-top: var(--theia-border-width) solid var(--theia-panel-border); + background: inherit; +} + +#theia-bottom-content-panel .p-TabBar-tab { + background: inherit; +} + +#theia-bottom-content-panel .p-TabBar-tab:not(.p-mod-current) { + color: var(--theia-panelTitle-inactiveForeground); +} + +#theia-bottom-content-panel .p-TabBar-tab.p-mod-current { + color: var(--theia-panelTitle-activeForeground); + border-top: var(--theia-border-width) solid var(--theia-panelTitle-activeBorder); +} + +#theia-bottom-content-panel .p-TabBar-tab.p-mod-current.theia-mod-active { + border-top-color: var(--theia-accent-color2); +} /*----------------------------------------------------------------------------- | Hidden tab bars used for rendering vertical side bars diff --git a/packages/core/src/browser/style/tabs.css b/packages/core/src/browser/style/tabs.css index 70fc66f1e2450..156e8c9d9bea3 100644 --- a/packages/core/src/browser/style/tabs.css +++ b/packages/core/src/browser/style/tabs.css @@ -19,23 +19,6 @@ font-size: var(--theia-ui-font-size1); } -.p-TabBar[data-orientation='horizontal'].theia-app-bottom { - background: var(--theia-layout-color0); -} - -.p-TabBar[data-orientation='horizontal'].theia-app-bottom .p-TabBar-tab { - background: var(--theia-layout-color0); -} - -.p-TabBar[data-orientation='horizontal'].theia-app-bottom .p-TabBar-tab.p-mod-current { - background: var(--theia-layout-color0); - border-top: var(--theia-border-width) solid var(--theia-ui-font-color2); -} - -.p-TabBar[data-orientation='horizontal'].theia-app-bottom .p-TabBar-tab.p-mod-current.theia-mod-active { - border-top-color: var(--theia-accent-color2); -} - .p-TabBar[data-orientation='horizontal'] { overflow-x: hidden; overflow-y: hidden; @@ -46,12 +29,6 @@ cursor: pointer; } -.p-TabBar[data-orientation='horizontal'] .p-TabBar-content { - flex: none; - align-items: flex-end; - z-index: 1; -} - .p-TabBar[data-orientation='horizontal'] .p-TabBar-tab { flex: none; height: calc(var(--theia-private-horizontal-tab-height) + var(--theia-private-horizontal-tab-scrollbar-rail-height) / 2); @@ -62,10 +39,6 @@ align-items: center; } -.p-TabBar[data-orientation='horizontal'] .p-TabBar-tab:last-child { - border-right: var(--theia-border-width) solid var(--theia-border-color0); -} - .p-TabBar[data-orientation='horizontal'] .p-TabBar-tab .theia-tab-icon-label { display: flex; line-height: var(--theia-content-line-height); From 94370db21ae7293b6eed830ca65477e0702043b8 Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Tue, 10 Dec 2019 15:18:44 +0000 Subject: [PATCH 13/65] apply terminal vscode colors Signed-off-by: Anton Kosyakov --- .../browser/terminal-frontend-contribution.ts | 66 ++++++- .../src/browser/terminal-frontend-module.ts | 11 +- .../src/browser/terminal-theme-service.ts | 187 ++++++++++++++++++ .../src/browser/terminal-widget-impl.ts | 75 +------ packages/terminal/src/browser/terminal.css | 3 +- 5 files changed, 265 insertions(+), 77 deletions(-) create mode 100644 packages/terminal/src/browser/terminal-theme-service.ts diff --git a/packages/terminal/src/browser/terminal-frontend-contribution.ts b/packages/terminal/src/browser/terminal-frontend-contribution.ts index 74b2228b51426..f1e2aaf884ea6 100644 --- a/packages/terminal/src/browser/terminal-frontend-contribution.ts +++ b/packages/terminal/src/browser/terminal-frontend-contribution.ts @@ -43,6 +43,9 @@ import URI from '@theia/core/lib/common/uri'; import { MAIN_MENU_BAR } from '@theia/core'; import { WorkspaceService } from '@theia/workspace/lib/browser'; import { ContextKeyService } from '@theia/core/lib/browser/context-key-service'; +import { ColorContribution } from '@theia/core/lib/browser/color-application-contribution'; +import { ColorRegistry } from '@theia/core/lib/browser/color-registry'; +import { terminalAnsiColorMap } from './terminal-theme-service'; export namespace TerminalMenus { export const TERMINAL = [...MAIN_MENU_BAR, '7_terminal']; @@ -91,7 +94,7 @@ export namespace TerminalCommands { } @injectable() -export class TerminalFrontendContribution implements TerminalService, CommandContribution, MenuContribution, KeybindingContribution, TabBarToolbarContribution { +export class TerminalFrontendContribution implements TerminalService, CommandContribution, MenuContribution, KeybindingContribution, TabBarToolbarContribution, ColorContribution { constructor( @inject(ApplicationShell) protected readonly shell: ApplicationShell, @@ -393,4 +396,65 @@ export class TerminalFrontendContribution implements TerminalService, CommandCon termWidget.start(); this.open(termWidget, { widgetOptions: options }); } + + /** + * It should be aligned with https://code.visualstudio.com/api/references/theme-color#integrated-terminal-colors + */ + registerColors(colors: ColorRegistry): void { + colors.register({ + id: 'terminal.background', + defaults: { + dark: 'panel.background', + light: 'panel.background', + hc: 'panel.background' + }, + description: 'The background color of the terminal, this allows coloring the terminal differently to the panel.' + }); + colors.register({ + id: 'terminal.foreground', + defaults: { + light: '#333333', + dark: '#CCCCCC', + hc: '#FFFFFF' + }, + description: 'The foreground color of the terminal.' + }); + colors.register({ + id: 'terminalCursor.foreground', + description: 'The foreground color of the terminal cursor.' + }); + colors.register({ + id: 'terminalCursor.background', + description: 'The background color of the terminal cursor. Allows customizing the color of a character overlapped by a block cursor.' + }); + colors.register({ + id: 'terminal.selectionBackground', + defaults: { + light: '#00000040', + dark: '#FFFFFF40', + hc: '#FFFFFF80' + }, + description: 'The selection background color of the terminal.' + }); + colors.register({ + id: 'terminal.border', + defaults: { + light: 'panel.border', + dark: 'panel.border', + hc: 'panel.border' + }, + description: 'The color of the border that separates split panes within the terminal. This defaults to panel.border.' + }); + // tslint:disable-next-line:forin + for (const id in terminalAnsiColorMap) { + const entry = terminalAnsiColorMap[id]; + const colorName = id.substring(13); + colors.register({ + id, + defaults: entry.defaults, + description: `'${colorName}' ANSI color in the terminal.` + }); + } + } + } diff --git a/packages/terminal/src/browser/terminal-frontend-module.ts b/packages/terminal/src/browser/terminal-frontend-module.ts index 0ddb8dff5bffe..b0310ede73e6d 100644 --- a/packages/terminal/src/browser/terminal-frontend-module.ts +++ b/packages/terminal/src/browser/terminal-frontend-module.ts @@ -14,6 +14,9 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ +import '../../src/browser/terminal.css'; +import 'xterm/lib/xterm.css'; + import { ContainerModule, Container } from 'inversify'; import { CommandContribution, MenuContribution } from '@theia/core/lib/common'; import { bindContributionProvider } from '@theia/core'; @@ -34,10 +37,9 @@ import { TerminalContribution } from './terminal-contribution'; import { TerminalLinkmatcherFiles } from './terminal-linkmatcher-files'; import { TerminalLinkmatcherDiffPre, TerminalLinkmatcherDiffPost } from './terminal-linkmatcher-diff'; import { TerminalQuickOpenService, TerminalQuickOpenContribution } from './terminal-quick-open-service'; - -import '../../src/browser/terminal.css'; -import 'xterm/lib/xterm.css'; import { TerminalCopyOnSelectionHandler } from './terminal-copy-on-selection-handler'; +import { ColorContribution } from '@theia/core/lib/browser/color-application-contribution'; +import { TerminalThemeService } from './terminal-theme-service'; export default new ContainerModule(bind => { bindTerminalPreferences(bind); @@ -75,9 +77,10 @@ export default new ContainerModule(bind => { bind(identifier).toService(TerminalQuickOpenContribution); } + bind(TerminalThemeService).toSelf().inSingletonScope(); bind(TerminalFrontendContribution).toSelf().inSingletonScope(); bind(TerminalService).toService(TerminalFrontendContribution); - for (const identifier of [CommandContribution, MenuContribution, KeybindingContribution, TabBarToolbarContribution]) { + for (const identifier of [CommandContribution, MenuContribution, KeybindingContribution, TabBarToolbarContribution, ColorContribution]) { bind(identifier).toService(TerminalFrontendContribution); } diff --git a/packages/terminal/src/browser/terminal-theme-service.ts b/packages/terminal/src/browser/terminal-theme-service.ts new file mode 100644 index 0000000000000..d8a13264c2c66 --- /dev/null +++ b/packages/terminal/src/browser/terminal-theme-service.ts @@ -0,0 +1,187 @@ +/******************************************************************************** + * Copyright (C) 2019 TypeFox 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 * as Xterm from 'xterm'; +import { injectable, inject } from 'inversify'; +import { ColorRegistry, ColorDefaults } from '@theia/core/lib/browser/color-registry'; +import { ThemeService } from '@theia/core/lib/browser/theming'; + +/** + * It should be aligned with https://github.com/microsoft/vscode/blob/0dfa355b3ad185a6289ba28a99c141ab9e72d2be/src/vs/workbench/contrib/terminal/common/terminalColorRegistry.ts#L40 + */ +export const terminalAnsiColorMap: { [key: string]: { index: number, defaults: ColorDefaults } } = { + 'terminal.ansiBlack': { + index: 0, + defaults: { + light: '#000000', + dark: '#000000', + hc: '#000000' + } + }, + 'terminal.ansiRed': { + index: 1, + defaults: { + light: '#cd3131', + dark: '#cd3131', + hc: '#cd0000' + } + }, + 'terminal.ansiGreen': { + index: 2, + defaults: { + light: '#00BC00', + dark: '#0DBC79', + hc: '#00cd00' + } + }, + 'terminal.ansiYellow': { + index: 3, + defaults: { + light: '#949800', + dark: '#e5e510', + hc: '#cdcd00' + } + }, + 'terminal.ansiBlue': { + index: 4, + defaults: { + light: '#0451a5', + dark: '#2472c8', + hc: '#0000ee' + } + }, + 'terminal.ansiMagenta': { + index: 5, + defaults: { + light: '#bc05bc', + dark: '#bc3fbc', + hc: '#cd00cd' + } + }, + 'terminal.ansiCyan': { + index: 6, + defaults: { + light: '#0598bc', + dark: '#11a8cd', + hc: '#00cdcd' + } + }, + 'terminal.ansiWhite': { + index: 7, + defaults: { + light: '#555555', + dark: '#e5e5e5', + hc: '#e5e5e5' + } + }, + 'terminal.ansiBrightBlack': { + index: 8, + defaults: { + light: '#666666', + dark: '#666666', + hc: '#7f7f7f' + } + }, + 'terminal.ansiBrightRed': { + index: 9, + defaults: { + light: '#cd3131', + dark: '#f14c4c', + hc: '#ff0000' + } + }, + 'terminal.ansiBrightGreen': { + index: 10, + defaults: { + light: '#14CE14', + dark: '#23d18b', + hc: '#00ff00' + } + }, + 'terminal.ansiBrightYellow': { + index: 11, + defaults: { + light: '#b5ba00', + dark: '#f5f543', + hc: '#ffff00' + } + }, + 'terminal.ansiBrightBlue': { + index: 12, + defaults: { + light: '#0451a5', + dark: '#3b8eea', + hc: '#5c5cff' + } + }, + 'terminal.ansiBrightMagenta': { + index: 13, + defaults: { + light: '#bc05bc', + dark: '#d670d6', + hc: '#ff00ff' + } + }, + 'terminal.ansiBrightCyan': { + index: 14, + defaults: { + light: '#0598bc', + dark: '#29b8db', + hc: '#00ffff' + } + }, + 'terminal.ansiBrightWhite': { + index: 15, + defaults: { + light: '#a5a5a5', + dark: '#e5e5e5', + hc: '#ffffff' + } + } +}; + +@injectable() +export class TerminalThemeService { + + @inject(ColorRegistry) + protected readonly colorRegistry: ColorRegistry; + + readonly onDidChange = ThemeService.get().onThemeChange; + + get theme(): Xterm.ITheme { + const foregroundColor = this.colorRegistry.getCurrentColor('terminal.foreground'); + const backgroundColor = this.colorRegistry.getCurrentColor('terminal.background') || this.colorRegistry.getCurrentColor('panel.background'); + const cursorColor = this.colorRegistry.getCurrentColor('terminalCursor.foreground') || foregroundColor; + const cursorAccentColor = this.colorRegistry.getCurrentColor('terminalCursor.background') || backgroundColor; + const selectionColor = this.colorRegistry.getCurrentColor('terminal.selectionBackground'); + + const theme: Xterm.ITheme = { + background: backgroundColor, + foreground: foregroundColor, + cursor: cursorColor, + cursorAccent: cursorAccentColor, + selection: selectionColor + }; + // tslint:disable-next-line:forin + for (const id in terminalAnsiColorMap) { + const colorName = id.substring(13); + // tslint:disable-next-line:no-any + (theme as any)[colorName] = this.colorRegistry.getCurrentColor(id); + } + return theme; + } + +} diff --git a/packages/terminal/src/browser/terminal-widget-impl.ts b/packages/terminal/src/browser/terminal-widget-impl.ts index f04d0ac74ba4b..0c8088e7890d8 100644 --- a/packages/terminal/src/browser/terminal-widget-impl.ts +++ b/packages/terminal/src/browser/terminal-widget-impl.ts @@ -25,7 +25,6 @@ import { ShellTerminalServerProxy } from '../common/shell-terminal-protocol'; import { terminalsPath } from '../common/terminal-protocol'; import { IBaseTerminalServer } from '../common/base-terminal-protocol'; import { TerminalWatcher } from '../common/terminal-watcher'; -import { ThemeService } from '@theia/core/lib/browser/theming'; import { TerminalWidgetOptions, TerminalWidget } from './base/terminal-widget'; import { MessageConnection } from 'vscode-jsonrpc'; import { Deferred } from '@theia/core/lib/common/promise-util'; @@ -34,6 +33,7 @@ import { TerminalContribution } from './terminal-contribution'; import URI from '@theia/core/lib/common/uri'; import { TerminalService } from './base/terminal-service'; import { TerminalCopyOnSelectionHandler } from './terminal-copy-on-selection-handler'; +import { TerminalThemeService } from './terminal-theme-service'; export const TERMINAL_WIDGET_FACTORY_ID = 'terminal'; @@ -42,17 +42,6 @@ export interface TerminalWidgetFactoryOptions extends Partial; @inject(TerminalService) protected readonly terminalService: TerminalService; @inject(TerminalCopyOnSelectionHandler) protected readonly copyOnSelectionHandler: TerminalCopyOnSelectionHandler; + @inject(TerminalThemeService) protected readonly themeService: TerminalThemeService; protected readonly onDidOpenEmitter = new Emitter(); readonly onDidOpen: Event = this.onDidOpenEmitter.event; @@ -98,9 +87,6 @@ export class TerminalWidgetImpl extends TerminalWidget implements StatefulWidget this.title.closable = true; this.addClass('terminal-container'); - /* Read CSS properties from the page and apply them to the terminal. */ - const cssProps = this.getCSSPropertiesFromPage(); - this.term = new Xterm.Terminal({ experimentalCharAtlas: 'dynamic', cursorBlink: false, @@ -112,12 +98,7 @@ export class TerminalWidgetImpl extends TerminalWidget implements StatefulWidget lineHeight: this.preferences['terminal.integrated.lineHeight'], scrollback: this.preferences['terminal.integrated.scrollback'], rendererType: this.getTerminalRendererType(this.preferences['terminal.integrated.rendererType']), - theme: { - foreground: cssProps.foreground, - background: cssProps.background, - cursor: cssProps.foreground, - selection: cssProps.selection - }, + theme: this.themeService.theme }); this.hoverMessage = document.createElement('div'); @@ -156,15 +137,7 @@ export class TerminalWidgetImpl extends TerminalWidget implements StatefulWidget } })); - this.toDispose.push(this.themeService.onThemeChange(c => { - const changedProps = this.getCSSPropertiesFromPage(); - this.term.setOption('theme', { - foreground: changedProps.foreground, - background: changedProps.background, - cursor: changedProps.foreground, - selection: cssProps.selection - }); - })); + this.toDispose.push(this.themeService.onDidChange(() => this.term.setOption('theme', this.themeService.theme))); this.attachCustomKeyEventHandler(); const titleChangeListenerDispose = this.term.onTitleChange((title: string) => { if (this.options.useServerTitle) { @@ -278,46 +251,6 @@ export class TerminalWidgetImpl extends TerminalWidget implements StatefulWidget } } - /* Get the font family and size from the CSS custom properties defined in - the root element. */ - private getCSSPropertiesFromPage(): TerminalCSSProperties { - /* Helper to look up a CSS property value and throw an error if it's - not defined. */ - function lookup(props: CSSStyleDeclaration, name: string): string { - /* There is sometimes an extra space in the front, remove it. */ - const value = props.getPropertyValue(name).trim(); - if (!value) { - throw new Error(`Couldn\'t find value of ${name}`); - } - - return value; - } - - /* Get the CSS properties of (aka :root in css). */ - const htmlElementProps = getComputedStyle(document.documentElement!); - - const foreground = lookup(htmlElementProps, '--theia-ui-font-color1'); - const background = lookup(htmlElementProps, '--theia-layout-color0'); - const selection = lookup(htmlElementProps, '--theia-transparent-accent-color2'); - - /* xterm.js expects #XXX of #XXXXXX for colors. */ - const colorRe = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/; - - if (!foreground.match(colorRe)) { - throw new Error(`Unexpected format for --theia-ui-font-color1 (${foreground})`); - } - - if (!background.match(colorRe)) { - throw new Error(`Unexpected format for --theia-layout-color0 (${background})`); - } - - return { - foreground, - background, - selection - }; - } - /** * Create a new shell terminal in the back-end and attach it to a * new terminal widget. diff --git a/packages/terminal/src/browser/terminal.css b/packages/terminal/src/browser/terminal.css index 7af055b69c70a..bf4a9f21882a1 100644 --- a/packages/terminal/src/browser/terminal.css +++ b/packages/terminal/src/browser/terminal.css @@ -18,9 +18,10 @@ width:100%; height:100%; padding: var(--theia-code-padding); + background: var(--theia-terminal-background); } .xterm .xterm-screen canvas { /* fix random 1px white border on terminal in Firefox. See https://github.com/eclipse-theia/theia/issues/4665 */ - border: 1px solid var(--theia-layout-color0); + border: 1px solid var(--theia-terminal-background); } From 377d1a30c812d3941aa833e1189c04dc0c5bafb9 Mon Sep 17 00:00:00 2001 From: Jan Bicker Date: Tue, 10 Dec 2019 15:30:12 +0000 Subject: [PATCH 14/65] Apply colors for sidepanel and trees/lists --- .../browser/common-frontend-contribution.ts | 24 ++++++++++--------- .../core/src/browser/style/search-box.css | 3 ++- packages/core/src/browser/style/sidepanel.css | 16 +++++++++---- packages/core/src/browser/style/tabs.css | 2 +- packages/core/src/browser/style/tree.css | 2 +- packages/keymaps/src/browser/style/index.css | 2 +- 6 files changed, 30 insertions(+), 19 deletions(-) diff --git a/packages/core/src/browser/common-frontend-contribution.ts b/packages/core/src/browser/common-frontend-contribution.ts index 62df2078b0b65..6245fab748260 100644 --- a/packages/core/src/browser/common-frontend-contribution.ts +++ b/packages/core/src/browser/common-frontend-contribution.ts @@ -725,15 +725,15 @@ export class CommonFrontendContribution implements FrontendApplicationContributi this.quickOpenService.open({ onType: (_, accept) => accept(items) }, { - placeholder: 'Select File Icon Theme', - fuzzyMatchLabel: true, - selectIndex: () => items.findIndex(item => item.id === this.iconThemes.current), - onClose: () => { - if (resetTo) { - this.iconThemes.current = resetTo; - } + placeholder: 'Select File Icon Theme', + fuzzyMatchLabel: true, + selectIndex: () => items.findIndex(item => item.id === this.iconThemes.current), + onClose: () => { + if (resetTo) { + this.iconThemes.current = resetTo; } - }); + } + }); } registerColors(colors: ColorRegistry): void { @@ -757,15 +757,17 @@ export class CommonFrontendContribution implements FrontendApplicationContributi { id: 'sideBarSectionHeader.foreground', description: 'Side bar foreground color. The side bar is the container for views like explorer and search.' }, { id: 'sideBarSectionHeader.border', defaults: { hc: '#6FC3DF' }, description: 'Side bar section header border color. The side bar is the container for views like explorer and search.' }, - // Lists and Trees + // Lists and Trees colors should be aligned with https://code.visualstudio.com/api/references/theme-color#lists-and-trees + // if not yet contributed by Monaco, check runtime css variables to learn + // not yet supported/no respective elements in theia + // list.focusBackground, list.focusForeground, list.inactiveFocusBackground, list.filterMatchBorder, list.dropBackground, listFilterWidget.outline, listFilterWidget.noMatchesOutline, tree.indentGuidesStroke { id: 'list.activeSelectionBackground', defaults: { dark: '#094771', light: '#0074E8' }, description: 'List/Tree background color for the selected item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.' }, { id: 'list.activeSelectionForeground', defaults: { dark: '#FFF', light: '#FFF' }, description: 'List/Tree foreground color for the selected item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.' }, { id: 'list.inactiveSelectionBackground', defaults: { dark: '#37373D', light: '#E4E6F1' }, description: 'List/Tree background color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.' }, { id: 'list.inactiveSelectionForeground', description: 'List/Tree foreground color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.' }, - { id: 'list.hoverBackground', defaults: { dark: '#2A2D2E', light: '#F0F0F0' }, description: 'List/Tree background when hovering over items using the mouse.' }, { id: 'list.hoverForeground', description: 'List/Tree foreground when hovering over items using the mouse.' }, - // { id: '', defaults: { dark: '', light: '', hc: '' }, description: '' }, + { id: 'list.filterMatchBackground', defaults: { dark: 'editor.findMatchHighlightBackground', light: 'editor.findMatchHighlightBackground' }, description: 'Background color of the filtered match.' }, // Panel colors should be aligned with https://code.visualstudio.com/api/references/theme-color#panel-colors { diff --git a/packages/core/src/browser/style/search-box.css b/packages/core/src/browser/style/search-box.css index 763d4d3d05cd3..f99545fbf70d5 100644 --- a/packages/core/src/browser/style/search-box.css +++ b/packages/core/src/browser/style/search-box.css @@ -23,7 +23,7 @@ align-items: baseline; box-shadow: var(--theia-border-width) var(--theia-border-width) var(--theia-border-color0); line-height: var(--theia-private-horizontal-tab-height); - background-color: var(--theia-layout-color0); + background-color: var(--theia-listFilterWidget-background); z-index: 1; } @@ -31,6 +31,7 @@ flex-grow: 1; line-height: calc(var(--theia-private-horizontal-tab-height) * 0.8); max-width: 6rem; + background-color: var(--theia-listFilterWidget-background); } .theia-search-button { diff --git a/packages/core/src/browser/style/sidepanel.css b/packages/core/src/browser/style/sidepanel.css index 43c9c091d9754..da65cc99261e6 100644 --- a/packages/core/src/browser/style/sidepanel.css +++ b/packages/core/src/browser/style/sidepanel.css @@ -56,12 +56,12 @@ } .p-TabBar.theia-app-left .p-TabBar-tab { - border-left: var(--theia-panel-border-width) solid var(--theia-activityBar-border); + border-right: var(--theia-panel-border-width) solid var(--theia-activityBar-border); margin-right: var(--theia-panel-border-width); } .p-TabBar.theia-app-right .p-TabBar-tab { - border-right: var(--theia-panel-border-width) solid var(--theia-activityBar-border); + border-left: var(--theia-panel-border-width) solid var(--theia-activityBar-border); margin-left: var(--theia-panel-border-width); } @@ -79,9 +79,17 @@ border-top-color: transparent; } +.p-TabBar.theia-app-left .p-TabBar-tab.p-mod-current.theia-mod-active { + border-left: var(--theia-panel-border-width) solid var(--theia-focusBorder); +} + .p-TabBar.theia-app-right .p-TabBar-tab.p-mod-current { - border-right-color: var(--theia-panel-border-width) solid var(--theia-activityBar-activeBorder); - border-top-color: transparent; + border-right-color: var(--theia-panel-border-width) solid var(--theia-activityBar-activeBorder); + border-top-color: transparent; +} + +.p-TabBar.theia-app-right .p-TabBar-tab.p-mod-current.theia-mod-active { + border-left: var(--theia-panel-border-width) solid var(--theia-focusBorder); } .p-TabBar.theia-app-sides .p-TabBar-tabLabel, diff --git a/packages/core/src/browser/style/tabs.css b/packages/core/src/browser/style/tabs.css index 156e8c9d9bea3..f80dd3984a333 100644 --- a/packages/core/src/browser/style/tabs.css +++ b/packages/core/src/browser/style/tabs.css @@ -68,7 +68,7 @@ /* This is the main application level active tab: only 1 exists. */ .p-TabBar .p-TabBar-tab.p-mod-current.theia-mod-active { - border-top-color: var(--theia-accent-color2); + border-top-color: var(--theia-focusBorder); } .p-TabBar.theia-app-centers .p-TabBar-tabIcon, diff --git a/packages/core/src/browser/style/tree.css b/packages/core/src/browser/style/tree.css index ac88ca7941804..d337184799e51 100644 --- a/packages/core/src/browser/style/tree.css +++ b/packages/core/src/browser/style/tree.css @@ -121,7 +121,7 @@ } .theia-TreeNodeSegment mark { - background-color: var(--theia-word-highlight-match-color1); + background-color: var(--theia-list-filterMatchBackground); color: var(--theia-ui-font-color1); } diff --git a/packages/keymaps/src/browser/style/index.css b/packages/keymaps/src/browser/style/index.css index ca8eb2f9c319f..ba07af81469c5 100644 --- a/packages/keymaps/src/browser/style/index.css +++ b/packages/keymaps/src/browser/style/index.css @@ -27,7 +27,7 @@ .fuzzy-match { font-weight: 600; - color: var(--theia-brand-color1); + color: var(--theia-list-highlightForeground); } .kb-actions { From 8a4c5c6789dbec4c21b2d123810b840b5ea80b91 Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Wed, 11 Dec 2019 09:21:03 +0000 Subject: [PATCH 15/65] apply editor Groups & tabs vscode colors Signed-off-by: Anton Kosyakov --- packages/core/src/browser/color-registry.ts | 9 +- .../browser/common-frontend-contribution.ts | 210 ++++++++++++++++-- packages/core/src/browser/core-preferences.ts | 6 + packages/core/src/browser/style/dockpanel.css | 9 +- packages/core/src/browser/style/sidepanel.css | 8 +- packages/core/src/browser/style/tabs.css | 94 +++++++- .../src/browser/monaco-color-registry.ts | 6 +- packages/monaco/src/typings/monaco/index.d.ts | 9 +- 8 files changed, 305 insertions(+), 46 deletions(-) diff --git a/packages/core/src/browser/color-registry.ts b/packages/core/src/browser/color-registry.ts index 9025ec575b67e..8a852dd8973ba 100644 --- a/packages/core/src/browser/color-registry.ts +++ b/packages/core/src/browser/color-registry.ts @@ -21,7 +21,7 @@ import { Emitter } from '../common/event'; /** * Either be a reference to an existing color or a color value as a hex string, rgba, or hsla. */ -export type Color = string | RGBA | HSLA; +export type Color = string | RGBA | HSLA | TransparentColor; export namespace Color { export function rgba(r: number, g: number, b: number, a: number = 1): Color { return { r, g, b, a }; @@ -31,6 +31,13 @@ export namespace Color { } export const white = rgba(255, 255, 255, 1); export const black = rgba(0, 0, 0, 1); + export function transparent(v: string, f: number): TransparentColor { + return { v, f }; + } +} +export interface TransparentColor { + v: string + f: number } export interface RGBA { /** diff --git a/packages/core/src/browser/common-frontend-contribution.ts b/packages/core/src/browser/common-frontend-contribution.ts index 6245fab748260..eb0d52cbfeb40 100644 --- a/packages/core/src/browser/common-frontend-contribution.ts +++ b/packages/core/src/browser/common-frontend-contribution.ts @@ -41,6 +41,7 @@ import { environment } from '@theia/application-package/lib/environment'; import { IconThemeService } from './icon-theme-service'; import { ColorContribution } from './color-application-contribution'; import { ColorRegistry, Color } from './color-registry'; +import { CorePreferences } from './core-preferences'; export namespace CommonMenus { @@ -253,6 +254,9 @@ export class CommonFrontendContribution implements FrontendApplicationContributi @inject(QuickOpenService) protected readonly quickOpenService: QuickOpenService; + @inject(CorePreferences) + protected readonly preferences: CorePreferences; + @postConstruct() protected init(): void { this.contextKeyService.createKey('isLinux', OS.type() === OS.Type.Linux); @@ -261,6 +265,16 @@ export class CommonFrontendContribution implements FrontendApplicationContributi this.initResourceContextKeys(); this.registerCtrlWHandling(); + + this.updateStyles(); + this.preferences.onPreferenceChanged(() => this.updateStyles()); + } + + protected updateStyles(): void { + document.body.classList.remove('theia-editor-highlightModifiedTabs'); + if (this.preferences['workbench.editor.highlightModifiedTabs']) { + document.body.classList.add('theia-editor-highlightModifiedTabs'); + } } onStart(): void { @@ -725,15 +739,15 @@ export class CommonFrontendContribution implements FrontendApplicationContributi this.quickOpenService.open({ onType: (_, accept) => accept(items) }, { - placeholder: 'Select File Icon Theme', - fuzzyMatchLabel: true, - selectIndex: () => items.findIndex(item => item.id === this.iconThemes.current), - onClose: () => { - if (resetTo) { - this.iconThemes.current = resetTo; + placeholder: 'Select File Icon Theme', + fuzzyMatchLabel: true, + selectIndex: () => items.findIndex(item => item.id === this.iconThemes.current), + onClose: () => { + if (resetTo) { + this.iconThemes.current = resetTo; + } } - } - }); + }); } registerColors(colors: ColorRegistry): void { @@ -760,7 +774,8 @@ export class CommonFrontendContribution implements FrontendApplicationContributi // Lists and Trees colors should be aligned with https://code.visualstudio.com/api/references/theme-color#lists-and-trees // if not yet contributed by Monaco, check runtime css variables to learn // not yet supported/no respective elements in theia - // list.focusBackground, list.focusForeground, list.inactiveFocusBackground, list.filterMatchBorder, list.dropBackground, listFilterWidget.outline, listFilterWidget.noMatchesOutline, tree.indentGuidesStroke + // list.focusBackground, list.focusForeground, list.inactiveFocusBackground, list.filterMatchBorder, + // list.dropBackground, listFilterWidget.outline, listFilterWidget.noMatchesOutline, tree.indentGuidesStroke { id: 'list.activeSelectionBackground', defaults: { dark: '#094771', light: '#0074E8' }, description: 'List/Tree background color for the selected item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.' }, { id: 'list.activeSelectionForeground', defaults: { dark: '#FFF', light: '#FFF' }, description: 'List/Tree foreground color for the selected item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.' }, { id: 'list.inactiveSelectionBackground', defaults: { dark: '#37373D', light: '#E4E6F1' }, description: 'List/Tree background color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.' }, @@ -769,6 +784,173 @@ export class CommonFrontendContribution implements FrontendApplicationContributi { id: 'list.hoverForeground', description: 'List/Tree foreground when hovering over items using the mouse.' }, { id: 'list.filterMatchBackground', defaults: { dark: 'editor.findMatchHighlightBackground', light: 'editor.findMatchHighlightBackground' }, description: 'Background color of the filtered match.' }, + // Edito Group & Tabs colors should be aligned with https://code.visualstudio.com/api/references/theme-color#editor-groups-tabs + { + id: 'editorGroup.border', + defaults: { + dark: '#444444', + light: '#E7E7E7', + hc: 'contrastBorder' + }, + description: 'Color to separate multiple editor groups from each other. Editor groups are the containers of editors.' + }, + { + id: 'editorGroup.dropBackground', + defaults: { + dark: Color.transparent('#53595D', 0.5), + light: Color.transparent('#2677CB', 0.18) + }, + description: 'Background color when dragging editors around. The color should have transparency so that the editor contents can still shine through.' + }, + { + id: 'editorGroupHeader.tabsBackground', + defaults: { + dark: '#252526', + light: '#F3F3F3' + }, + description: 'Background color of the editor group title header when tabs are enabled. Editor groups are the containers of editors.' + }, + { + id: 'editorGroupHeader.tabsBorder', + defaults: { + hc: 'contrastBorder' + }, + description: 'Border color of the editor group title header when tabs are enabled. Editor groups are the containers of editors.' + }, + { + id: 'tab.activeBackground', + defaults: { + dark: 'editor.background', + light: 'editor.background', + hc: 'editor.background' + }, + description: 'Active tab background color. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' + }, + { + id: 'tab.unfocusedActiveBackground', + defaults: { + dark: 'tab.activeBackground', + light: 'tab.activeBackground', + hc: 'tab.activeBackground' + }, + description: 'Active tab background color in an unfocused group. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' + }, + { + id: 'tab.inactiveBackground', + defaults: { + dark: '#2D2D2D', + light: '#ECECEC' + }, + description: 'Inactive tab background color. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' + }, + { + id: 'tab.activeForeground', + defaults: { + dark: Color.white, + light: '#333333', + hc: Color.white + }, description: 'Active tab foreground color in an active group. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' + }, + { + id: 'tab.inactiveForeground', defaults: { + dark: Color.transparent('tab.activeForeground', 0.5), + light: Color.transparent('tab.activeForeground', 0.7), + hc: Color.white + }, description: 'Inactive tab foreground color in an active group. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' + }, + { + id: 'tab.unfocusedActiveForeground', defaults: { + dark: Color.transparent('tab.activeForeground', 0.5), + light: Color.transparent('tab.activeForeground', 0.7), + hc: Color.white + }, description: 'Active tab foreground color in an unfocused group. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' + }, + { + id: 'tab.unfocusedInactiveForeground', defaults: { + dark: Color.transparent('tab.inactiveForeground', 0.5), + light: Color.transparent('tab.inactiveForeground', 0.5), + hc: Color.white + }, description: 'Inactive tab foreground color in an unfocused group. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' + }, + { + id: 'tab.border', defaults: { + dark: '#252526', + light: '#F3F3F3', + hc: 'contrastBorder' + }, description: 'Border to separate tabs from each other. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' + }, + { + id: 'tab.activeBorder', + description: 'Border on the bottom of an active tab. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' + }, + { + id: 'tab.unfocusedActiveBorder', + defaults: { + dark: Color.transparent('tab.activeBorder', 0.5), + light: Color.transparent('tab.activeBorder', 0.7) + }, + description: 'Border on the bottom of an active tab in an unfocused group. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' + }, + { + id: 'tab.activeBorderTop', + defaults: { + dark: 'focusBorder', + light: 'focusBorder' + }, + description: 'Border to the top of an active tab. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' + }, + { + id: 'tab.unfocusedActiveBorderTop', defaults: { + dark: Color.transparent('tab.activeBorderTop', 0.5), + light: Color.transparent('tab.activeBorderTop', 0.7) + }, description: 'Border to the top of an active tab in an unfocused group. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' + }, + { + id: 'tab.hoverBackground', + description: 'Tab background color when hovering. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' + }, { + id: 'tab.unfocusedHoverBackground', defaults: { + dark: Color.transparent('tab.hoverBackground', 0.5), + light: Color.transparent('tab.hoverBackground', 0.7) + }, description: 'Tab background color in an unfocused group when hovering. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' + }, + { + id: 'tab.hoverBorder', + description: 'Border to highlight tabs when hovering. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' + }, { + id: 'tab.unfocusedHoverBorder', defaults: { + dark: Color.transparent('tab.hoverBorder', 0.5), + light: Color.transparent('tab.hoverBorder', 0.7) + }, description: 'Border to highlight tabs in an unfocused group when hovering. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' + }, + { + id: 'tab.activeModifiedBorder', defaults: { + dark: '#3399CC', + light: '#33AAEE' + }, description: 'Border on the top of modified (dirty) active tabs in an active group. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' + }, + { + id: 'tab.inactiveModifiedBorder', defaults: { + dark: Color.transparent('tab.activeModifiedBorder', 0.5), + light: Color.transparent('tab.activeModifiedBorder', 0.5), + hc: Color.white + }, description: 'Border on the top of modified (dirty) inactive tabs in an active group. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' + }, + { + id: 'tab.unfocusedActiveModifiedBorder', defaults: { + dark: Color.transparent('tab.activeModifiedBorder', 0.5), + light: Color.transparent('tab.activeModifiedBorder', 0.7), + hc: Color.white + }, description: 'Border on the top of modified (dirty) active tabs in an unfocused group. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' + }, + { + id: 'tab.unfocusedInactiveModifiedBorder', defaults: { + dark: Color.transparent('tab.inactiveModifiedBorder', 0.5), + light: Color.transparent('tab.inactiveModifiedBorder', 0.5), + hc: Color.white + }, description: 'Border on the top of modified (dirty) inactive tabs in an unfocused group. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' + }, + // Panel colors should be aligned with https://code.visualstudio.com/api/references/theme-color#panel-colors { id: 'panel.background', defaults: { @@ -777,12 +959,12 @@ export class CommonFrontendContribution implements FrontendApplicationContributi }, { id: 'panel.border', defaults: { - dark: Color.rgba(128, 128, 128, 0.35), light: Color.rgba(128, 128, 128, 0.35), hc: 'contrastBorder' + dark: Color.transparent('#808080', 0.35), light: Color.transparent('#808080', 0.35), hc: 'contrastBorder' }, description: 'Panel border color to separate the panel from the editor. Panels are shown below the editor area and contain views like output and integrated terminal.' }, { id: 'panel.dropBackground', defaults: { - dark: Color.rgba(255, 255, 255, 0.12), light: Color.rgba(38, 119, 203, 0.18), hc: Color.rgba(255, 255, 255, 0.12) + dark: Color.rgba(255, 255, 255, 0.12), light: Color.transparent('#2677CB', 0.18), hc: Color.rgba(255, 255, 255, 0.12) }, description: 'Drag and drop feedback color for the panel title items. The color should have transparency so that the panel entries can still shine through. Panels are shown below the editor area and contain views like output and integrated terminal.' }, { @@ -792,12 +974,12 @@ export class CommonFrontendContribution implements FrontendApplicationContributi }, { id: 'panelTitle.inactiveForeground', defaults: { - dark: Color.rgba(231, 231, 231, 0.6), light: Color.rgba(66, 66, 66, 0.75), hc: Color.white + dark: Color.transparent('panelTitle.activeForeground', 0.6), light: Color.transparent('panelTitle.activeForeground', 0.75), hc: Color.white }, description: 'Title color for the inactive panel. Panels are shown below the editor area and contain views like output and integrated terminal.' }, { id: 'panelTitle.activeBorder', defaults: { - dark: Color.rgba(231, 231, 231, 0.6), light: Color.rgba(66, 66, 66, 0.75), hc: 'contrastBorder' + dark: 'panelTitle.activeForeground', light: 'panelTitle.activeForeground', hc: 'contrastBorder' }, description: 'Border color for the active panel title. Panels are shown below the editor area and contain views like output and integrated terminal.' }, { @@ -806,7 +988,7 @@ export class CommonFrontendContribution implements FrontendApplicationContributi }, { id: 'imagePreview.border', defaults: { - dark: Color.rgba(128, 128, 128, 0.35), light: Color.rgba(128, 128, 128, 0.35), hc: 'contrastBorder' + dark: Color.transparent('#808080', 0.35), light: Color.transparent('#808080', 0.35), hc: 'contrastBorder' }, description: 'Border color for image in image preview.' }, diff --git a/packages/core/src/browser/core-preferences.ts b/packages/core/src/browser/core-preferences.ts index 2721a58d77c9b..aa7c0efbe59a0 100644 --- a/packages/core/src/browser/core-preferences.ts +++ b/packages/core/src/browser/core-preferences.ts @@ -29,6 +29,11 @@ export const corePreferenceSchema: PreferenceSchema = { default: 'singleClick', description: 'Controls how to open items in trees using the mouse.' }, + 'workbench.editor.highlightModifiedTabs': { + 'type': 'boolean', + 'description': 'Controls whether a top border is drawn on modified (dirty) editor tabs or not.', + 'default': false + }, 'application.confirmExit': { type: 'string', enum: [ @@ -52,6 +57,7 @@ export interface CoreConfiguration { 'application.confirmExit': 'never' | 'ifRequired' | 'always'; 'workbench.list.openMode': 'singleClick' | 'doubleClick'; 'workbench.commandPalette.history': number; + 'workbench.editor.highlightModifiedTabs': boolean } export const CorePreferences = Symbol('CorePreferences'); diff --git a/packages/core/src/browser/style/dockpanel.css b/packages/core/src/browser/style/dockpanel.css index 1c73e2f7b20eb..dc07695ed6d6d 100644 --- a/packages/core/src/browser/style/dockpanel.css +++ b/packages/core/src/browser/style/dockpanel.css @@ -29,21 +29,14 @@ .p-DockPanel-handle[data-orientation='vertical'] { min-height: var(--theia-border-width); - border-top: var(--theia-border-width) solid var(--theia-border-color1); } .p-DockPanel-handle[data-orientation='horizontal'] { min-width: var(--theia-border-width); - border-left: var(--theia-border-width) solid var(--theia-border-color1); -} - -.p-DockPanel-handle[data-orientation='horizontal']:after { - background-color: var(--theia-layout-color0); - border-left: var(--theia-border-width) solid var(--theia-border-color1); } .p-DockPanel-overlay { - background: rgba(33, 150, 243, 0.1); + background: var(--theia-editorGroup-dropBackground); border: var(--theia-border-width) dashed var(--theia-brand-color1); transition-property: top, left, right, bottom; transition-duration: 150ms; diff --git a/packages/core/src/browser/style/sidepanel.css b/packages/core/src/browser/style/sidepanel.css index da65cc99261e6..e4d242a98e34b 100644 --- a/packages/core/src/browser/style/sidepanel.css +++ b/packages/core/src/browser/style/sidepanel.css @@ -198,12 +198,6 @@ border-color: var(--theia-panelInput-border); } -#theia-bottom-content-panel .p-DockPanel-handle, -#theia-bottom-content-panel .p-DockPanel-handle::after { - background: none; - border: none; -} - #theia-bottom-content-panel .p-DockPanel-handle[data-orientation='horizontal'] { border-left: var(--theia-border-width) solid var(--theia-panel-border); } @@ -227,7 +221,7 @@ } #theia-bottom-content-panel .p-TabBar-tab.p-mod-current.theia-mod-active { - border-top-color: var(--theia-accent-color2); + border-top-color: var(--theia-focusBorder); } /*----------------------------------------------------------------------------- diff --git a/packages/core/src/browser/style/tabs.css b/packages/core/src/browser/style/tabs.css index f80dd3984a333..c881d2246c289 100644 --- a/packages/core/src/browser/style/tabs.css +++ b/packages/core/src/browser/style/tabs.css @@ -54,21 +54,93 @@ | Tabs in the center area (main and bottom) |----------------------------------------------------------------------------*/ -#theia-main-content-panel .p-Widget.p-DockPanel-widget { - background-color: var(--theia-layout-color0); +#theia-main-content-panel { + background: var(--theia-editor-background); } -/* This is a current tab of a tab bar: each tab bar has 1. */ -.p-TabBar .p-TabBar-tab.p-mod-current { - min-height: calc(var(--theia-private-horizontal-tab-height) + var(--theia-border-width)); - background: var(--theia-layout-color0); - color: var(--theia-ui-font-color0); - border-top: var(--theia-border-width) solid var(--theia-layout-color0); +#theia-main-content-panel .p-DockPanel-handle[data-orientation='horizontal'] { + border-left: var(--theia-border-width) solid var(--theia-editorGroup-border); } -/* This is the main application level active tab: only 1 exists. */ -.p-TabBar .p-TabBar-tab.p-mod-current.theia-mod-active { - border-top-color: var(--theia-focusBorder); +#theia-main-content-panel .p-DockPanel-handle[data-orientation='vertical'] + .p-TabBar { + border-top: var(--theia-border-width) solid var(--theia-editorGroup-border); +} + +#theia-main-content-panel .p-TabBar .p-TabBar-tab { + border-right: 1px solid var(--theia-tab-border); +} + +#theia-main-content-panel .p-TabBar .p-TabBar-tab:hover.theia-mod-active { + background: var(--theia-tab-hoverBackground) !important; + box-shadow: var(--theia-tab-hoverBorder) 0 -1px inset !important; +} + +#theia-main-content-panel .p-TabBar .p-TabBar-tab:hover:not(.theia-mod-active) { + background: var(--theia-tab-unfocusedHoverBackground) !important; + box-shadow: var(--theia-tab-unfocusedHoverBorder) 0 -1px inset !important; +} + +/* active tab in an active group */ +body.theia-editor-highlightModifiedTabs +#theia-main-content-panel .p-TabBar .p-TabBar-tab.p-mod-current.theia-mod-active.theia-mod-dirty { + border-top: 1px solid var(--theia-tab-activeModifiedBorder); +} + +#theia-main-content-panel .p-TabBar .p-TabBar-tab.p-mod-current.theia-mod-active { + background: var(--theia-tab-activeBackground); + color: var(--theia-tab-activeForeground); + border-top: 1px solid var(--theia-tab-activeBorderTop); + border-bottom: 1px solid var(--theia-tab-activeBorder); +} + +/* inactive tab in an active group */ +body.theia-editor-highlightModifiedTabs +#theia-main-content-panel .p-TabBar .p-TabBar-tab:not(.p-mod-current).theia-mod-active.theia-mod-dirty { + border-top: 1px solid var(--theia-tab-inactiveModifiedBorder); +} + +#theia-main-content-panel .p-TabBar .p-TabBar-tab:not(.p-mod-current).theia-mod-active { + background: var(--theia-tab-inactiveBackground); + color: var(--theia-tab-inactiveForeground); +} + +/* active tab in an unfocused group */ +body.theia-editor-highlightModifiedTabs +#theia-main-content-panel .p-TabBar .p-TabBar-tab.p-mod-current:not(.theia-mod-active).theia-mod-dirty { + border-top: 1px solid var(--theia-tab-unfocusedActiveModifiedBorder); +} + +#theia-main-content-panel .p-TabBar .p-TabBar-tab.p-mod-current:not(.theia-mod-active) { + background: var(--theia-tab-unfocusedActiveBackground); + color: var(--theia-tab-unfocusedActiveForeground); + border-top: 1px solid var(--theia-tab-unfocusedActiveBorderTop); + border-bottom: 1px solid var(--theia-tab-unfocusedActiveBorder); +} + +/* inactive tab in an unfocused group */ +body.theia-editor-highlightModifiedTabs +#theia-main-content-panel .p-TabBar .p-TabBar-tab:not(.p-mod-current):not(.theia-mod-active).theia-mod-dirty { + border-top: 1px solid var(--theia-tab-unfocusedInactiveModifiedBorder); +} + +#theia-main-content-panel .p-TabBar .p-TabBar-tab:not(.p-mod-current):not(.theia-mod-active) { + background: var(--theia-tab-inactiveBackground); + color: var(--theia-tab-inactiveForeground); +} + +.p-TabBar.theia-app-centers { + background: var(--theia-editorGroupHeader-tabsBackground); +} + +.p-TabBar.theia-app-centers::after { + content: ''; + position: absolute; + bottom: 0; + left: 0; + pointer-events: none; + background-color: var(--theia-editorGroupHeader-tabsBorder); + width: 100%; + height: 1px; } .p-TabBar.theia-app-centers .p-TabBar-tabIcon, diff --git a/packages/monaco/src/browser/monaco-color-registry.ts b/packages/monaco/src/browser/monaco-color-registry.ts index 96b5a179217a8..3231854de51ef 100644 --- a/packages/monaco/src/browser/monaco-color-registry.ts +++ b/packages/monaco/src/browser/monaco-color-registry.ts @@ -47,11 +47,13 @@ export class MonacoColorRegistry extends ColorRegistry { return Disposable.create(() => this.monacoColorRegistry.deregisterColor(identifier)); } - protected toColor(value: Color | undefined): string | monaco.color.Color | undefined { + protected toColor(value: Color | undefined): monaco.color.ColorValue | undefined { if (!value || typeof value === 'string') { return value; } - if ('r' in value) { + if ('v' in value) { + return monaco.color.transparent(value.v, value.f); + } else if ('r' in value) { const { r, g, b, a } = value; return new monaco.color.Color(new monaco.color.RGBA(r, g, b, a)); } else { diff --git a/packages/monaco/src/typings/monaco/index.d.ts b/packages/monaco/src/typings/monaco/index.d.ts index e0a14e20d5900..06440b5b8e649 100644 --- a/packages/monaco/src/typings/monaco/index.d.ts +++ b/packages/monaco/src/typings/monaco/index.d.ts @@ -552,10 +552,12 @@ declare module monaco.color { export interface ColorContribution { readonly id: string; } + export type ColorFunction = () => string | Color; + export type ColorValue = string | Color | ColorFunction; export interface ColorDefaults { - light?: string | Color; - dark?: string | Color; - hc?: string | Color; + light?: ColorValue; + dark?: ColorValue; + hc?: ColorValue; } export interface IColorRegistry { getColors(): ColorContribution[]; @@ -563,6 +565,7 @@ declare module monaco.color { deregisterColor(id: string): void; } export function getColorRegistry(): IColorRegistry; + export function transparent(colorValue: ColorValue, factor: number): ColorFunction; } declare module monaco.referenceSearch { From c6d6c0d9b490ab5fa6a17066ea3523f50bd805a7 Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Wed, 11 Dec 2019 11:07:55 +0000 Subject: [PATCH 16/65] apply minimap vscode colors Signed-off-by: Anton Kosyakov --- .../browser/decorations/editor-decoration.ts | 18 ++++- .../browser/dirty-diff/dirty-diff-module.ts | 2 - .../browser/style/dirty-diff-decorator.css | 52 -------------- packages/git/src/browser/style/dirty-diff.css | 38 ---------- .../dirty-diff/dirty-diff-decorator.ts | 30 ++++++-- packages/scm/src/browser/scm-contribution.ts | 71 ++++++++++++++++++- .../scm/src/browser/scm-frontend-module.ts | 6 +- .../browser/style/dirty-diff-decorator.css | 2 +- packages/scm/src/browser/style/dirty-diff.css | 36 ++++++---- 9 files changed, 139 insertions(+), 116 deletions(-) delete mode 100644 packages/git/src/browser/style/dirty-diff-decorator.css delete mode 100644 packages/git/src/browser/style/dirty-diff.css diff --git a/packages/editor/src/browser/decorations/editor-decoration.ts b/packages/editor/src/browser/decorations/editor-decoration.ts index fb29be22d3cd0..701495be2b51c 100644 --- a/packages/editor/src/browser/decorations/editor-decoration.ts +++ b/packages/editor/src/browser/decorations/editor-decoration.ts @@ -77,14 +77,30 @@ export interface EditorDecorationOptions { * render this decoration in the overview ruler. */ overviewRuler?: DecorationOverviewRulerOptions; + /** + * If set, render this decoration in the minimap. + */ + minimap?: DecorationMinimapOptions; } -export interface DecorationOverviewRulerOptions { +export interface DecorationOptions { /** * color of the decoration in the overview ruler. * use `rgba` values to play well with other decorations. */ color: string; +} + +export enum MinimapPosition { + Inline = 1, + Gutter = 2 +} + +export interface DecorationMinimapOptions extends DecorationOptions { + position?: MinimapPosition; +} + +export interface DecorationOverviewRulerOptions extends DecorationOptions { /** * position in the overview ruler. */ diff --git a/packages/git/src/browser/dirty-diff/dirty-diff-module.ts b/packages/git/src/browser/dirty-diff/dirty-diff-module.ts index 75b5765800544..1a4ed606c4e6c 100644 --- a/packages/git/src/browser/dirty-diff/dirty-diff-module.ts +++ b/packages/git/src/browser/dirty-diff/dirty-diff-module.ts @@ -19,8 +19,6 @@ import { FrontendApplicationContribution } from '@theia/core/lib/browser'; import { DirtyDiffContribution } from './dirty-diff-contribution'; import { DirtyDiffManager } from './dirty-diff-manager'; -import '../../../src/browser/style/dirty-diff.css'; - export function bindDirtyDiff(bind: interfaces.Bind): void { bind(DirtyDiffManager).toSelf().inSingletonScope(); bind(DirtyDiffContribution).toSelf().inSingletonScope(); diff --git a/packages/git/src/browser/style/dirty-diff-decorator.css b/packages/git/src/browser/style/dirty-diff-decorator.css deleted file mode 100644 index 520eb9894c607..0000000000000 --- a/packages/git/src/browser/style/dirty-diff-decorator.css +++ /dev/null @@ -1,52 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -.dirty-diff-glyph { - margin-left: 5px; - cursor: pointer; -} - -.dirty-diff-removed-line:after { - content: ''; - position: absolute; - bottom: -4px; - box-sizing: border-box; - width: 4px; - height: 0; - z-index: 9; - border-top: 4px solid transparent; - border-bottom: 4px solid transparent; - transition: border-top-width 80ms linear, border-bottom-width 80ms linear, bottom 80ms linear; -} - -.dirty-diff-glyph:before { - position: absolute; - content: ''; - height: 100%; - width: 0; - left: -2px; - transition: width 80ms linear, left 80ms linear; -} - -.dirty-diff-removed-line:before { - margin-left: 3px; - height: 0; - bottom: 0; - transition: height 80ms linear; -} - -.margin-view-overlays > div:hover > .dirty-diff-glyph:before { - position: absolute; - content: ''; - height: 100%; - width: 9px; - left: -6px; -} - -.margin-view-overlays > div:hover > .dirty-diff-removed-line:after { - bottom: 0; - border-top-width: 0; - border-bottom-width: 0; -} \ No newline at end of file diff --git a/packages/git/src/browser/style/dirty-diff.css b/packages/git/src/browser/style/dirty-diff.css deleted file mode 100644 index 6acd1022be73c..0000000000000 --- a/packages/git/src/browser/style/dirty-diff.css +++ /dev/null @@ -1,38 +0,0 @@ -/******************************************************************************** - * Copyright (C) 2018 TypeFox 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 'dirty-diff-decorator.css'; - -.dirty-diff-added-line { - border-left: 3px solid var(--theia-added-color0); -} -.dirty-diff-added-line:before { - background: var(--theia-added-color0); -} - -.dirty-diff-removed-line:after { - border-left: 4px solid var(--theia-removed-color0); -} -.dirty-diff-removed-line:before { - background: var(--theia-removed-color0); -} - -.dirty-diff-modified-line { - border-left: 3px solid var(--theia-modified-color0); -} -.dirty-diff-modified-line:before { - background: var(--theia-modified-color0); -} diff --git a/packages/scm/src/browser/dirty-diff/dirty-diff-decorator.ts b/packages/scm/src/browser/dirty-diff/dirty-diff-decorator.ts index 12ed9c39f1f08..617fd5fd03c79 100644 --- a/packages/scm/src/browser/dirty-diff/dirty-diff-decorator.ts +++ b/packages/scm/src/browser/dirty-diff/dirty-diff-decorator.ts @@ -22,7 +22,8 @@ import { EditorDecorationOptions, OverviewRulerLane, EditorDecorator, - TextEditor + TextEditor, + MinimapPosition } from '@theia/editor/lib/browser'; import { DirtyDiff, LineRange } from './diff-computer'; @@ -35,25 +36,40 @@ export enum DirtyDiffDecorationType { const AddedLineDecoration = { linesDecorationsClassName: 'dirty-diff-glyph dirty-diff-added-line', overviewRuler: { - color: 'rgba(0, 255, 0, 0.8)', + color: 'editorOverviewRuler.addedForeground', position: OverviewRulerLane.Left, - } + }, + minimap: { + color: 'minimapGutter.addedBackground', + position: MinimapPosition.Gutter + }, + isWholeLine: true }; const RemovedLineDecoration = { linesDecorationsClassName: 'dirty-diff-glyph dirty-diff-removed-line', overviewRuler: { - color: 'rgba(230, 0, 0, 0.8)', + color: 'editorOverviewRuler.deletedForeground', position: OverviewRulerLane.Left, - } + }, + minimap: { + color: 'minimapGutter.deletedBackground', + position: MinimapPosition.Gutter + }, + isWholeLine: false }; const ModifiedLineDecoration = { linesDecorationsClassName: 'dirty-diff-glyph dirty-diff-modified-line', overviewRuler: { - color: 'rgba(0, 100, 150, 0.8)', + color: 'editorOverviewRuler.modifiedForeground', position: OverviewRulerLane.Left, - } + }, + minimap: { + color: 'minimapGutter.modifiedBackground', + position: MinimapPosition.Gutter + }, + isWholeLine: true }; export interface DirtyDiffUpdate extends DirtyDiff { diff --git a/packages/scm/src/browser/scm-contribution.ts b/packages/scm/src/browser/scm-contribution.ts index afee96b6b60fd..e715aa973cecb 100644 --- a/packages/scm/src/browser/scm-contribution.ts +++ b/packages/scm/src/browser/scm-contribution.ts @@ -31,6 +31,8 @@ import { ScmWidget } from '../browser/scm-widget'; import URI from '@theia/core/lib/common/uri'; import { ScmQuickOpenService } from './scm-quick-open-service'; import { ScmRepository } from './scm-repository'; +import { ColorContribution } from '@theia/core/lib/browser/color-application-contribution'; +import { ColorRegistry, Color } from '@theia/core/lib/browser/color-registry'; export const SCM_WIDGET_FACTORY_ID = ScmWidget.ID; export const SCM_VIEW_CONTAINER_ID = 'scm-view-container'; @@ -52,7 +54,7 @@ export namespace SCM_COMMANDS { } @injectable() -export class ScmContribution extends AbstractViewContribution implements FrontendApplicationContribution { +export class ScmContribution extends AbstractViewContribution implements FrontendApplicationContribution, ColorContribution { @inject(StatusBar) protected readonly statusBar: StatusBar; @inject(ScmService) protected readonly scmService: ScmService; @@ -180,4 +182,71 @@ export class ScmContribution extends AbstractViewContribution impleme this.statusBarDisposable.push(Disposable.create(() => this.statusBar.removeElement(id))); } + /** + * It should be aligned with https://github.com/microsoft/vscode/blob/0dfa355b3ad185a6289ba28a99c141ab9e72d2be/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts#L808 + */ + registerColors(colors: ColorRegistry): void { + const overviewRulerDefault = Color.rgba(0, 122, 204, 0.6); + colors.register( + { + id: 'editorGutter.modifiedBackground', defaults: { + dark: Color.rgba(12, 125, 157), + light: Color.rgba(102, 175, 224), + hc: Color.rgba(0, 155, 249) + }, description: 'Editor gutter background color for lines that are modified.' + }, + { + id: 'editorGutter.addedBackground', defaults: { + dark: Color.rgba(88, 124, 12), + light: Color.rgba(129, 184, 139), + hc: Color.rgba(51, 171, 78) + }, description: 'Editor gutter background color for lines that are added.' + }, + { + id: 'editorGutter.deletedBackground', defaults: { + dark: Color.rgba(148, 21, 27), + light: Color.rgba(202, 75, 81), + hc: Color.rgba(252, 93, 109) + }, description: 'Editor gutter background color for lines that are deleted.' + }, + { + id: 'minimapGutter.modifiedBackground', defaults: { + dark: Color.rgba(12, 125, 157), + light: Color.rgba(102, 175, 224), + hc: Color.rgba(0, 155, 249) + }, description: 'Minimap gutter background color for lines that are modified.' + }, + { + id: 'minimapGutter.addedBackground', + defaults: { + dark: Color.rgba(88, 124, 12), + light: Color.rgba(129, 184, 139), + hc: Color.rgba(51, 171, 78) + }, description: 'Minimap gutter background color for lines that are added.' + }, + { + id: 'minimapGutter.deletedBackground', defaults: { + dark: Color.rgba(148, 21, 27), + light: Color.rgba(202, 75, 81), + hc: Color.rgba(252, 93, 109) + }, description: 'Minimap gutter background color for lines that are deleted.' + }, + { + id: 'editorOverviewRuler.modifiedForeground', defaults: { + dark: overviewRulerDefault, light: overviewRulerDefault, hc: overviewRulerDefault + }, description: 'Overview ruler marker color for modified content.' + }, + { + id: 'editorOverviewRuler.addedForeground', defaults: { + dark: overviewRulerDefault, light: overviewRulerDefault, hc: overviewRulerDefault + }, description: 'Overview ruler marker color for added content.' + }, + { + id: 'editorOverviewRuler.deletedForeground', defaults: { + dark: overviewRulerDefault, light: overviewRulerDefault, hc: overviewRulerDefault + }, description: 'Overview ruler marker color for deleted content.' + } + ); + } + } diff --git a/packages/scm/src/browser/scm-frontend-module.ts b/packages/scm/src/browser/scm-frontend-module.ts index d81c645961edc..a2187f09b4347 100644 --- a/packages/scm/src/browser/scm-frontend-module.ts +++ b/packages/scm/src/browser/scm-frontend-module.ts @@ -14,6 +14,8 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ +import '../../src/browser/style/index.css'; + import { ContainerModule } from 'inversify'; import { bindViewContribution, FrontendApplicationContribution, @@ -22,9 +24,7 @@ import { } from '@theia/core/lib/browser'; import { ScmService } from './scm-service'; import { SCM_WIDGET_FACTORY_ID, ScmContribution, SCM_VIEW_CONTAINER_ID, SCM_VIEW_CONTAINER_TITLE_OPTIONS } from './scm-contribution'; - import { ScmWidget } from './scm-widget'; -import '../../src/browser/style/index.css'; import { ScmQuickOpenService } from './scm-quick-open-service'; import { bindDirtyDiff } from './dirty-diff/dirty-diff-module'; import { NavigatorTreeDecorator } from '@theia/navigator/lib/browser'; @@ -33,6 +33,7 @@ import { ScmDecorationsService } from './decorations/scm-decorations-service'; import { ScmAvatarService } from './scm-avatar-service'; import { ScmContextKeyService } from './scm-context-key-service'; import { ScmLayoutVersion3Migration } from './scm-layout-migrations'; +import { ColorContribution } from '@theia/core/lib/browser/color-application-contribution'; export default new ContainerModule(bind => { bind(ScmContextKeyService).toSelf().inSingletonScope(); @@ -64,6 +65,7 @@ export default new ContainerModule(bind => { bind(ScmQuickOpenService).toSelf().inSingletonScope(); bindViewContribution(bind, ScmContribution); bind(FrontendApplicationContribution).toService(ScmContribution); + bind(ColorContribution).toService(ScmContribution); bind(NavigatorTreeDecorator).to(ScmNavigatorDecorator).inSingletonScope(); bind(ScmDecorationsService).toSelf().inSingletonScope(); diff --git a/packages/scm/src/browser/style/dirty-diff-decorator.css b/packages/scm/src/browser/style/dirty-diff-decorator.css index 520eb9894c607..1b630c3ba07ac 100644 --- a/packages/scm/src/browser/style/dirty-diff-decorator.css +++ b/packages/scm/src/browser/style/dirty-diff-decorator.css @@ -49,4 +49,4 @@ bottom: 0; border-top-width: 0; border-bottom-width: 0; -} \ No newline at end of file +} diff --git a/packages/scm/src/browser/style/dirty-diff.css b/packages/scm/src/browser/style/dirty-diff.css index 6acd1022be73c..1f27f060dcaba 100644 --- a/packages/scm/src/browser/style/dirty-diff.css +++ b/packages/scm/src/browser/style/dirty-diff.css @@ -16,23 +16,35 @@ @import 'dirty-diff-decorator.css'; -.dirty-diff-added-line { - border-left: 3px solid var(--theia-added-color0); +.monaco-editor .dirty-diff-added-line { + border-left: 3px solid var(--theia-editorGutter-addedBackground); + transition: opacity 0.5s; } -.dirty-diff-added-line:before { - background: var(--theia-added-color0); +.monaco-editor .dirty-diff-added-line:before { + background: var(--theia-editorGutter-addedBackground); +} +.monaco-editor .margin:hover .dirty-diff-added-line { + opacity: 1; } -.dirty-diff-removed-line:after { - border-left: 4px solid var(--theia-removed-color0); +.monaco-editor .dirty-diff-removed-line:after { + border-left: 4px solid var(--theia-editorGutter-deletedBackground); + transition: opacity 0.5s; +} +.monaco-editor .dirty-diff-removed-line:before { + background: var(--theia-editorGutter-deletedBackground); } -.dirty-diff-removed-line:before { - background: var(--theia-removed-color0); +.monaco-editor .margin:hover .dirty-diff-removed-line { + opacity: 1; } -.dirty-diff-modified-line { - border-left: 3px solid var(--theia-modified-color0); +.monaco-editor .dirty-diff-modified-line { + border-left: 3px solid var(--theia-editorGutter-modifiedBackground); + transition: opacity 0.5s; +} +.monaco-editor .dirty-diff-modified-line:before { + background: var(--theia-editorGutter-modifiedBackground); } -.dirty-diff-modified-line:before { - background: var(--theia-modified-color0); +.monaco-editor .margin:hover .dirty-diff-modified-line { + opacity: 1; } From 5bdc34ef32946259d55086549bdbc55a9235304f Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Wed, 11 Dec 2019 11:48:42 +0000 Subject: [PATCH 17/65] apply merge conflicts vscode colors Signed-off-by: Anton Kosyakov --- .../src/browser/merge-conflicts-decorations.ts | 6 +++--- packages/merge-conflicts/src/browser/style/index.css | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/merge-conflicts/src/browser/merge-conflicts-decorations.ts b/packages/merge-conflicts/src/browser/merge-conflicts-decorations.ts index 429c9ca15cfeb..804b8b84e1d5a 100644 --- a/packages/merge-conflicts/src/browser/merge-conflicts-decorations.ts +++ b/packages/merge-conflicts/src/browser/merge-conflicts-decorations.ts @@ -59,7 +59,7 @@ export namespace MergeConflictsDecorations { className: 'merge-conflict-current-content', overviewRuler: { position: OverviewRulerLane.Full, - color: 'rgba(0, 255, 0, 0.3)', + color: 'editorOverviewRuler.currentContentForeground', } }, BaseMarker: { @@ -71,7 +71,7 @@ export namespace MergeConflictsDecorations { className: 'merge-conflict-base-content', overviewRuler: { position: OverviewRulerLane.Full, - color: 'rgba(125, 125, 125, 0.3)', + color: 'editorOverviewRuler.commonContentForeground', } }, IncomingMarker: { @@ -83,7 +83,7 @@ export namespace MergeConflictsDecorations { className: 'merge-conflict-incoming-content', overviewRuler: { position: OverviewRulerLane.Full, - color: 'rgba(0, 0, 255, 0.3)', + color: 'editorOverviewRuler.incomingContentForeground', } }, }; diff --git a/packages/merge-conflicts/src/browser/style/index.css b/packages/merge-conflicts/src/browser/style/index.css index 02853197efdbe..48d97a3cfce7a 100644 --- a/packages/merge-conflicts/src/browser/style/index.css +++ b/packages/merge-conflicts/src/browser/style/index.css @@ -15,25 +15,25 @@ ********************************************************************************/ .merge-conflict-current-marker { - background-color: rgba(0, 255, 0, 0.1); + background-color: var(--theia-merge-currentHeaderBackground); } .merge-conflict-current-content { - background-color: rgba(0, 255, 0, 0.3); + background-color: var(--theia-merge-currentContentBackground); } .merge-conflict-base-marker { - background-color: rgba(125, 125, 125, 0.1); + background-color: var(--theia-merge-commonHeaderBackground); } .merge-conflict-base-content { - background-color: rgba(125, 125, 125, 0.3); + background-color: var(--theia-merge-commonContentBackground); } .merge-conflict-incoming-marker { - background-color: rgba(0, 0, 255, 0.1); + background-color: var(--theia-merge-incomingHeaderBackground); } .merge-conflict-incoming-content { - background-color: rgba(0, 0, 255, 0.3); + background-color: var(--theia-merge-incomingContentBackground); } From 1acc15c1f3746ca1468c0f58e193b3576d79c9fe Mon Sep 17 00:00:00 2001 From: Jan Bicker Date: Wed, 11 Dec 2019 12:44:54 +0000 Subject: [PATCH 18/65] Aplied color for statusbar, adapted colors of searchbox in trees Signed-off-by: Jan Bicker --- .../browser/common-frontend-contribution.ts | 62 ++++++++++++++++++- .../core/src/browser/style/search-box.css | 4 +- .../core/src/browser/style/status-bar.css | 17 ++++- .../workspace-frontend-contribution.ts | 12 +++- 4 files changed, 87 insertions(+), 8 deletions(-) diff --git a/packages/core/src/browser/common-frontend-contribution.ts b/packages/core/src/browser/common-frontend-contribution.ts index eb0d52cbfeb40..0c0f014aad5d3 100644 --- a/packages/core/src/browser/common-frontend-contribution.ts +++ b/packages/core/src/browser/common-frontend-contribution.ts @@ -772,10 +772,12 @@ export class CommonFrontendContribution implements FrontendApplicationContributi { id: 'sideBarSectionHeader.border', defaults: { hc: '#6FC3DF' }, description: 'Side bar section header border color. The side bar is the container for views like explorer and search.' }, // Lists and Trees colors should be aligned with https://code.visualstudio.com/api/references/theme-color#lists-and-trees - // if not yet contributed by Monaco, check runtime css variables to learn - // not yet supported/no respective elements in theia + // if not yet contributed by Monaco, check runtime css variables to learn. + // TODO: Following are not yet supported/no respective elements in theia: // list.focusBackground, list.focusForeground, list.inactiveFocusBackground, list.filterMatchBorder, // list.dropBackground, listFilterWidget.outline, listFilterWidget.noMatchesOutline, tree.indentGuidesStroke + // list.invalidItemForeground, + // list.warningForeground, list.errorForeground => tree node needs an respective class { id: 'list.activeSelectionBackground', defaults: { dark: '#094771', light: '#0074E8' }, description: 'List/Tree background color for the selected item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.' }, { id: 'list.activeSelectionForeground', defaults: { dark: '#FFF', light: '#FFF' }, description: 'List/Tree foreground color for the selected item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.' }, { id: 'list.inactiveSelectionBackground', defaults: { dark: '#37373D', light: '#E4E6F1' }, description: 'List/Tree background color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.' }, @@ -951,6 +953,62 @@ export class CommonFrontendContribution implements FrontendApplicationContributi }, description: 'Border on the top of modified (dirty) inactive tabs in an unfocused group. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' }, + // Status bar colors should be aligned with https://code.visualstudio.com/api/references/theme-color#status-bar-colors + // Not yet supported: + // statusBarItem.prominentForeground, statusBarItem.prominentBackground, statusBarItem.prominentHoverBackground + { + id: 'statusBar.foreground', defaults: { + dark: '#FFFFFF', + light: '#FFFFFF', + hc: '#FFFFFF' + }, description: 'Status bar foreground color when a workspace is opened. The status bar is shown in the bottom of the window.' + }, + { + id: 'statusBar.background', defaults: { + dark: '#007ACC', + light: '#007ACC' + }, description: 'Status bar background color when a workspace is opened. The status bar is shown in the bottom of the window.' + }, + { + id: 'statusBar.noFolderForeground', defaults: { + dark: 'statusBar.foreground', + light: 'statusBar.foreground', + hc: 'statusBar.foreground' + }, description: 'Status bar foreground color when no folder is opened. The status bar is shown in the bottom of the window.' + }, + { + id: 'statusBar.noFolderBackground', defaults: { + dark: '#68217A', + light: '#68217A' + }, description: 'Status bar background color when no folder is opened. The status bar is shown in the bottom of the window.' + }, + { + id: 'statusBar.border', defaults: { + hc: 'contrastBorder' + }, description: 'Status bar border color separating to the sidebar and editor. The status bar is shown in the bottom of the window.' + }, + { + id: 'statusBar.noFolderBorder', defaults: { + dark: 'statusBar.border', + light: 'statusBar.border', + hc: 'statusBar.border' + }, description: 'Status bar border color separating to the sidebar and editor when no folder is opened. The status bar is shown in the bottom of the window.' + }, + { + id: 'statusBarItem.activeBackground', defaults: { + dark: Color.rgba(255, 255, 255, 0.18), + light: Color.rgba(255, 255, 255, 0.18), + hc: Color.rgba(255, 255, 255, 0.18) + }, description: 'Status bar item background color when clicking. The status bar is shown in the bottom of the window.' + }, + { + id: 'statusBarItem.hoverBackground', defaults: { + dark: Color.rgba(255, 255, 255, 0.12), + light: Color.rgba(255, 255, 255, 0.12), + hc: Color.rgba(255, 255, 255, 0.12) + }, description: 'Status bar item background color when hovering. The status bar is shown in the bottom of the window.' + }, + // Panel colors should be aligned with https://code.visualstudio.com/api/references/theme-color#panel-colors { id: 'panel.background', defaults: { diff --git a/packages/core/src/browser/style/search-box.css b/packages/core/src/browser/style/search-box.css index f99545fbf70d5..dae7ef0c223cc 100644 --- a/packages/core/src/browser/style/search-box.css +++ b/packages/core/src/browser/style/search-box.css @@ -23,7 +23,7 @@ align-items: baseline; box-shadow: var(--theia-border-width) var(--theia-border-width) var(--theia-border-color0); line-height: var(--theia-private-horizontal-tab-height); - background-color: var(--theia-listFilterWidget-background); + background-color: var(--theia-editorWidget-background); z-index: 1; } @@ -31,7 +31,7 @@ flex-grow: 1; line-height: calc(var(--theia-private-horizontal-tab-height) * 0.8); max-width: 6rem; - background-color: var(--theia-listFilterWidget-background); + background-color: var(--theia-input-background); } .theia-search-button { diff --git a/packages/core/src/browser/style/status-bar.css b/packages/core/src/browser/style/status-bar.css index 33f798cc75391..579f7ff57af78 100644 --- a/packages/core/src/browser/style/status-bar.css +++ b/packages/core/src/browser/style/status-bar.css @@ -19,10 +19,17 @@ } #theia-statusBar { - background: var(--theia-statusbar-color); + background: var(--theia-statusBar-background); display: flex; min-height: var(--theia-statusBar-height); white-space: nowrap; + border-top: var(--theia-border-width) solid var(--theia-statusBar-border); +} + +body.theia-no-open-workspace #theia-statusBar{ + background: var(--theia-statusBar-noFolderBackground); + color: var(--theia-statusBar-noFolderForeground); + border-top: var(--theia-border-width) solid var(--theia-statusBar-noFolderBorder); } #theia-statusBar .area { @@ -42,7 +49,7 @@ } #theia-statusBar .area .element { - color: var(--theia-statusBar-font-color); + color: var(--theia-statusBar-foreground); display: flex; align-items: center; font-size: var(--theia-statusBar-font-size); @@ -57,10 +64,14 @@ } #theia-statusBar .area .element.hasCommand:hover { - background-color: rgba(255, 255, 255, 0.2); + background-color: var(--theia-statusBarItem-hoverBackground); cursor: pointer; } +#theia-statusBar .area .element.hasCommand:active { + background-color: var(--theia-statusBarItem-activeBackground); +} + #theia-statusBar .area.left .element { margin-right: var(--theia-ui-padding); } diff --git a/packages/workspace/src/browser/workspace-frontend-contribution.ts b/packages/workspace/src/browser/workspace-frontend-contribution.ts index 80b6bd29a755a..5ed50d2fb5ac5 100644 --- a/packages/workspace/src/browser/workspace-frontend-contribution.ts +++ b/packages/workspace/src/browser/workspace-frontend-contribution.ts @@ -58,7 +58,17 @@ export class WorkspaceFrontendContribution implements CommandContribution, Keybi const workspaceFolderCountKey = this.contextKeyService.createKey('workspaceFolderCount', 0); const updateWorkspaceFolderCountKey = () => workspaceFolderCountKey.set(this.workspaceService.tryGetRoots().length); updateWorkspaceFolderCountKey(); - this.workspaceService.onWorkspaceChanged(updateWorkspaceFolderCountKey); + this.workspaceService.onWorkspaceChanged(() => { + updateWorkspaceFolderCountKey(); + this.updateStyles(); + }); + } + + protected updateStyles(): void { + document.body.classList.remove('theia-no-open-workspace'); + if (!this.workspaceService.tryGetRoots().length) { + document.body.classList.add('theia-no-open-workspace'); + } } registerCommands(commands: CommandRegistry): void { From 5a017834117c21337d2243f67207635f33927609 Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Wed, 11 Dec 2019 13:45:18 +0000 Subject: [PATCH 19/65] apply diff editor vscode colors Signed-off-by: Anton Kosyakov --- .../src/browser/styles/index.css | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/search-in-workspace/src/browser/styles/index.css b/packages/search-in-workspace/src/browser/styles/index.css index dc8c9c34bff1b..5f3f71eebc44d 100644 --- a/packages/search-in-workspace/src/browser/styles/index.css +++ b/packages/search-in-workspace/src/browser/styles/index.css @@ -248,20 +248,28 @@ } .t-siw-search-container .resultLine .match { - background: var(--theia-word-highlight-match-color1); line-height: normal; white-space: pre; + background: var(--theia-editor-findMatchHighlightBackground); + border: 1px solid var(--theia-editor-findMatchHighlightBorder); +} +.theia-hc .t-siw-search-container .resultLine .match { + border-style: dashed; } .t-siw-search-container .resultLine .match.strike-through { text-decoration: line-through; + background: var(--theia-diffEditor-removedTextBackground); + border-color: var(--theia-diffEditor-removedTextBorder); } -.t-siw-search-container .resultLine.selected .match { - background: var(--theia-word-highlight-match-color1); +.t-siw-search-container .resultLine .replace-term { + background: var(--theia-diffEditor-insertedTextBackground); + border: 1p solid var(--theia-diffEditor-insertedTextBorder); } +.theia-hc .t-siw-search-container .resultLine .replace-term { - background: var(--theia-word-highlight-replace-color0); + border-style: dashed; } .t-siw-search-container .noWrapInfo { From 06153bd1bdb401bfd1c119daf8c95e1247f55d77 Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Wed, 11 Dec 2019 14:51:15 +0000 Subject: [PATCH 20/65] apply editor hover widget vscode colors Signed-off-by: Anton Kosyakov --- packages/debug/src/browser/style/index.css | 10 ++++++---- packages/terminal/src/browser/terminal-widget-impl.ts | 7 ++++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/debug/src/browser/style/index.css b/packages/debug/src/browser/style/index.css index 03df2a91b6596..c937da15de018 100644 --- a/packages/debug/src/browser/style/index.css +++ b/packages/debug/src/browser/style/index.css @@ -124,7 +124,7 @@ .theia-session-container > .debug-toolbar { padding-top: var(--theia-ui-padding); padding-bottom: var(--theia-ui-padding); - border-bottom: 1px solid var(--theia-layout-color0); + border-bottom: 1px solid var(--theia-sideBarSectionHeader-border); } .debug-toolbar .debug-configuration { @@ -316,8 +316,10 @@ min-height: 324px; width: 324px; height: 324px; - border: 1px solid var(--theia-layout-color4); - background: var(--theia-layout-color0); + border: 1px solid var(--theia-editorHoverWidget-border); + background: var(--theia-editorHoverWidget-background); + /* TODO color: var(--theia-editorHoverWidget-foreground); with a newer Monaco version */ + color: var(--theia-editorWidget-foreground); } .theia-debug-hover .theia-source-tree { @@ -331,7 +333,7 @@ text-overflow: ellipsis; padding: var(--theia-ui-padding); padding-left: calc(var(--theia-ui-padding)*2); - border-bottom: 1px solid var(--theia-layout-color4); + border-bottom: 1px solid var(--theia-editorHoverWidget-border); } .theia-debug-hover-content { diff --git a/packages/terminal/src/browser/terminal-widget-impl.ts b/packages/terminal/src/browser/terminal-widget-impl.ts index 0c8088e7890d8..b84c03a3f9801 100644 --- a/packages/terminal/src/browser/terminal-widget-impl.ts +++ b/packages/terminal/src/browser/terminal-widget-impl.ts @@ -104,9 +104,10 @@ export class TerminalWidgetImpl extends TerminalWidget implements StatefulWidget this.hoverMessage = document.createElement('div'); this.hoverMessage.textContent = 'Cmd + click to follow link'; this.hoverMessage.style.position = 'fixed'; - this.hoverMessage.style.color = 'var(--theia-ui-font-color1)'; - this.hoverMessage.style.backgroundColor = 'var(--theia-layout-color1)'; - this.hoverMessage.style.borderColor = 'var(--theia-layout-color3)'; + // TODO use `var(--theia-editorHoverWidget-foreground) with a newer Monaco version + this.hoverMessage.style.color = 'var(--theia-editorWidget-foreground)'; + this.hoverMessage.style.backgroundColor = 'var(--theia-editorHoverWidget-background)'; + this.hoverMessage.style.borderColor = 'var(--theia-editorHoverWidget-border)'; this.hoverMessage.style.borderWidth = '0.5px'; this.hoverMessage.style.borderStyle = 'solid'; this.hoverMessage.style.padding = '5px'; From 492f669d329fdcfe59754d2f280b230bccb43040 Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Wed, 11 Dec 2019 14:58:54 +0000 Subject: [PATCH 21/65] apply progress bar vscode colors Signed-off-by: Anton Kosyakov --- packages/core/src/browser/style/progress-bar.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/browser/style/progress-bar.css b/packages/core/src/browser/style/progress-bar.css index 700372da43351..03b9e9a942a66 100644 --- a/packages/core/src/browser/style/progress-bar.css +++ b/packages/core/src/browser/style/progress-bar.css @@ -20,7 +20,7 @@ } .theia-progress-bar { - background-color: var(--theia-brand-color0); + background-color: var(--theia-progressBar-background); height: 2px; width: 3%; animation: progress-animation 1.3s 0s infinite cubic-bezier(0.645, 0.045, 0.355, 1); From 48c12fc4a3b66fcdaca142f98ef5c955a416a678 Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Wed, 11 Dec 2019 16:06:06 +0000 Subject: [PATCH 22/65] apply badge vscode colors Signed-off-by: Anton Kosyakov --- .../callhierarchy/src/browser/style/index.css | 2 +- .../core/src/browser/style/notification.css | 4 +-- .../style/variables-bright.useable.css | 5 ++-- .../browser/style/variables-dark.useable.css | 5 ++-- .../src/browser/style/index.css | 6 ++--- .../git/src/browser/blame/blame-decorator.ts | 6 ++--- packages/git/src/browser/git-contribution.ts | 27 +++++++++++++++++++ .../outline-view/src/browser/styles/index.css | 2 +- 8 files changed, 43 insertions(+), 14 deletions(-) diff --git a/packages/callhierarchy/src/browser/style/index.css b/packages/callhierarchy/src/browser/style/index.css index c1076fd7b9fd5..1ba5de2c09ef5 100644 --- a/packages/callhierarchy/src/browser/style/index.css +++ b/packages/callhierarchy/src/browser/style/index.css @@ -45,7 +45,7 @@ } .theia-CallHierarchyTree .definitionNode .referenceCount { - color: var(--theia-ui-font-color3); + color: var(--theia-badge-background); } .theia-CallHierarchyTree .definitionNode .container { diff --git a/packages/core/src/browser/style/notification.css b/packages/core/src/browser/style/notification.css index 3c89a0f3aced4..b9a6f7011d0e9 100644 --- a/packages/core/src/browser/style/notification.css +++ b/packages/core/src/browser/style/notification.css @@ -20,9 +20,9 @@ .notification-count-container { align-self: center; - background-color: var(--theia-ui-font-color3); + background-color: var(--theia-badge-background); border-radius: 20px; - color: var(--theia-ui-font-color0); + color: var(--theia-badge-foreground); display: flex; font-size: calc(var(--theia-ui-font-size0) * 0.8); font-weight: 500; diff --git a/packages/core/src/browser/style/variables-bright.useable.css b/packages/core/src/browser/style/variables-bright.useable.css index ac55c26086389..5667e657181d8 100644 --- a/packages/core/src/browser/style/variables-bright.useable.css +++ b/packages/core/src/browser/style/variables-bright.useable.css @@ -43,10 +43,11 @@ is not optimized for dense, information rich UIs. --theia-ui-icon-font-size: 14px; /* Ensures px perfect FontAwesome icons */ --theia-ui-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - --theia-ui-font-color0: var(--md-grey-900); + /** deprecated ui font colors */ + --theia-ui-font-color0: var(--theia-foreground); --theia-ui-font-color1: var(--md-grey-700); --theia-ui-font-color2: var(--md-grey-500); - --theia-ui-font-color3: var(--md-grey-300); + --theia-ui-font-color3: var(--theia-badge-background); /* Special font colors */ diff --git a/packages/core/src/browser/style/variables-dark.useable.css b/packages/core/src/browser/style/variables-dark.useable.css index f952308ec67cb..262d575279f26 100644 --- a/packages/core/src/browser/style/variables-dark.useable.css +++ b/packages/core/src/browser/style/variables-dark.useable.css @@ -43,10 +43,11 @@ is not optimized for dense, information rich UIs. --theia-ui-icon-font-size: 14px; /* Ensures px perfect FontAwesome icons */ --theia-ui-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - --theia-ui-font-color0: var(--md-grey-100); + /* deprecated ui font colors */ + --theia-ui-font-color0: var(--theia-foreground); --theia-ui-font-color1: var(--md-grey-300); --theia-ui-font-color2: var(--md-grey-500); - --theia-ui-font-color3: var(--md-grey-700); + --theia-ui-font-color3: var(--theia-badge-background); /* Special font colors */ diff --git a/packages/getting-started/src/browser/style/index.css b/packages/getting-started/src/browser/style/index.css index b52f8a88f7b3b..53d4a493b42a3 100644 --- a/packages/getting-started/src/browser/style/index.css +++ b/packages/getting-started/src/browser/style/index.css @@ -30,7 +30,7 @@ html, body { .gs-action-container { line-height: 20px; - color: var(--theia-ui-font-color0); + color: var(--theia-foreground); } .gs-action-details { @@ -43,7 +43,7 @@ html, body { } .gs-header h1 { - color: var(--theia-ui-font-color0); + color: var(--theia-foreground); flex: 1; font-weight: 600; } @@ -71,7 +71,7 @@ html, body { } .gs-section-header { - color: var(--theia-ui-font-color0); + color: var(--theia-foreground); font-size: var(--theia-ui-font-size2); font-weight: 600; margin-bottom: 5px; diff --git a/packages/git/src/browser/blame/blame-decorator.ts b/packages/git/src/browser/blame/blame-decorator.ts index 4c9556b91755c..88475fe7f27ae 100644 --- a/packages/git/src/browser/blame/blame-decorator.ts +++ b/packages/git/src/browser/blame/blame-decorator.ts @@ -210,8 +210,8 @@ export namespace BlameDecorator { export const defaultGutterStyles = { width: `${maxWidth}ch`, - color: 'var(--theia-ui-font-color0)', - backgroundColor: 'var(--theia-layout-color1)', + color: 'var(--theia-gitlens-gutterForegroundColor)', + backgroundColor: 'var(--theia-gitlens-gutterBackgroundColor)', height: '100%', margin: '0 26px -1px 0', display: 'inline-block', @@ -223,7 +223,7 @@ export namespace BlameDecorator { }); export const highlightStyle = new EditorDecorationStyle('git-blame-highlight::before', style => { - style.backgroundColor = 'var(--theia-layout-color2)'; + style.backgroundColor = 'var(--theia-gitlens-lineHighlightBackgroundColor)'; }); } diff --git a/packages/git/src/browser/git-contribution.ts b/packages/git/src/browser/git-contribution.ts index 0f1c76a43099f..1fb292399b463 100644 --- a/packages/git/src/browser/git-contribution.ts +++ b/packages/git/src/browser/git-contribution.ts @@ -781,6 +781,33 @@ export class GitContribution implements CommandContribution, MenuContribution, T 'dark': '#6c6cc4', 'hc': '#6c6cc4' } + }, + { + 'id': 'gitlens.gutterBackgroundColor', + 'description': 'Specifies the background color of the gutter blame annotations', + 'defaults': { + 'dark': '#FFFFFF13', + 'light': '#0000000C', + 'hc': '#FFFFFF13' + } + }, + { + 'id': 'gitlens.gutterForegroundColor', + 'description': 'Specifies the foreground color of the gutter blame annotations', + 'defaults': { + 'dark': '#BEBEBE', + 'light': '#747474', + 'hc': '#BEBEBE' + } + }, + { + 'id': 'gitlens.lineHighlightBackgroundColor', + 'description': 'Specifies the background color of the associated line highlights in blame annotations', + 'defaults': { + 'dark': '#00BCF233', + 'light': '#00BCF233', + 'hc': '#00BCF233' + } } ); } diff --git a/packages/outline-view/src/browser/styles/index.css b/packages/outline-view/src/browser/styles/index.css index 70b3df708a1ad..7bcb61c88b8ca 100644 --- a/packages/outline-view/src/browser/styles/index.css +++ b/packages/outline-view/src/browser/styles/index.css @@ -19,7 +19,7 @@ } .no-outline { - color: var(--theia-ui-font-color0); + color: var(--theia-foreground); text-align: left; } From 04f1bd41204b3e710397d761d741793ccaa34525 Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Thu, 12 Dec 2019 09:07:54 +0000 Subject: [PATCH 23/65] [color] add more color functions Signed-off-by: Anton Kosyakov --- packages/core/src/browser/color-registry.ts | 15 +++++++++++---- .../monaco/src/browser/monaco-color-registry.ts | 4 ++-- packages/monaco/src/typings/monaco/index.d.ts | 2 ++ 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/packages/core/src/browser/color-registry.ts b/packages/core/src/browser/color-registry.ts index 8a852dd8973ba..27018a6e796aa 100644 --- a/packages/core/src/browser/color-registry.ts +++ b/packages/core/src/browser/color-registry.ts @@ -21,7 +21,7 @@ import { Emitter } from '../common/event'; /** * Either be a reference to an existing color or a color value as a hex string, rgba, or hsla. */ -export type Color = string | RGBA | HSLA | TransparentColor; +export type Color = string | RGBA | HSLA | ColorTransformation; export namespace Color { export function rgba(r: number, g: number, b: number, a: number = 1): Color { return { r, g, b, a }; @@ -31,11 +31,18 @@ export namespace Color { } export const white = rgba(255, 255, 255, 1); export const black = rgba(0, 0, 0, 1); - export function transparent(v: string, f: number): TransparentColor { - return { v, f }; + export function transparent(v: string, f: number): ColorTransformation { + return { v, f, kind: 'transparent' }; + } + export function lighten(v: string, f: number): ColorTransformation { + return { v, f, kind: 'lighten' }; + } + export function darken(v: string, f: number): ColorTransformation { + return { v, f, kind: 'darken' }; } } -export interface TransparentColor { +export interface ColorTransformation { + kind: 'transparent' | 'lighten' | 'darken' v: string f: number } diff --git a/packages/monaco/src/browser/monaco-color-registry.ts b/packages/monaco/src/browser/monaco-color-registry.ts index 3231854de51ef..3a3bac08a9ee5 100644 --- a/packages/monaco/src/browser/monaco-color-registry.ts +++ b/packages/monaco/src/browser/monaco-color-registry.ts @@ -51,8 +51,8 @@ export class MonacoColorRegistry extends ColorRegistry { if (!value || typeof value === 'string') { return value; } - if ('v' in value) { - return monaco.color.transparent(value.v, value.f); + if ('kind' in value) { + return monaco.color[value.kind](value.v, value.f); } else if ('r' in value) { const { r, g, b, a } = value; return new monaco.color.Color(new monaco.color.RGBA(r, g, b, a)); diff --git a/packages/monaco/src/typings/monaco/index.d.ts b/packages/monaco/src/typings/monaco/index.d.ts index 06440b5b8e649..39a847a28fad3 100644 --- a/packages/monaco/src/typings/monaco/index.d.ts +++ b/packages/monaco/src/typings/monaco/index.d.ts @@ -565,6 +565,8 @@ declare module monaco.color { deregisterColor(id: string): void; } export function getColorRegistry(): IColorRegistry; + export function darken(colorValue: ColorValue, factor: number): ColorFunction; + export function lighten(colorValue: ColorValue, factor: number): ColorFunction; export function transparent(colorValue: ColorValue, factor: number): ColorFunction; } From 77053a0aa0cebd689c05e6be397cdfed1e5ef312 Mon Sep 17 00:00:00 2001 From: Jan Bicker Date: Thu, 12 Dec 2019 09:30:47 +0000 Subject: [PATCH 24/65] Applied colors for buttons and quickInput Added foreground color body Signed-off-by: Jan Bicker --- .../browser/common-frontend-contribution.ts | 58 +++++++++++++------ packages/core/src/browser/style/index.css | 7 ++- packages/monaco/src/browser/style/index.css | 3 +- .../workspace-frontend-contribution.ts | 1 + 4 files changed, 47 insertions(+), 22 deletions(-) diff --git a/packages/core/src/browser/common-frontend-contribution.ts b/packages/core/src/browser/common-frontend-contribution.ts index 0c0f014aad5d3..2615dbabdca0e 100644 --- a/packages/core/src/browser/common-frontend-contribution.ts +++ b/packages/core/src/browser/common-frontend-contribution.ts @@ -739,15 +739,15 @@ export class CommonFrontendContribution implements FrontendApplicationContributi this.quickOpenService.open({ onType: (_, accept) => accept(items) }, { - placeholder: 'Select File Icon Theme', - fuzzyMatchLabel: true, - selectIndex: () => items.findIndex(item => item.id === this.iconThemes.current), - onClose: () => { - if (resetTo) { - this.iconThemes.current = resetTo; - } + placeholder: 'Select File Icon Theme', + fuzzyMatchLabel: true, + selectIndex: () => items.findIndex(item => item.id === this.iconThemes.current), + onClose: () => { + if (resetTo) { + this.iconThemes.current = resetTo; } - }); + } + }); } registerColors(colors: ColorRegistry): void { @@ -757,6 +757,11 @@ export class CommonFrontendContribution implements FrontendApplicationContributi { id: 'selection.background', defaults: { dark: '#217daf', light: '#c0dbf1' }, description: 'Overall border color for focused elements. This color is only used if not overridden by a component.' }, { id: 'icon.foreground', defaults: { dark: '#C5C5C5', light: '#424242', hc: '#FFFFFF' }, description: 'The default color for icons in the workbench.' }, + // Buttons should be aligned with https://code.visualstudio.com/api/references/theme-color#button-control + { id: 'button.foreground', defaults: { dark: Color.white, light: Color.white, hc: Color.white }, description: 'Button foreground color.' }, + { id: 'button.background', defaults: { dark: '#0E639C', light: '#007ACC' }, description: 'Button background color.' }, + { id: 'button.hoverBackground', defaults: { dark: Color.lighten('button.background', 0.2), light: Color.darken('button.background', 0.2) }, description: 'Button background color when hovering.' }, + // Activity Bar colors should be aligned with https://code.visualstudio.com/api/references/theme-color#activity-bar { id: 'activityBar.background', defaults: { dark: '#333333', light: '#2C2C2C', hc: '#000000' }, description: 'Activity bar background color. The activity bar is showing on the far left or right and allows to switch between views of the side bar.' }, { id: 'activityBar.border', defaults: { hc: '#6FC3DF' }, description: 'Activity bar border color separating to the side bar. The activity bar is showing on the far left or right and allows to switch between views of the side bar.' }, @@ -911,20 +916,20 @@ export class CommonFrontendContribution implements FrontendApplicationContributi id: 'tab.hoverBackground', description: 'Tab background color when hovering. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' }, { - id: 'tab.unfocusedHoverBackground', defaults: { - dark: Color.transparent('tab.hoverBackground', 0.5), - light: Color.transparent('tab.hoverBackground', 0.7) - }, description: 'Tab background color in an unfocused group when hovering. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' - }, + id: 'tab.unfocusedHoverBackground', defaults: { + dark: Color.transparent('tab.hoverBackground', 0.5), + light: Color.transparent('tab.hoverBackground', 0.7) + }, description: 'Tab background color in an unfocused group when hovering. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' + }, { id: 'tab.hoverBorder', description: 'Border to highlight tabs when hovering. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' }, { - id: 'tab.unfocusedHoverBorder', defaults: { - dark: Color.transparent('tab.hoverBorder', 0.5), - light: Color.transparent('tab.hoverBorder', 0.7) - }, description: 'Border to highlight tabs in an unfocused group when hovering. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' - }, + id: 'tab.unfocusedHoverBorder', defaults: { + dark: Color.transparent('tab.hoverBorder', 0.5), + light: Color.transparent('tab.hoverBorder', 0.7) + }, description: 'Border to highlight tabs in an unfocused group when hovering. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' + }, { id: 'tab.activeModifiedBorder', defaults: { dark: '#3399CC', @@ -1009,6 +1014,23 @@ export class CommonFrontendContribution implements FrontendApplicationContributi }, description: 'Status bar item background color when hovering. The status bar is shown in the bottom of the window.' }, + // Quickinput colors should be aligned with https://code.visualstudio.com/api/references/theme-color#quick-picker + // if not yet contributed by Monaco, check runtime css variables to learn. + { + id: 'quickInput.background', defaults: { + dark: 'sideBar.background', + light: 'sideBar.background', + hc: 'sideBar.background' + }, description: 'Quick Input background color. The Quick Input widget is the container for views like the color theme picker.' + }, + { + id: 'quickInput.foreground', defaults: { + dark: 'sideBar.foreground', + light: 'sideBar.foreground', + hc: 'sideBar.foreground' + }, description: 'Quick Input foreground color. The Quick Input widget is the container for views like the color theme picker.' + }, + // Panel colors should be aligned with https://code.visualstudio.com/api/references/theme-color#panel-colors { id: 'panel.background', defaults: { diff --git a/packages/core/src/browser/style/index.css b/packages/core/src/browser/style/index.css index 4ca509bec93f2..d34d3430a93f9 100644 --- a/packages/core/src/browser/style/index.css +++ b/packages/core/src/browser/style/index.css @@ -27,6 +27,7 @@ body { overflow: hidden; font-family: var(--theia-ui-font-family); background: var(--theia-layout-color0); + color: var(--theia-foreground); } .theia-maximized { @@ -125,8 +126,8 @@ body { button.theia-button, .theia-button { border: none; - color: var(--theia-ui-button-font-color); - background-color: var(--theia-ui-button-color); + color: var(--theia-button-foreground); + background-color: var(--theia-button-background); min-width: 65px; outline: none; cursor: pointer; @@ -138,7 +139,7 @@ button.theia-button, .theia-button { } button.theia-button:hover, .theia-button:hover, .theia-button:focus { - background-color: var(--theia-ui-button-color-hover); + background-color: var(--theia-button-hoverBackground); } button.secondary, .theia-button.secondary { diff --git a/packages/monaco/src/browser/style/index.css b/packages/monaco/src/browser/style/index.css index df1d1899e89e7..fa3af9b6bc4df 100644 --- a/packages/monaco/src/browser/style/index.css +++ b/packages/monaco/src/browser/style/index.css @@ -37,7 +37,8 @@ } .monaco-quick-open-widget { - background-color: var(--theia-layout-color1) !important; + background-color: var(--theia-quickInput-background) !important; + color: var(--theia-quickInput-foreground) !important; } .quick-open-entry .quick-open-row .monaco-icon-label .monaco-icon-label-description-container .monaco-highlighted-label .highlight { diff --git a/packages/workspace/src/browser/workspace-frontend-contribution.ts b/packages/workspace/src/browser/workspace-frontend-contribution.ts index 5ed50d2fb5ac5..34288185cd067 100644 --- a/packages/workspace/src/browser/workspace-frontend-contribution.ts +++ b/packages/workspace/src/browser/workspace-frontend-contribution.ts @@ -58,6 +58,7 @@ export class WorkspaceFrontendContribution implements CommandContribution, Keybi const workspaceFolderCountKey = this.contextKeyService.createKey('workspaceFolderCount', 0); const updateWorkspaceFolderCountKey = () => workspaceFolderCountKey.set(this.workspaceService.tryGetRoots().length); updateWorkspaceFolderCountKey(); + this.updateStyles(); this.workspaceService.onWorkspaceChanged(() => { updateWorkspaceFolderCountKey(); this.updateStyles(); From 042a780a53a02aaa0201a6f4a554d1db4c2a6459 Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Thu, 12 Dec 2019 09:39:29 +0000 Subject: [PATCH 25/65] apply notification vscode colors Signed-off-by: Anton Kosyakov --- .../src/browser/messages-frontend-module.ts | 2 + .../src/browser/notifications-contribution.ts | 80 ++++++++++++++++++- .../src/browser/style/notifications.css | 36 ++++----- 3 files changed, 99 insertions(+), 19 deletions(-) diff --git a/packages/messages/src/browser/messages-frontend-module.ts b/packages/messages/src/browser/messages-frontend-module.ts index 6b7e7e65a875a..aed1073a60a66 100644 --- a/packages/messages/src/browser/messages-frontend-module.ts +++ b/packages/messages/src/browser/messages-frontend-module.ts @@ -24,6 +24,7 @@ import { NotificationsRenderer } from './notifications-renderer'; import { NotificationsContribution, NotificationsKeybindingContext } from './notifications-contribution'; import { FrontendApplicationContribution, KeybindingContribution, KeybindingContext } from '@theia/core/lib/browser'; import { CommandContribution } from '@theia/core'; +import { ColorContribution } from '@theia/core/lib/browser/color-application-contribution'; export default new ContainerModule((bind, unbind, isBound, rebind) => { bind(NotificationsRenderer).toSelf().inSingletonScope(); @@ -31,6 +32,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { bind(FrontendApplicationContribution).toService(NotificationsContribution); bind(CommandContribution).toService(NotificationsContribution); bind(KeybindingContribution).toService(NotificationsContribution); + bind(ColorContribution).toService(NotificationsContribution); bind(NotificationsKeybindingContext).toSelf().inSingletonScope(); bind(KeybindingContext).toService(NotificationsKeybindingContext); bind(NotificationManager).toSelf().inSingletonScope(); diff --git a/packages/messages/src/browser/notifications-contribution.ts b/packages/messages/src/browser/notifications-contribution.ts index 4368d84502283..d11819f193c67 100644 --- a/packages/messages/src/browser/notifications-contribution.ts +++ b/packages/messages/src/browser/notifications-contribution.ts @@ -23,9 +23,11 @@ import { NotificationsCommands } from './notifications-commands'; import { CommandContribution, CommandRegistry } from '@theia/core'; import { NotificationManager } from './notifications-manager'; import { NotificationsRenderer } from './notifications-renderer'; +import { ColorContribution } from '@theia/core/lib/browser/color-application-contribution'; +import { ColorRegistry, Color } from '@theia/core/lib/browser/color-registry'; @injectable() -export class NotificationsContribution implements FrontendApplicationContribution, CommandContribution, KeybindingContribution { +export class NotificationsContribution implements FrontendApplicationContribution, CommandContribution, KeybindingContribution, ColorContribution { protected readonly id = 'theia-notification-center'; @@ -87,6 +89,82 @@ export class NotificationsContribution implements FrontendApplicationContributio keybinding: 'esc' }); } + + registerColors(colors: ColorRegistry): void { + colors.register( + { + id: 'notificationCenter.border', defaults: { + hc: 'contrastBorder' + }, description: 'Notifications center border color. Notifications slide in from the bottom right of the window.' + }, + { + id: 'notificationToast.border', defaults: { + hc: 'contrastBorder' + }, description: 'Notification toast border color. Notifications slide in from the bottom right of the window.' + }, + { + id: 'notifications.foreground', defaults: { + dark: 'editorWidget.foreground', + light: 'editorWidget.foreground', + hc: 'editorWidget.foreground' + }, description: 'Notifications foreground color. Notifications slide in from the bottom right of the window.' + }, + { + id: 'notifications.background', defaults: { + dark: 'editorWidget.background', + light: 'editorWidget.background', + hc: 'editorWidget.background' + }, description: 'Notifications background color. Notifications slide in from the bottom right of the window.' + }, + { + id: 'notificationLink.foreground', defaults: { + dark: 'textLink.foreground', + light: 'textLink.foreground', + hc: 'textLink.foreground' + }, description: 'Notification links foreground color. Notifications slide in from the bottom right of the window.' + }, + { + id: 'notificationCenterHeader.foreground', + description: 'Notifications center header foreground color. Notifications slide in from the bottom right of the window.' + }, + { + id: 'notificationCenterHeader.background', defaults: { + dark: Color.lighten('notifications.background', 0.3), + light: Color.darken('notifications.background', 0.05), + hc: 'notifications.background' + }, description: 'Notifications center header background color. Notifications slide in from the bottom right of the window.' + }, + { + id: 'notifications.border', defaults: { + dark: 'notificationCenterHeader.background', + light: 'notificationCenterHeader.background', + hc: 'notificationCenterHeader.background' + }, description: 'Notifications border color separating from other notifications in the notifications center. Notifications slide in from the bottom right of the window.' + }, + { + id: 'notificationsErrorIcon.foreground', defaults: { + dark: 'editorError.foreground', + light: 'editorError.foreground', + hc: 'editorError.foreground' + }, description: 'The color used for the icon of error notifications. Notifications slide in from the bottom right of the window.' + }, + { + id: 'notificationsWarningIcon.foreground', defaults: { + dark: 'editorWarning.foreground', + light: 'editorWarning.foreground', + hc: 'editorWarning.foreground' + }, description: 'The color used for the icon of warning notifications. Notifications slide in from the bottom right of the window.' + }, + { + id: 'notificationsInfoIcon.foreground', defaults: { + dark: 'editorInfo.foreground', + light: 'editorInfo.foreground', + hc: 'editorInfo.foreground' + }, description: 'The color used for the icon of info notifications. Notifications slide in from the bottom right of the window.' + } + ); + } + } @injectable() diff --git a/packages/messages/src/browser/style/notifications.css b/packages/messages/src/browser/style/notifications.css index 4a82a3a3a6e4f..ccf6696c4d68f 100644 --- a/packages/messages/src/browser/style/notifications.css +++ b/packages/messages/src/browser/style/notifications.css @@ -38,22 +38,25 @@ /* Toasts */ .theia-notifications-container.theia-notification-toasts .theia-notification-list-item { - background-color: var(--theia-layout-color1); - box-shadow: 0px 0px 4px 0px rgba(0, 0, 0, 0.5); + background-color: var(--theia-notifications-background); + box-shadow: 0px 0px 4px 0px var(--theia-widget-shadow); + border: 1px solid var(--theia-notificationToast-border); margin-top: 6px; } /* Center */ .theia-notifications-container.theia-notification-center { - background-color: var(--theia-layout-color1); - box-shadow: 0px 0px 6px 0px rgba(0, 0, 0, 0.5); + background-color: var(--theia-notifications-background); + border: 1px solid var(--theia-notificationCenter-border); + box-shadow: 0px 0px 6px 0px var(--theia-widget-shadow); } /* Center > Header */ .theia-notification-center-header { - background-color: var(--theia-layout-color2); + color: var(--theia-notificationCenterHeader-foreground); + background-color: var(--theia-notificationCenterHeader-background); display: flex; flex-direction: row; flex-wrap: nowrap; @@ -63,18 +66,14 @@ } .theia-notification-center-header-title { - color: var(--theia-ui-font-color0); font-size: calc(var(--theia-ui-font-size1) / 1.1); font-family: var(--theia-ui-font-family); margin: 8px; - /* padding: 4px; */ flex-grow: 2; } .theia-notification-center-header-actions { - color: white; margin: 8px; - /* padding: 4px; */ } /* List */ @@ -103,10 +102,10 @@ justify-content: space-between; } .theia-notification-list-item:hover { - background-color: var(--theia-layout-color2); + background-color: var(--theia-list-hoverBackground); } .theia-notification-list > .theia-notification-list-item:not(:last-child) { - border-top: 1px var(--theia-layout-color2) solid; + border-top: 1px var(--theia-notifications-border) solid; } .theia-notification-list-item-content { @@ -131,7 +130,6 @@ } .theia-notification-message { - color: var(--theia-ui-font-color0); font-size: var(--theia-ui-font-size1); font-family: var(--theia-ui-font-family); overflow-wrap: break-word; @@ -146,10 +144,13 @@ .theia-notification-message a { border: none; - color: var(--theia-accent-color1); + color: var(--theia-notificationLink-foreground); outline: 0; text-decoration: none; } +.theia-notification-message a:focus { + outline-color: var(--theia-focusBorder); +} .theia-notification-icon { font-family: FontAwesome; @@ -162,17 +163,17 @@ .theia-notification-icon-info:before { content: "\f05a"; - color: var(--theia-accent-color0); + color: var(--theia-notificationsInfoIcon-foreground); } .theia-notification-icon-warning:before { content: "\f071"; - color: darkorange; + color: var(--theia-notificationsWarningIcon-foreground); } .theia-notification-icon-error:before { content: "\f057"; - color: tomato; + color: var(--theia-notificationsErrorIcon-foreground); } .theia-notification-actions { @@ -230,7 +231,6 @@ } .theia-notification-source { - color: var(--theia-ui-font-color3); font-size: var(--theia-ui-font-size0); font-family: var(--theia-ui-font-family); overflow-wrap: break-word; @@ -263,7 +263,7 @@ .theia-notification-item-progressbar { height: 2px; - background-color: var(--theia-brand-color0); + background-color: var(--theia-progressBar-background); width: 66%; } From 93b2c276cfa0b0188d0ea2f5457301631be47f2f Mon Sep 17 00:00:00 2001 From: Jan Bicker Date: Thu, 12 Dec 2019 10:20:05 +0000 Subject: [PATCH 26/65] Fix for icon variables in debug view Themes were gotten by id, but must be get by type. Signed-off-by: Jan Bicker --- .../src/browser/debug-frontend-application-contribution.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/debug/src/browser/debug-frontend-application-contribution.ts b/packages/debug/src/browser/debug-frontend-application-contribution.ts index db410d2bad7da..c09a1bbaf5a7b 100644 --- a/packages/debug/src/browser/debug-frontend-application-contribution.ts +++ b/packages/debug/src/browser/debug-frontend-application-contribution.ts @@ -312,11 +312,11 @@ const darkCss = require('../../src/browser/style/debug-dark.useable.css'); const lightCss = require('../../src/browser/style/debug-bright.useable.css'); function updateTheme(): void { - const theme = ThemeService.get().getCurrentTheme().id; - if (theme === 'dark') { + const themeType = ThemeService.get().getCurrentTheme().type; + if (themeType === 'dark' || themeType === 'hc' ) { lightCss.unuse(); darkCss.use(); - } else if (theme === 'light') { + } else if (themeType === 'light') { darkCss.unuse(); lightCss.use(); } From 7b71aba15cf01cfb1c1d7307dc09cc3b38e3edf4 Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Thu, 12 Dec 2019 10:58:57 +0000 Subject: [PATCH 27/65] apply title bar and menu vscode colors Signed-off-by: Anton Kosyakov --- .../browser/common-frontend-contribution.ts | 118 +++++++++++++++--- packages/core/src/browser/style/menus.css | 53 ++++---- 2 files changed, 129 insertions(+), 42 deletions(-) diff --git a/packages/core/src/browser/common-frontend-contribution.ts b/packages/core/src/browser/common-frontend-contribution.ts index 2615dbabdca0e..caebafc1638f7 100644 --- a/packages/core/src/browser/common-frontend-contribution.ts +++ b/packages/core/src/browser/common-frontend-contribution.ts @@ -739,15 +739,15 @@ export class CommonFrontendContribution implements FrontendApplicationContributi this.quickOpenService.open({ onType: (_, accept) => accept(items) }, { - placeholder: 'Select File Icon Theme', - fuzzyMatchLabel: true, - selectIndex: () => items.findIndex(item => item.id === this.iconThemes.current), - onClose: () => { - if (resetTo) { - this.iconThemes.current = resetTo; + placeholder: 'Select File Icon Theme', + fuzzyMatchLabel: true, + selectIndex: () => items.findIndex(item => item.id === this.iconThemes.current), + onClose: () => { + if (resetTo) { + this.iconThemes.current = resetTo; + } } - } - }); + }); } registerColors(colors: ColorRegistry): void { @@ -916,20 +916,20 @@ export class CommonFrontendContribution implements FrontendApplicationContributi id: 'tab.hoverBackground', description: 'Tab background color when hovering. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' }, { - id: 'tab.unfocusedHoverBackground', defaults: { - dark: Color.transparent('tab.hoverBackground', 0.5), - light: Color.transparent('tab.hoverBackground', 0.7) - }, description: 'Tab background color in an unfocused group when hovering. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' - }, + id: 'tab.unfocusedHoverBackground', defaults: { + dark: Color.transparent('tab.hoverBackground', 0.5), + light: Color.transparent('tab.hoverBackground', 0.7) + }, description: 'Tab background color in an unfocused group when hovering. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' + }, { id: 'tab.hoverBorder', description: 'Border to highlight tabs when hovering. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' }, { - id: 'tab.unfocusedHoverBorder', defaults: { - dark: Color.transparent('tab.hoverBorder', 0.5), - light: Color.transparent('tab.hoverBorder', 0.7) - }, description: 'Border to highlight tabs in an unfocused group when hovering. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' - }, + id: 'tab.unfocusedHoverBorder', defaults: { + dark: Color.transparent('tab.hoverBorder', 0.5), + light: Color.transparent('tab.hoverBorder', 0.7) + }, description: 'Border to highlight tabs in an unfocused group when hovering. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' + }, { id: 'tab.activeModifiedBorder', defaults: { dark: '#3399CC', @@ -1072,6 +1072,88 @@ export class CommonFrontendContribution implements FrontendApplicationContributi }, description: 'Border color for image in image preview.' }, + // Title Bar colors should be aligned with https://code.visualstudio.com/api/references/theme-color#title-bar-colors + { + id: 'titleBar.activeForeground', defaults: { + dark: '#CCCCCC', + light: '#333333', + hc: '#FFFFFF' + }, description: 'Title bar foreground when the window is active. Note that this color is currently only supported on macOS.' + }, + { + id: 'titleBar.inactiveForeground', defaults: { + dark: Color.transparent('titleBar.activeForeground', 0.6), + light: Color.transparent('titleBar.activeForeground', 0.6) + }, description: 'Title bar foreground when the window is inactive. Note that this color is currently only supported on macOS.' + }, { + id: 'titleBar.activeBackground', defaults: { + dark: '#3C3C3C', + light: '#DDDDDD', + hc: '#000000' + }, description: 'Title bar background when the window is active. Note that this color is currently only supported on macOS.' + }, { + id: 'titleBar.inactiveBackground', defaults: { + dark: Color.transparent('titleBar.activeBackground', 0.6), + light: Color.transparent('titleBar.activeBackground', 0.6) + }, description: 'Title bar background when the window is inactive. Note that this color is currently only supported on macOS.' + }, { + id: 'titleBar.border', defaults: { + hc: 'contrastBorder' + }, description: 'Title bar border color. Note that this color is currently only supported on macOS.' + }, + + // Menu Bar colors should be aligned with https://code.visualstudio.com/api/references/theme-color#menu-bar-colors + { + id: 'menubar.selectionForeground', defaults: { + dark: 'titleBar.activeForeground', + light: 'titleBar.activeForeground', + hc: 'titleBar.activeForeground' + }, description: 'Foreground color of the selected menu item in the menubar.' + }, { + id: 'menubar.selectionBackground', defaults: { + dark: Color.transparent('#ffffff', 0.1), + light: Color.transparent('#000000', 0.1) + }, description: 'Background color of the selected menu item in the menubar.' + }, { + id: 'menubar.selectionBorder', defaults: { + hc: 'activeContrastBorder' + }, description: 'Border color of the selected menu item in the menubar.' + }, + { + id: 'menu.border', defaults: { + hc: 'contrastBorder' + }, description: 'Border color of menus.' + }, { + id: 'menu.foreground', defaults: { + dark: 'dropdown.foreground', light: 'foreground', hc: 'dropdown.foreground' + }, + description: 'Foreground color of menu items.' + }, { + id: 'menu.background', defaults: { + dark: 'dropdown.background', light: 'dropdown.background', hc: 'dropdown.background' + }, description: 'Background color of menu items.' + }, { + id: 'menu.selectionForeground', defaults: { + dark: 'list.activeSelectionForeground', light: 'list.activeSelectionForeground', hc: 'list.activeSelectionForeground' + }, description: 'Foreground color of the selected menu item in menus.' + }, + { + id: 'menu.selectionBackground', defaults: + { dark: 'list.activeSelectionBackground', light: 'list.activeSelectionBackground', hc: 'list.activeSelectionBackground' }, + description: 'Background color of the selected menu item in menus.' + }, + { + id: 'menu.selectionBorder', defaults: { + hc: 'activeContrastBorder' + }, description: 'Border color of the selected menu item in menus.' + }, + { + id: 'menu.separatorBackground', defaults: { + dark: '#BBBBBB', light: '#888888', hc: 'contrastBorder' + }, + description: 'Color of a separator menu item in menus.' + }, + // Welcome Page colors should be aligned with https://code.visualstudio.com/api/references/theme-color#welcome-page { id: 'welcomePage.background', description: 'Background color for the Welcome page.' }, { id: 'welcomePage.buttonBackground', defaults: { dark: Color.rgba(0, 0, 0, .2), light: Color.rgba(0, 0, 0, .04), hc: Color.black }, description: 'Background color for the buttons on the Welcome page.' }, diff --git a/packages/core/src/browser/style/menus.css b/packages/core/src/browser/style/menus.css index 0471c7f585e6e..d05b1b6c6b38a 100644 --- a/packages/core/src/browser/style/menus.css +++ b/packages/core/src/browser/style/menus.css @@ -22,6 +22,7 @@ :root { --theia-private-menubar-height: 32px; --theia-private-menu-item-height: 24px; + --theia-menu-z-index: 10000; } @@ -32,8 +33,6 @@ .p-Widget.p-MenuBar { padding-left: 5px; - background: var(--theia-menu-color0); - color: var(--theia-ui-bar-font-color1); font-size: var(--theia-ui-font-size1); } @@ -45,30 +44,29 @@ .p-MenuBar-item { padding: 0px 8px; - border-left: var(--theia-border-width) solid transparent; - border-right: var(--theia-border-width) solid transparent; + border-left: var(--theia-border-width) solid var(--theia-menu-border); + border-right: var(--theia-border-width) solid var(--theia-menu-border); line-height: var(--theia-private-menubar-height); } .p-MenuBar-item.p-mod-active { - background: var(--theia-menu-color2); - color: var(--theia-ui-bar-font-color0); + background: var(--theia-menubar-selectionBackground); + color: var(--theia-menubar-selectionForeground); opacity: 1; } .p-MenuBar.p-mod-active .p-MenuBar-item.p-mod-active { - z-index: 10001; - background: var(--theia-menu-color1); - border-left: var(--theia-border-width) solid var(--theia-border-color1); - border-right: var(--theia-border-width) solid var(--theia-border-color1); - box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.2); + z-index: calc(var(--theia-menu-z-index) - 1); + background: var(--theia-menubar-selectionBackground); + border-left: var(--theia-border-width) solid var(--theia-menubar-selectionBorder); + border-right: var(--theia-border-width) solid var(--theia-menubar-selectionBorder); } .p-MenuBar-item.p-mod-disabled { - opacity: var(--theia-mod-disabled-opacity);; + opacity: var(--theia-mod-disabled-opacity); } @@ -76,7 +74,7 @@ margin: 2px; padding: 0; border: none; - border-left: var(--theia-border-width) solid var(--theia-border-color2); + border-left: var(--theia-border-width) solid var(--theia-menu-separatorBackground); } @@ -86,11 +84,17 @@ #theia-top-panel { - background: var(--theia-menu-color0); + background: var(--theia-titleBar-activeBackground); + color: var(--theia-titleBar-activeForeground); display: flex; min-height: var(--theia-private-menubar-height); + border-bottom: 1px solid var(--theia-titleBar-border); +} +#theia-top-panel:window-inactive, +#theia-top-panel:-moz-window-inactive { + background: var(--theia-titleBar-inactiveBackground); + color: var(--theia-titleBar-inactiveForeground); } - /*----------------------------------------------------------------------------- | Menu @@ -98,15 +102,15 @@ .p-Menu { - z-index: 10000; + z-index: var(--theia-menu-z-index); padding: 4px 0px; - background: var(--theia-menu-color1); - color: var(--theia-ui-font-color1); + background: var(--theia-menu-background); + color: var(--theia-menu-foreground); font-size: var(--theia-ui-font-size1); - box-shadow: 0px 1px 6px rgba(0, 0, 0, 0.2); + box-shadow: 0px 1px 6px var(--theia-widget-shadow); + border: 1px solid var(--theia-menu-border); } - .p-Menu-item { min-height: var(--theia-private-menu-item-height); max-height: var(--theia-private-menu-item-height); @@ -116,14 +120,15 @@ .p-Menu-item.p-mod-active { - background: var(--theia-menu-color2); - color: var(--theia-ui-bar-font-color0); + background: var(--theia-menu-selectionBackground); + color: var(--theia-menu-selectionForeground); + border: thin solid var(--theia-menu-selectionBorder); opacity: 1; } .p-Menu-item.p-mod-disabled { - opacity: var(--theia-mod-disabled-opacity);; + opacity: var(--theia-mod-disabled-opacity); } @@ -166,7 +171,7 @@ display: block; position: relative; top: 4px; - border-top: var(--theia-border-width) solid var(--theia-ui-font-color3); + border-top: var(--theia-border-width) solid var(--theia-menu-separatorBackground); } .p-Menu-itemIcon::before, From 52e0a1eaef6a2bd1fb2b1a283c4c11313498c8d2 Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Thu, 12 Dec 2019 12:15:58 +0000 Subject: [PATCH 28/65] apply vscode colors to dialogs Signed-off-by: Anton Kosyakov --- .../src/browser/connection-status-service.ts | 2 +- .../core/src/browser/style/alert-messages.css | 2 +- packages/core/src/browser/style/dialog.css | 30 +++++++------------ packages/core/src/browser/style/index.css | 12 +++++--- .../style/variables-bright.useable.css | 4 --- .../browser/style/variables-dark.useable.css | 4 --- .../src/browser/style/index.css | 2 +- .../src/browser/style/file-dialog.css | 7 ++--- packages/git/src/browser/style/index.css | 6 ++-- packages/keymaps/src/browser/style/index.css | 2 +- .../src/browser/problem/problem-decorator.ts | 2 +- .../problem/problem-tabbar-decorator.ts | 2 +- packages/markers/src/browser/style/index.css | 2 +- .../mini-browser/src/browser/style/index.css | 2 +- .../browser/hosted-plugin-manager-client.ts | 2 +- .../plugin-ext/src/main/browser/commands.ts | 2 +- .../dialogs/style/modal-notification.css | 8 ++--- .../status-bar-message-registry-main.ts | 6 +++- .../src/plugin/status-bar/status-bar-item.ts | 11 +------ .../src/plugin/status-bar/vscolor-const.ts | 21 ------------- packages/scm/src/browser/style/index.css | 4 +-- .../src/browser/styles/index.css | 6 ++-- 22 files changed, 50 insertions(+), 89 deletions(-) delete mode 100644 packages/plugin-ext/src/plugin/status-bar/vscolor-const.ts diff --git a/packages/core/src/browser/connection-status-service.ts b/packages/core/src/browser/connection-status-service.ts index 8e3cfc0cfc5b1..ae75281247731 100644 --- a/packages/core/src/browser/connection-status-service.ts +++ b/packages/core/src/browser/connection-status-service.ts @@ -210,7 +210,7 @@ export class ApplicationConnectionStatusContribution extends DefaultFrontendAppl tooltip: 'Cannot connect to backend.', priority: 5000 }); - this.statusBar.setBackgroundColor('var(--theia-warn-color0)'); + this.statusBar.setBackgroundColor('var(--theia-editorWarning-foreground)'); this.statusBar.setColor('var(--theia-warn-font-color0)'); } } diff --git a/packages/core/src/browser/style/alert-messages.css b/packages/core/src/browser/style/alert-messages.css index 9e09ee0e756d3..bb697c71d5ce8 100644 --- a/packages/core/src/browser/style/alert-messages.css +++ b/packages/core/src/browser/style/alert-messages.css @@ -40,7 +40,7 @@ /* warning message */ .theia-warning-alert { - background-color: var(--theia-warn-color0); + background-color: var(--theia-editorWarning-foreground); color: var(--theia-warn-font-color0); padding: 10px; } diff --git a/packages/core/src/browser/style/dialog.css b/packages/core/src/browser/style/dialog.css index 21cc1bb1e1681..d4c55578fdb8c 100644 --- a/packages/core/src/browser/style/dialog.css +++ b/packages/core/src/browser/style/dialog.css @@ -25,8 +25,7 @@ left: 0; justify-content: center; align-items: center; - background: rgba(1,1,1,0.5); - color: var(--theia-ui-font-color1); + background: rgba(0, 0, 0, 0.3); font-size: var(--theia-ui-font-size1); padding: 2px; } @@ -35,8 +34,10 @@ flex-direction: column; min-width: 400px; min-height: 150px; - background-color: var(--theia-ui-dialog-color); - color: var(--theia-ui-dialog-font-color); + color: var(--theia-editorWidget-foreground); + background-color: var(--theia-editorWidget-background); + border: 1px solid var(--theia-contrastBorder); + box-shadow: 0 0px 8px var(--theia-widget-shadow); } .p-Widget.dialogOverlay .dialogTitle { display: flex; @@ -46,8 +47,8 @@ align-items: center; text-align: center; font-size: var(--theia-ui-font-size1); - background-color: var(--theia-ui-dialog-header-color); - color: var(--theia-ui-dialog-header-font-color); + background-color: var(--theia-statusBar-background); + color: var(--theia-statusBar-foreground); padding: 0 calc(var(--theia-ui-padding)*2); min-height: 24px; } @@ -93,15 +94,6 @@ input { outline: none; } -.p-Widget.dialogOverlay select { - border: 1px solid var(--theia-border-color1); - color: var(--theia-ui-font-color1); - font-size: var(--theia-ui-font-size1); - border-radius: 0; - background: transparent; - outline: none; -} - .p-Widget.dialogOverlay.hidden { display: none; } @@ -109,14 +101,14 @@ input { display: none; } .p-Widget.dialogOverlay .error { - color: var(--theia-error-color1); + color: var(--theia-editorError-foreground); } .p-Widget.dialogOverlay .error.main { - color: var(--theia-error-color1); - border-color: var(--theia-error-color1); + color: var(--theia-editorError-foreground); + border-color: var(--theia-editorError-border); } .p-Widget.dialogOverlay .error > .theia-button.main { - background-color: var(--theia-error-color1); + background-color: var(--theia-editorError-foreground); color: var(--theia-ui-font-color1); } .p-Widget.dialogOverlay .error > .dialogErrorMessage { diff --git a/packages/core/src/browser/style/index.css b/packages/core/src/browser/style/index.css index d34d3430a93f9..14e35620074d2 100644 --- a/packages/core/src/browser/style/index.css +++ b/packages/core/src/browser/style/index.css @@ -163,15 +163,19 @@ button.secondary[disabled], .theia-button.secondary[disabled] { background-color: var(--theia-ui-button-color-secondary-disabled); } -.p-Widget select { - color: var(--theia-ui-font-color1); +select { + color: var(--dropdown-foreground); font-size: var(--theia-ui-font-size1); border-radius: 0; - border: 1px solid var(--theia-border-color1); - background: var(--theia-layout-color2); + border: 1px solid var(--theia-dropdown-border); + background: var(--theia-dropdown-background); outline: none; } +select option { + background: var(--theia-dropdown-listBackground); +} + textarea { font-family: var(--theia-ui-font-family); } diff --git a/packages/core/src/browser/style/variables-bright.useable.css b/packages/core/src/browser/style/variables-bright.useable.css index 5667e657181d8..4717895a8ef90 100644 --- a/packages/core/src/browser/style/variables-bright.useable.css +++ b/packages/core/src/browser/style/variables-bright.useable.css @@ -124,7 +124,6 @@ is not optimized for dense, information rich UIs. /* State colors (warn, error, success, info) ------------------------------------------ */ - --theia-warn-color0: var(--md-amber-500); --theia-warn-color1: var(--md-amber-400); --theia-warn-color2: var(--md-amber-300); --theia-warn-color3: var(--md-amber-200); @@ -132,7 +131,6 @@ is not optimized for dense, information rich UIs. --theia-warn-font-color0: var(--md-grey-900); --theia-error-color0: var(--md-red-400); - --theia-error-color1: var(--md-red-300); --theia-error-color2: var(--md-red-200); --theia-error-color3: var(--md-red-100); @@ -232,8 +230,6 @@ is not optimized for dense, information rich UIs. /* Dialogs */ --theia-ui-dialog-header-color: var(--theia-brand-color1); --theia-ui-dialog-header-font-color: var(--theia-inverse-ui-font-color0); - --theia-ui-dialog-color: var(--theia-layout-color0); - --theia-ui-dialog-font-color: var(--theia-ui-font-color1); /* Variables */ --theia-variable-name-color: #9B46B0; diff --git a/packages/core/src/browser/style/variables-dark.useable.css b/packages/core/src/browser/style/variables-dark.useable.css index 262d575279f26..67c3b79ee8efd 100644 --- a/packages/core/src/browser/style/variables-dark.useable.css +++ b/packages/core/src/browser/style/variables-dark.useable.css @@ -124,7 +124,6 @@ is not optimized for dense, information rich UIs. /* State colors (warn, error, success, info) ------------------------------------------ */ - --theia-warn-color0: var(--md-amber-600); --theia-warn-color1: var(--md-amber-500); --theia-warn-color2: var(--md-amber-400); --theia-warn-color3: var(--md-amber-300); @@ -132,7 +131,6 @@ is not optimized for dense, information rich UIs. --theia-warn-font-color0: var(--md-grey-900); --theia-error-color0: var(--md-red-700); - --theia-error-color1: var(--md-red-500); --theia-error-color2: var(--md-red-300); --theia-error-color3: var(--md-red-100); @@ -232,8 +230,6 @@ is not optimized for dense, information rich UIs. /* Dialogs */ --theia-ui-dialog-header-color: var(--theia-brand-color0); --theia-ui-dialog-header-font-color: var(--theia-ui-font-color1); - --theia-ui-dialog-color: var(--theia-layout-color4); - --theia-ui-dialog-font-color: var(--theia-ui-font-color1); /* Variables */ --theia-variable-name-color: #C586C0; diff --git a/packages/extension-manager/src/browser/style/index.css b/packages/extension-manager/src/browser/style/index.css index 18e162ae8b054..de6a20f79ad73 100644 --- a/packages/extension-manager/src/browser/style/index.css +++ b/packages/extension-manager/src/browser/style/index.css @@ -70,7 +70,7 @@ } .extensionButton.installed { - background-color: var(--theia-error-color1); + background-color: var(--theia-editorError-foreground); } .extensionButton.outdated { diff --git a/packages/filesystem/src/browser/style/file-dialog.css b/packages/filesystem/src/browser/style/file-dialog.css index c99b228a33846..a8d27c856edcd 100644 --- a/packages/filesystem/src/browser/style/file-dialog.css +++ b/packages/filesystem/src/browser/style/file-dialog.css @@ -23,7 +23,8 @@ .dialogContent .theia-ResponsiveFileDialog { height: 500px; width: 500px; - background-color: var(--theia-layout-color0); + border: 1px solid var(--theia-editorWidget-border); + background: var(--theia-dropdown-background); } @@ -95,7 +96,6 @@ .dialogContent .theia-LocationList { width: 427px; height: 21px; - background: var(--theia-layout-color2)!important; } /* @@ -117,8 +117,7 @@ .dialogContent .theia-FileTreeFiltersList { width: 427px; - height: 21px; - background: var(--theia-layout-color2)!important; + height: 21px; } /* diff --git a/packages/git/src/browser/style/index.css b/packages/git/src/browser/style/index.css index ee4cb3ac7861c..b0726518c0eda 100644 --- a/packages/git/src/browser/style/index.css +++ b/packages/git/src/browser/style/index.css @@ -83,7 +83,7 @@ } .theia-git .gitItem .status.deleted { - color: var(--theia-warn-color0); + color: var(--theia-editorWarning-foreground); } .theia-git .gitItem .status.renamed { @@ -141,7 +141,7 @@ } .theia-git-commit-message-warning { - border-color: var(--theia-warn-color0); + border-color: var(--theia-editorWarning-foreground); } .theia-git-commit-message-error { @@ -169,7 +169,7 @@ .theia-git-message-warning, .theia-git-validation-message-warning { - background-color: var(--theia-warn-color0) !important; + background-color: var(--theia-editorWarning-foreground) !important; color: var(--theia-warn-font-color0); } diff --git a/packages/keymaps/src/browser/style/index.css b/packages/keymaps/src/browser/style/index.css index ba07af81469c5..e22a73f4f1d95 100644 --- a/packages/keymaps/src/browser/style/index.css +++ b/packages/keymaps/src/browser/style/index.css @@ -157,7 +157,7 @@ } .no-kb { - border: 1px solid var(--theia-warn-color0); + border: 1px solid var(--theia-editorWarning-foreground); } #search-kb { diff --git a/packages/markers/src/browser/problem/problem-decorator.ts b/packages/markers/src/browser/problem/problem-decorator.ts index 15f27bd7aa84b..ee10b5a9dfc42 100644 --- a/packages/markers/src/browser/problem/problem-decorator.ts +++ b/packages/markers/src/browser/problem/problem-decorator.ts @@ -156,7 +156,7 @@ export class ProblemDecorator implements TreeDecorator { const { severity } = marker.data; switch (severity) { case 1: return 'var(--theia-error-color0)'; - case 2: return 'var(--theia-warn-color0)'; + case 2: return 'var(--theia-editorWarning-foreground)'; case 3: return 'var(--theia-info-color0)'; default: return 'var(--theia-success-color0)'; } diff --git a/packages/markers/src/browser/problem/problem-tabbar-decorator.ts b/packages/markers/src/browser/problem/problem-tabbar-decorator.ts index 33de77b77790c..001ced2f20eba 100644 --- a/packages/markers/src/browser/problem/problem-tabbar-decorator.ts +++ b/packages/markers/src/browser/problem/problem-tabbar-decorator.ts @@ -140,7 +140,7 @@ export class ProblemTabBarDecorator implements TabBarDecorator { const { severity } = marker.data; switch (severity) { case 1: return 'var(--theia-error-color0)'; - case 2: return 'var(--theia-warn-color0)'; + case 2: return 'var(--theia-editorWarning-foreground)'; case 3: return 'var(--theia-info-color0)'; default: return 'var(--theia-success-color0)'; } diff --git a/packages/markers/src/browser/style/index.css b/packages/markers/src/browser/style/index.css index 62947eb4d7cd5..587173a9b7da5 100644 --- a/packages/markers/src/browser/style/index.css +++ b/packages/markers/src/browser/style/index.css @@ -58,7 +58,7 @@ } .theia-marker-container .warning { - color: var(--theia-warn-color0); + color: var(--theia-editorWarning-foreground); } .theia-marker-container .information { diff --git a/packages/mini-browser/src/browser/style/index.css b/packages/mini-browser/src/browser/style/index.css index 3b0516ae7816e..2806054e217ea 100644 --- a/packages/mini-browser/src/browser/style/index.css +++ b/packages/mini-browser/src/browser/style/index.css @@ -143,7 +143,7 @@ .theia-mini-browser-error-bar { height: 19px; padding-left: var(--theia-ui-padding); - background-color: var(--theia-warn-color0); + background-color: var(--theia-editorWarning-foreground); color: var(--theia-warn-font-color0); font-size: var(--theia-statusBar-font-size); z-index: 1000; /* Above the transparent overlay (`z-index: 999;`). */ diff --git a/packages/plugin-dev/src/browser/hosted-plugin-manager-client.ts b/packages/plugin-dev/src/browser/hosted-plugin-manager-client.ts index e1cf1ea06967d..4b6b0125cee1e 100644 --- a/packages/plugin-dev/src/browser/hosted-plugin-manager-client.ts +++ b/packages/plugin-dev/src/browser/hosted-plugin-manager-client.ts @@ -323,7 +323,7 @@ class OpenHostedInstanceLinkDialog extends AbstractDialog { this.linkNode = document.createElement('a'); this.linkNode.target = '_blank'; - this.linkNode.setAttribute('style', 'color: var(--theia-ui-dialog-font-color);'); + this.linkNode.setAttribute('style', 'color: var(--theia-editorWidget-foreground);'); this.contentNode.appendChild(this.linkNode); const messageNode = document.createElement('div'); diff --git a/packages/plugin-ext/src/main/browser/commands.ts b/packages/plugin-ext/src/main/browser/commands.ts index d16cf67cb2fee..84b76ad973bcf 100644 --- a/packages/plugin-ext/src/main/browser/commands.ts +++ b/packages/plugin-ext/src/main/browser/commands.ts @@ -75,7 +75,7 @@ class OpenNewTabDialog extends AbstractDialog { this.linkNode = document.createElement('a'); this.linkNode.target = '_blank'; - this.linkNode.setAttribute('style', 'color: var(--theia-ui-dialog-font-color);'); + this.linkNode.setAttribute('style', 'color: var(--theia-editorWidget-foreground);'); this.contentNode.appendChild(this.linkNode); const messageNode = document.createElement('div'); diff --git a/packages/plugin-ext/src/main/browser/dialogs/style/modal-notification.css b/packages/plugin-ext/src/main/browser/dialogs/style/modal-notification.css index de1cbdef0f886..b168e1b5c53f4 100644 --- a/packages/plugin-ext/src/main/browser/dialogs/style/modal-notification.css +++ b/packages/plugin-ext/src/main/browser/dialogs/style/modal-notification.css @@ -28,10 +28,10 @@ position: relative; width: 100%; min-width: 200px; - background-color: var(--theia-ui-dialog-color); + background-color: var(--theia-editorWidget-background); min-height: 35px; margin-bottom: 1px; - color: var(--theia-ui-dialog-font-color); + color: var(--theia-editorWidget-foreground); } .modal-Notification .icon { @@ -50,11 +50,11 @@ } .modal-Notification .icon .error { - color: var(--theia-error-color1); + color: var(--theia-editorError-foreground); } .modal-Notification .icon .warning { - color: var(--theia-warn-color0); + color: var(--theia-editorWarning-foreground); } .modal-Notification .text { diff --git a/packages/plugin-ext/src/main/browser/status-bar-message-registry-main.ts b/packages/plugin-ext/src/main/browser/status-bar-message-registry-main.ts index 07578a7e0e435..1c7509ddde1fd 100644 --- a/packages/plugin-ext/src/main/browser/status-bar-message-registry-main.ts +++ b/packages/plugin-ext/src/main/browser/status-bar-message-registry-main.ts @@ -18,6 +18,7 @@ import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposa import * as types from '../../plugin/types-impl'; import { StatusBarMessageRegistryMain } from '../../common/plugin-api-rpc'; import { StatusBar, StatusBarAlignment, StatusBarEntry } from '@theia/core/lib/browser/status-bar/status-bar'; +import { ColorRegistry } from '@theia/core/lib/browser/color-registry'; export class StatusBarMessageRegistryMainImpl implements StatusBarMessageRegistryMain, Disposable { private readonly delegate: StatusBar; @@ -26,8 +27,11 @@ export class StatusBarMessageRegistryMainImpl implements StatusBarMessageRegistr Disposable.create(() => { /* mark as not disposed */ }) ); + protected readonly colorRegistry: ColorRegistry; + constructor(container: interfaces.Container) { this.delegate = container.get(StatusBar); + this.colorRegistry = container.get(ColorRegistry); } dispose(): void { @@ -45,7 +49,7 @@ export class StatusBarMessageRegistryMainImpl implements StatusBarMessageRegistr text: text || '', priority, alignment: alignment === types.StatusBarAlignment.Left ? StatusBarAlignment.LEFT : StatusBarAlignment.RIGHT, - color, + color: color && (this.colorRegistry.getCurrentColor(color) || color), tooltip, command }; diff --git a/packages/plugin-ext/src/plugin/status-bar/status-bar-item.ts b/packages/plugin-ext/src/plugin/status-bar/status-bar-item.ts index 15517e8079ade..c1a581fd95c32 100644 --- a/packages/plugin-ext/src/plugin/status-bar/status-bar-item.ts +++ b/packages/plugin-ext/src/plugin/status-bar/status-bar-item.ts @@ -16,7 +16,6 @@ import * as theia from '@theia/plugin'; import { ThemeColor, StatusBarAlignment } from '../types-impl'; import { StatusBarMessageRegistryMain } from '../../common/plugin-api-rpc'; -import { VS_COLORS } from './vscolor-const'; import { UUID } from '@phosphor/coreutils/lib/uuid'; export class StatusBarItemImpl implements theia.StatusBarItem { @@ -116,20 +115,12 @@ export class StatusBarItemImpl implements theia.StatusBarItem { this._proxy.$setMessage(this.id, this.text, this.priority, this.alignment, - this.getColor(), + typeof this.color === 'string' ? this.color : this.color && this.color.id, this.tooltip, this.command); }, 0); } - private getColor(): string | undefined { - if (typeof this.color !== 'string' && typeof this.color !== 'undefined') { - const colorId = (this.color).id; - return `var(${VS_COLORS[colorId] ? VS_COLORS[colorId] : colorId})`; - } - return this.color; - } - public dispose(): void { this.hide(); } diff --git a/packages/plugin-ext/src/plugin/status-bar/vscolor-const.ts b/packages/plugin-ext/src/plugin/status-bar/vscolor-const.ts deleted file mode 100644 index bcfbe0adfb216..0000000000000 --- a/packages/plugin-ext/src/plugin/status-bar/vscolor-const.ts +++ /dev/null @@ -1,21 +0,0 @@ -/******************************************************************************** - * Copyright (C) 2018 Red Hat, Inc. 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 - ********************************************************************************/ -export const VS_COLORS: {[vsColorId: string]: string} = { - 'statusBar.foreground': '--theia-layout-color4', - 'editorOverviewRuler.errorForeground': '--theia-error-color0', - 'editorOverviewRuler.warningForeground': '--theia-warn-color0', - 'editorOverviewRuler.infoForeground': '--theia-info-color0' -}; diff --git a/packages/scm/src/browser/style/index.css b/packages/scm/src/browser/style/index.css index 1fe0292ce179b..f04d19be09d20 100644 --- a/packages/scm/src/browser/style/index.css +++ b/packages/scm/src/browser/style/index.css @@ -128,7 +128,7 @@ } .theia-scm-input-message-warning { - border-color: var(--theia-warn-color0); + border-color: var(--theia-editorWarning-foreground); } .theia-scm-input-message-error { @@ -156,7 +156,7 @@ .theia-scm-message-warning, .theia-scm-validation-message-warning { - background-color: var(--theia-warn-color0) !important; + background-color: var(--theia-editorWarning-foreground) !important; color: var(--theia-warn-font-color0); } diff --git a/packages/search-in-workspace/src/browser/styles/index.css b/packages/search-in-workspace/src/browser/styles/index.css index 5f3f71eebc44d..50d5fe109730e 100644 --- a/packages/search-in-workspace/src/browser/styles/index.css +++ b/packages/search-in-workspace/src/browser/styles/index.css @@ -121,7 +121,7 @@ border-style: solid; border-width: var(--theia-border-width); margin: -1px; - border-color: var(--theia-warn-color0); + border-color: var(--theia-editorWarning-foreground); } .t-siw-search-container .searchHeader .search-field-container .search-notification { @@ -136,13 +136,13 @@ } .t-siw-search-container .searchHeader .search-notification div{ - background-color: var(--theia-warn-color0); + background-color: var(--theia-editorWarning-foreground); width: calc(100% + 2px); margin-left: -1px; color: var(--theia-warn-font-color0); z-index: 1000; position: absolute; - border: 1px solid var(--theia-warn-color0); + border: 1px solid var(--theia-editorWarning-foreground); box-sizing: border-box; padding: 3px; } From 3bf626b29efb16d1d324357415e06d718bc6834e Mon Sep 17 00:00:00 2001 From: Jan Bicker Date: Thu, 12 Dec 2019 12:38:45 +0000 Subject: [PATCH 29/65] Applied Text colors Signed-off-by: Jan Bicker --- .../browser/common-frontend-contribution.ts | 1 + packages/core/src/browser/style/index.css | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/packages/core/src/browser/common-frontend-contribution.ts b/packages/core/src/browser/common-frontend-contribution.ts index caebafc1638f7..393f58393dfe3 100644 --- a/packages/core/src/browser/common-frontend-contribution.ts +++ b/packages/core/src/browser/common-frontend-contribution.ts @@ -758,6 +758,7 @@ export class CommonFrontendContribution implements FrontendApplicationContributi { id: 'icon.foreground', defaults: { dark: '#C5C5C5', light: '#424242', hc: '#FFFFFF' }, description: 'The default color for icons in the workbench.' }, // Buttons should be aligned with https://code.visualstudio.com/api/references/theme-color#button-control + // if not yet contributed by Monaco, check runtime css variables to learn { id: 'button.foreground', defaults: { dark: Color.white, light: Color.white, hc: Color.white }, description: 'Button foreground color.' }, { id: 'button.background', defaults: { dark: '#0E639C', light: '#007ACC' }, description: 'Button background color.' }, { id: 'button.hoverBackground', defaults: { dark: Color.lighten('button.background', 0.2), light: Color.darken('button.background', 0.2) }, description: 'Button background color when hovering.' }, diff --git a/packages/core/src/browser/style/index.css b/packages/core/src/browser/style/index.css index 14e35620074d2..852394cbcb957 100644 --- a/packages/core/src/browser/style/index.css +++ b/packages/core/src/browser/style/index.css @@ -30,6 +30,23 @@ body { color: var(--theia-foreground); } +a { + color: var(--theia-textLink-foreground); +} + +a:active, a:hover { + color: var(--theia-textLink-activeForeground); +} + +code { + color: var(--theia-textPreformat-foreground); +} + +blockquote { + color: var(--theia-textBlockQuote-background); + border: var(--theia-border-width) solid var(--theia-textBlockQuote-border); +} + .theia-maximized { position: fixed !important; top: 0 !important; @@ -90,7 +107,6 @@ body { .p-Widget { font-size: var(--theia-ui-font-size1); - color: var(--theia-ui-font-color1); } .p-Widget.p-mod-hidden { From a4ca5508b3afc86ab0cf2032ec9d27871c80afbf Mon Sep 17 00:00:00 2001 From: Jan Bicker Date: Thu, 12 Dec 2019 12:49:18 +0000 Subject: [PATCH 30/65] Improved look of navigator search-box Signed-off-by: Jan Bicker --- packages/core/src/browser/style/search-box.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/core/src/browser/style/search-box.css b/packages/core/src/browser/style/search-box.css index dae7ef0c223cc..434c73c2a1704 100644 --- a/packages/core/src/browser/style/search-box.css +++ b/packages/core/src/browser/style/search-box.css @@ -23,8 +23,9 @@ align-items: baseline; box-shadow: var(--theia-border-width) var(--theia-border-width) var(--theia-border-color0); line-height: var(--theia-private-horizontal-tab-height); - background-color: var(--theia-editorWidget-background); + background-color: var(--theia-editor-background); z-index: 1; + border: var(--theia-border-width) solid var(--theia-editor-background) } .theia-search-input { From dee87771a045e09138cdb5c442ad27e144abc05e Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Thu, 12 Dec 2019 14:22:44 +0000 Subject: [PATCH 31/65] apply window border vscode colors Signed-off-by: Anton Kosyakov --- .../src/browser/common-frontend-contribution.ts | 13 +++++++++++++ packages/core/src/browser/style/index.css | 5 +++++ 2 files changed, 18 insertions(+) diff --git a/packages/core/src/browser/common-frontend-contribution.ts b/packages/core/src/browser/common-frontend-contribution.ts index 393f58393dfe3..23b75c2ab0768 100644 --- a/packages/core/src/browser/common-frontend-contribution.ts +++ b/packages/core/src/browser/common-frontend-contribution.ts @@ -757,6 +757,19 @@ export class CommonFrontendContribution implements FrontendApplicationContributi { id: 'selection.background', defaults: { dark: '#217daf', light: '#c0dbf1' }, description: 'Overall border color for focused elements. This color is only used if not overridden by a component.' }, { id: 'icon.foreground', defaults: { dark: '#C5C5C5', light: '#424242', hc: '#FFFFFF' }, description: 'The default color for icons in the workbench.' }, + // Window border colors should be aligned with https://code.visualstudio.com/api/references/theme-color#window-border + { + id: 'window.activeBorder', defaults: { + hc: 'contrastBorder' + }, description: 'The color used for the border of the window when it is active.' + }, + { + id: 'window.inactiveBorder', defaults: { + hc: 'contrastBorder' + }, + description: 'The color used for the border of the window when it is inactive.' + }, + // Buttons should be aligned with https://code.visualstudio.com/api/references/theme-color#button-control // if not yet contributed by Monaco, check runtime css variables to learn { id: 'button.foreground', defaults: { dark: Color.white, light: Color.white, hc: Color.white }, description: 'Button foreground color.' }, diff --git a/packages/core/src/browser/style/index.css b/packages/core/src/browser/style/index.css index 852394cbcb957..45b6435a89303 100644 --- a/packages/core/src/browser/style/index.css +++ b/packages/core/src/browser/style/index.css @@ -28,6 +28,11 @@ body { font-family: var(--theia-ui-font-family); background: var(--theia-layout-color0); color: var(--theia-foreground); + border: 1px solid var(--theia-window-activeBorder); +} +body:window-inactive, +body:-moz-window-inactive { + border-color: var(--theia-window-inactiveBorder); } a { From e09a6cbd8f8805ae9029cb8682105227d7375b9a Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Thu, 12 Dec 2019 14:32:38 +0000 Subject: [PATCH 32/65] [theming] remove usage of deprecated styles for box-shadow attributes Signed-off-by: Anton Kosyakov --- packages/core/src/browser/style/scrollbars.css | 2 +- packages/core/src/browser/style/search-box.css | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/src/browser/style/scrollbars.css b/packages/core/src/browser/style/scrollbars.css index 1e3a126ffc179..dcf6d10e5ec5e 100644 --- a/packages/core/src/browser/style/scrollbars.css +++ b/packages/core/src/browser/style/scrollbars.css @@ -174,5 +174,5 @@ } .monaco-scrollable-element > .shadow.top { - box-shadow: var(--theia-scrollbar-box-shadow-color) 0px 6px 6px -6px inset !important; + box-shadow: var(--theia-widget-shadow) 0px 6px 6px -6px inset !important; } diff --git a/packages/core/src/browser/style/search-box.css b/packages/core/src/browser/style/search-box.css index 434c73c2a1704..4c86f1ecffd13 100644 --- a/packages/core/src/browser/style/search-box.css +++ b/packages/core/src/browser/style/search-box.css @@ -21,7 +21,7 @@ right: 0px; display: flex; align-items: baseline; - box-shadow: var(--theia-border-width) var(--theia-border-width) var(--theia-border-color0); + box-shadow: var(--theia-border-width) var(--theia-border-width) var(--theia-widget-shadow); line-height: var(--theia-private-horizontal-tab-height); background-color: var(--theia-editor-background); z-index: 1; From 305ff32ad7a84e4288068accaf64aaeba94eca8a Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Thu, 12 Dec 2019 15:27:05 +0000 Subject: [PATCH 33/65] [console] remove usage of deprecated css variables Signed-off-by: Anton Kosyakov --- packages/console/src/browser/style/index.css | 8 +- packages/core/src/browser/color-registry.ts | 2 +- .../browser/common-frontend-contribution.ts | 174 ++++++++++++++++++ .../style/variables-bright.useable.css | 27 --- .../browser/style/variables-dark.useable.css | 27 --- 5 files changed, 178 insertions(+), 60 deletions(-) diff --git a/packages/console/src/browser/style/index.css b/packages/console/src/browser/style/index.css index 44195fa95c4a0..6a76b1e86455f 100644 --- a/packages/console/src/browser/style/index.css +++ b/packages/console/src/browser/style/index.css @@ -15,7 +15,6 @@ ********************************************************************************/ .theia-console-content { - color: var(--theia-content-font-color0); font-size: var(--theia-code-font-size); line-height: var(--theia-code-line-height); font-family: var(--theia-code-font-family); @@ -23,7 +22,7 @@ .theia-console-input { padding-left: 20px; - border-top: var(--theia-panel-border-width) solid var(--theia-border-color1); + border-top: var(--theia-panel-border-width) solid var(--theia-panel-border); } .theia-console-input:before { @@ -31,15 +30,14 @@ position: absolute; content: '\276f'; line-height: 18px; - color: var(--theia-ui-font-color1); } .theia-console-error { - color: var(--theia-error-color2); + color: var(--theia-errorForeground); } .theia-console-warning { - color: var(--theia-warn-color2); + color: var(--theia-editorWarning-foreground); } .theia-console-ansi-console-item { diff --git a/packages/core/src/browser/color-registry.ts b/packages/core/src/browser/color-registry.ts index 27018a6e796aa..0494a0d18f7b4 100644 --- a/packages/core/src/browser/color-registry.ts +++ b/packages/core/src/browser/color-registry.ts @@ -127,7 +127,7 @@ export class ColorRegistry { } toCssVariableName(id: string, prefix = 'theia'): string { - return `--${prefix}-${id.replace('.', '-')}`; + return `--${prefix}-${id.replace(/\./g, '-')}`; } getCurrentColor(id: string): string | undefined { diff --git a/packages/core/src/browser/common-frontend-contribution.ts b/packages/core/src/browser/common-frontend-contribution.ts index 23b75c2ab0768..37cc1f4a35eae 100644 --- a/packages/core/src/browser/common-frontend-contribution.ts +++ b/packages/core/src/browser/common-frontend-contribution.ts @@ -1173,6 +1173,180 @@ export class CommonFrontendContribution implements FrontendApplicationContributi { id: 'welcomePage.buttonBackground', defaults: { dark: Color.rgba(0, 0, 0, .2), light: Color.rgba(0, 0, 0, .04), hc: Color.black }, description: 'Background color for the buttons on the Welcome page.' }, { id: 'welcomePage.buttonHoverBackground', defaults: { dark: Color.rgba(200, 235, 255, .072), light: Color.rgba(0, 0, 0, .10) }, description: 'Hover background color for the buttons on the Welcome page.' }, { id: 'walkThrough.embeddedEditorBackground', defaults: { dark: Color.rgba(0, 0, 0, .4), light: '#f4f4f4' }, description: 'Background color for the embedded editors on the Interactive Playground.' }, + + // Theia Variable colors + { + id: 'variable.name.color', defaults: { + dark: '#C586C0', + light: '#9B46B0', + hc: '#C586C0' + }, + description: 'Color of a variable name.' + }, + { + id: 'variable.value.color', defaults: { + dark: Color.rgba(204, 204, 204, 0.6), + light: Color.rgba(108, 108, 108, 0.8), + hc: Color.rgba(204, 204, 204, 0.6) + }, + description: 'Color of a variable value.' + }, + { + id: 'variable.number.variable.color', defaults: { + dark: '#B5CEA8', + light: '#09885A', + hc: '#B5CEA8' + }, + description: 'Value color of a number variable' + }, + { + id: 'variable.boolean.variable.color', defaults: { + dark: '#4E94CE', + light: '#0000FF', + hc: '#4E94CE' + }, + description: 'Value color of a boolean variable' + }, + { + id: 'variable.string.variable.color', defaults: { + dark: '#CE9178', + light: '#A31515', + hc: '#CE9178' + }, + description: 'Value color of a string variable' + }, + + // Theia ANSI colors + { + id: 'ansi.black.color', defaults: { + dark: '#A0A0A0', + light: Color.rgba(128, 128, 128), + hc: '#A0A0A0' + }, + description: 'ANSI black color' + }, + { + id: 'ansi.red.color', defaults: { + dark: '#A74747', + light: '#BE1717', + hc: '#A74747' + }, + description: 'ANSI red color' + }, + { + id: 'ansi.green.color', defaults: { + dark: '#348F34', + light: '#338A2F', + hc: '#348F34' + }, + description: 'ANSI green color' + }, + { + id: 'ansi.yellow.color', defaults: { + dark: '#5F4C29', + light: '#BEB817', + hc: '#5F4C29' + }, + description: 'ANSI yellow color' + }, + { + id: 'ansi.blue.color', defaults: { + dark: '#6286BB', + light: Color.rgba(0, 0, 139), + hc: '#6286BB' + }, + description: 'ANSI blue color' + }, + { + id: 'ansi.magenta.color', defaults: { + dark: '#914191', + light: Color.rgba(139, 0, 139), + hc: '#914191' + }, + description: 'ANSI magenta color' + }, + { + id: 'ansi.cyan.color', defaults: { + dark: '#218D8D', + light: Color.rgba(0, 139, 139), + hc: '#218D8D' + }, + description: 'ANSI cyan color' + }, + { + id: 'ansi.white.color', defaults: { + dark: '#707070', + light: '#BDBDBD', + hc: '#707070' + }, + description: 'ANSI white color' + }, + + // Theia ANSI background colors + { + id: 'ansi.black.background.color', defaults: { + dark: '#A0A0A0', + light: Color.rgba(128, 128, 128), + hc: '#A0A0A0' + }, + description: 'ANSI black background color' + }, + { + id: 'ansi.red.background.color', defaults: { + dark: '#A74747', + light: '#BE1717', + hc: '#A74747' + }, + description: 'ANSI red background color' + }, + { + id: 'ansi.green.background.color', defaults: { + dark: '#348F34', + light: '#338A2F', + hc: '#348F34' + }, + description: 'ANSI green background color' + }, + { + id: 'ansi.yellow.background.color', defaults: { + dark: '#5F4C29', + light: '#BEB817', + hc: '#5F4C29' + }, + description: 'ANSI yellow background color' + }, + { + id: 'ansi.blue.background.color', defaults: { + dark: '#6286BB', + light: Color.rgba(0, 0, 139), + hc: '#6286BB' + }, + description: 'ANSI blue background color' + }, + { + id: 'ansi.magenta.background.color', defaults: { + dark: '#914191', + light: Color.rgba(139, 0, 139), + hc: '#914191' + }, + description: 'ANSI magenta background color' + }, + { + id: 'ansi.cyan.background.color', defaults: { + dark: '#218D8D', + light: Color.rgba(0, 139, 139), + hc: '#218D8D' + }, + description: 'ANSI cyan background color' + }, + { + id: 'ansi.white.background.color', defaults: { + dark: '#707070', + light: '#BDBDBD', + hc: '#707070' + }, + description: 'ANSI white background color' + } ); } } diff --git a/packages/core/src/browser/style/variables-bright.useable.css b/packages/core/src/browser/style/variables-bright.useable.css index 4717895a8ef90..cc209bd0df78e 100644 --- a/packages/core/src/browser/style/variables-bright.useable.css +++ b/packages/core/src/browser/style/variables-bright.useable.css @@ -231,33 +231,6 @@ is not optimized for dense, information rich UIs. --theia-ui-dialog-header-color: var(--theia-brand-color1); --theia-ui-dialog-header-font-color: var(--theia-inverse-ui-font-color0); - /* Variables */ - --theia-variable-name-color: #9B46B0; - --theia-variable-value-color: rgba(108, 108, 108, 0.8); - --theia-number-variable-color: #09885A; - --theia-boolean-variable-color: #0000FF; - --theia-string-variable-color: #A31515; - - /* ANSI color */ - --theia-ansi-black-color: gray; - --theia-ansi-red-color: #BE1717; - --theia-ansi-green-color: #338A2F; - --theia-ansi-yellow-color: #BEB817; - --theia-ansi-blue-color: darkblue; - --theia-ansi-magenta-color: darkmagenta; - --theia-ansi-cyan-color: darkcyan; - --theia-ansi-white-color: #BDBDBD; - - /* ANSI background color */ - --theia-ansi-black-background-color: gray; - --theia-ansi-red-background-color: #BE1717; - --theia-ansi-green-background-color: #338A2F; - --theia-ansi-yellow-background-color: #BEB817; - --theia-ansi-blue-background-color: darkblue; - --theia-ansi-magenta-background-color: darkmagenta; - --theia-ansi-cyan-background-color: darkcyan; - --theia-ansi-white-background-color: #BDBDBD; - /* Output */ --theia-output-font-color: var(--theia-ui-font-color1); diff --git a/packages/core/src/browser/style/variables-dark.useable.css b/packages/core/src/browser/style/variables-dark.useable.css index 67c3b79ee8efd..f94befa57637e 100644 --- a/packages/core/src/browser/style/variables-dark.useable.css +++ b/packages/core/src/browser/style/variables-dark.useable.css @@ -231,33 +231,6 @@ is not optimized for dense, information rich UIs. --theia-ui-dialog-header-color: var(--theia-brand-color0); --theia-ui-dialog-header-font-color: var(--theia-ui-font-color1); - /* Variables */ - --theia-variable-name-color: #C586C0; - --theia-variable-value-color: rgba(204, 204, 204, 0.6); - --theia-number-variable-color: #B5CEA8; - --theia-boolean-variable-color: #4E94CE; - --theia-string-variable-color: #CE9178; - - /* ANSI color */ - --theia-ansi-black-color: #A0A0A0; - --theia-ansi-red-color: #A74747; - --theia-ansi-green-color: #348F34; - --theia-ansi-yellow-color: #5F4C29; - --theia-ansi-blue-color: #6286BB; - --theia-ansi-magenta-color: #914191; - --theia-ansi-cyan-color: #218D8D; - --theia-ansi-white-color: #707070; - - /* ANSI background color */ - --theia-ansi-black-background-color: #A0A0A0; - --theia-ansi-red-background-color: #A74747; - --theia-ansi-green-background-color: #348F34; - --theia-ansi-yellow-background-color: #5F4C29; - --theia-ansi-blue-background-color: #6286BB; - --theia-ansi-magenta-background-color: #914191; - --theia-ansi-cyan-background-color: #218D8D; - --theia-ansi-white-background-color: #707070; - /* Output */ --theia-output-font-color: var(--theia-ui-font-color1); From 3bfcdaa3a214c0c311ec8adae1354173fd1c1374 Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Thu, 12 Dec 2019 15:41:28 +0000 Subject: [PATCH 34/65] [getting-started] remove usage of old css colors Signed-off-by: Anton Kosyakov --- packages/getting-started/src/browser/style/index.css | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/packages/getting-started/src/browser/style/index.css b/packages/getting-started/src/browser/style/index.css index 53d4a493b42a3..86eb253b4db0e 100644 --- a/packages/getting-started/src/browser/style/index.css +++ b/packages/getting-started/src/browser/style/index.css @@ -30,12 +30,11 @@ html, body { .gs-action-container { line-height: 20px; - color: var(--theia-foreground); } .gs-action-details { padding-left: 5px; - color: var(--theia-ui-font-color1); + color: var(--theia-descriptionForeground); } .gs-container { @@ -43,25 +42,23 @@ html, body { } .gs-header h1 { - color: var(--theia-foreground); flex: 1; font-weight: 600; } .gs-hr { - background-color: var(--theia-border-color1); + background-color: var(--theia-contrastBorder); height: 1px; border: 0; margin: 0px; } .gs-no-recent { - color: var(--theia-ui-font-color1); + color: var(--theia-descriptionForeground); } .gs-section a { border: none; - color: var(--theia-accent-color1); font-weight: 500; text-decoration: none; } @@ -71,7 +68,6 @@ html, body { } .gs-section-header { - color: var(--theia-foreground); font-size: var(--theia-ui-font-size2); font-weight: 600; margin-bottom: 5px; @@ -82,7 +78,7 @@ html, body { } .gs-sub-header { - color: var(--theia-ui-font-color2); + color: var(--theia-descriptionForeground); text-transform: capitalize; font-weight: 400; } From 492e1dc87c36392ac7b7910a434cabe7f7c6603f Mon Sep 17 00:00:00 2001 From: Jan Bicker Date: Thu, 12 Dec 2019 16:36:03 +0000 Subject: [PATCH 35/65] Applied input control colors and adapted respective styles Signed-off-by: Jan Bicker --- .../browser/common-frontend-contribution.ts | 119 ++++++++++-------- packages/core/src/browser/dialogs.ts | 1 + packages/core/src/browser/style/dialog.css | 13 +- packages/core/src/browser/style/index.css | 19 ++- packages/core/src/browser/tree/search-box.ts | 1 + .../src/browser/model/debug-breakpoint.tsx | 2 +- .../src/browser/file-dialog/file-dialog.ts | 2 +- .../src/browser/file-upload-service.ts | 2 + .../src/browser/keybindings-widget.tsx | 2 +- .../src/browser/mini-browser-content.ts | 1 + packages/scm/src/browser/scm-widget.tsx | 2 +- packages/scm/src/browser/style/index.css | 3 - .../browser/search-in-workspace-widget.tsx | 3 + .../src/browser/styles/index.css | 13 +- 14 files changed, 102 insertions(+), 81 deletions(-) diff --git a/packages/core/src/browser/common-frontend-contribution.ts b/packages/core/src/browser/common-frontend-contribution.ts index 37cc1f4a35eae..82b9d77d49f39 100644 --- a/packages/core/src/browser/common-frontend-contribution.ts +++ b/packages/core/src/browser/common-frontend-contribution.ts @@ -739,15 +739,15 @@ export class CommonFrontendContribution implements FrontendApplicationContributi this.quickOpenService.open({ onType: (_, accept) => accept(items) }, { - placeholder: 'Select File Icon Theme', - fuzzyMatchLabel: true, - selectIndex: () => items.findIndex(item => item.id === this.iconThemes.current), - onClose: () => { - if (resetTo) { - this.iconThemes.current = resetTo; - } + placeholder: 'Select File Icon Theme', + fuzzyMatchLabel: true, + selectIndex: () => items.findIndex(item => item.id === this.iconThemes.current), + onClose: () => { + if (resetTo) { + this.iconThemes.current = resetTo; } - }); + } + }); } registerColors(colors: ColorRegistry): void { @@ -756,6 +756,7 @@ export class CommonFrontendContribution implements FrontendApplicationContributi // if not yet contributed by Monaco, check runtime css variables to learn { id: 'selection.background', defaults: { dark: '#217daf', light: '#c0dbf1' }, description: 'Overall border color for focused elements. This color is only used if not overridden by a component.' }, { id: 'icon.foreground', defaults: { dark: '#C5C5C5', light: '#424242', hc: '#FFFFFF' }, description: 'The default color for icons in the workbench.' }, + { id: 'contrastBorder', defaults: { hc: '#6FC3DF' }, description: 'An extra border around elements to separate them from others for greater contrast.' }, // Window border colors should be aligned with https://code.visualstudio.com/api/references/theme-color#window-border { @@ -783,7 +784,15 @@ export class CommonFrontendContribution implements FrontendApplicationContributi { id: 'activityBar.foreground', defaults: { dark: '#FFFFFF', light: '#FFFFFF', hc: '#FFFFFF' }, description: 'Activity bar item foreground color when it is active. The activity bar is showing on the far left or right and allows to switch between views of the side bar.' }, { id: 'activityBar.inactiveForeground', defaults: { dark: '#FFFFFF', light: '#FFFFFF', hc: '#FFFFFF' }, description: 'Activity bar item foreground color when it is active. The activity bar is showing on the far left or right and allows to switch between views of the side bar.' }, - // Side Bar + // Input control colors should be aligned with https://code.visualstudio.com/api/references/theme-color#input-control + // if not yet contributed by Monaco, check runtime css variables to learn + { id: 'input.border', defaults: { hc: 'contrastBorder' }, description: 'Input box border.' }, + { id: 'inputValidation.errorForeground', defaults: { dark: 'errorForeground', light: 'errorForeground', hc: 'errorForeground' }, description: 'Input validation foreground color for error severity.' }, + { id: 'inputValidation.infoForeground', description: 'Input validation foreground color for information severity.' }, + { id: 'inputValidation.warningForeground', description: 'Input validation foreground color for warning severity.' }, + + // Side Bar should be aligned with https://code.visualstudio.com/api/references/theme-color#side-bar + // if not yet contributed by Monaco, check runtime css variables to learn { id: 'sideBar.background', defaults: { dark: '#252526', light: '#F3F3F3', hc: '#000000' }, description: 'Side bar background color. The side bar is the container for views like explorer and search.' }, { id: 'sideBar.foreground', description: 'Side bar foreground color. The side bar is the container for views like explorer and search.' }, { id: 'sideBarSectionHeader.background', defaults: { dark: '#80808033', light: '#80808033' }, description: 'Side bar section header background color. The side bar is the container for views like explorer and search.' }, @@ -930,20 +939,20 @@ export class CommonFrontendContribution implements FrontendApplicationContributi id: 'tab.hoverBackground', description: 'Tab background color when hovering. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' }, { - id: 'tab.unfocusedHoverBackground', defaults: { - dark: Color.transparent('tab.hoverBackground', 0.5), - light: Color.transparent('tab.hoverBackground', 0.7) - }, description: 'Tab background color in an unfocused group when hovering. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' - }, + id: 'tab.unfocusedHoverBackground', defaults: { + dark: Color.transparent('tab.hoverBackground', 0.5), + light: Color.transparent('tab.hoverBackground', 0.7) + }, description: 'Tab background color in an unfocused group when hovering. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' + }, { id: 'tab.hoverBorder', description: 'Border to highlight tabs when hovering. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' }, { - id: 'tab.unfocusedHoverBorder', defaults: { - dark: Color.transparent('tab.hoverBorder', 0.5), - light: Color.transparent('tab.hoverBorder', 0.7) - }, description: 'Border to highlight tabs in an unfocused group when hovering. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' - }, + id: 'tab.unfocusedHoverBorder', defaults: { + dark: Color.transparent('tab.hoverBorder', 0.5), + light: Color.transparent('tab.hoverBorder', 0.7) + }, description: 'Border to highlight tabs in an unfocused group when hovering. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' + }, { id: 'tab.activeModifiedBorder', defaults: { dark: '#3399CC', @@ -1100,21 +1109,21 @@ export class CommonFrontendContribution implements FrontendApplicationContributi light: Color.transparent('titleBar.activeForeground', 0.6) }, description: 'Title bar foreground when the window is inactive. Note that this color is currently only supported on macOS.' }, { - id: 'titleBar.activeBackground', defaults: { - dark: '#3C3C3C', - light: '#DDDDDD', - hc: '#000000' - }, description: 'Title bar background when the window is active. Note that this color is currently only supported on macOS.' - }, { - id: 'titleBar.inactiveBackground', defaults: { - dark: Color.transparent('titleBar.activeBackground', 0.6), - light: Color.transparent('titleBar.activeBackground', 0.6) - }, description: 'Title bar background when the window is inactive. Note that this color is currently only supported on macOS.' - }, { - id: 'titleBar.border', defaults: { - hc: 'contrastBorder' - }, description: 'Title bar border color. Note that this color is currently only supported on macOS.' - }, + id: 'titleBar.activeBackground', defaults: { + dark: '#3C3C3C', + light: '#DDDDDD', + hc: '#000000' + }, description: 'Title bar background when the window is active. Note that this color is currently only supported on macOS.' + }, { + id: 'titleBar.inactiveBackground', defaults: { + dark: Color.transparent('titleBar.activeBackground', 0.6), + light: Color.transparent('titleBar.activeBackground', 0.6) + }, description: 'Title bar background when the window is inactive. Note that this color is currently only supported on macOS.' + }, { + id: 'titleBar.border', defaults: { + hc: 'contrastBorder' + }, description: 'Title bar border color. Note that this color is currently only supported on macOS.' + }, // Menu Bar colors should be aligned with https://code.visualstudio.com/api/references/theme-color#menu-bar-colors { @@ -1124,33 +1133,33 @@ export class CommonFrontendContribution implements FrontendApplicationContributi hc: 'titleBar.activeForeground' }, description: 'Foreground color of the selected menu item in the menubar.' }, { - id: 'menubar.selectionBackground', defaults: { - dark: Color.transparent('#ffffff', 0.1), - light: Color.transparent('#000000', 0.1) - }, description: 'Background color of the selected menu item in the menubar.' - }, { - id: 'menubar.selectionBorder', defaults: { - hc: 'activeContrastBorder' - }, description: 'Border color of the selected menu item in the menubar.' - }, + id: 'menubar.selectionBackground', defaults: { + dark: Color.transparent('#ffffff', 0.1), + light: Color.transparent('#000000', 0.1) + }, description: 'Background color of the selected menu item in the menubar.' + }, { + id: 'menubar.selectionBorder', defaults: { + hc: 'activeContrastBorder' + }, description: 'Border color of the selected menu item in the menubar.' + }, { id: 'menu.border', defaults: { hc: 'contrastBorder' }, description: 'Border color of menus.' }, { - id: 'menu.foreground', defaults: { - dark: 'dropdown.foreground', light: 'foreground', hc: 'dropdown.foreground' - }, - description: 'Foreground color of menu items.' - }, { - id: 'menu.background', defaults: { - dark: 'dropdown.background', light: 'dropdown.background', hc: 'dropdown.background' - }, description: 'Background color of menu items.' - }, { - id: 'menu.selectionForeground', defaults: { - dark: 'list.activeSelectionForeground', light: 'list.activeSelectionForeground', hc: 'list.activeSelectionForeground' - }, description: 'Foreground color of the selected menu item in menus.' + id: 'menu.foreground', defaults: { + dark: 'dropdown.foreground', light: 'foreground', hc: 'dropdown.foreground' }, + description: 'Foreground color of menu items.' + }, { + id: 'menu.background', defaults: { + dark: 'dropdown.background', light: 'dropdown.background', hc: 'dropdown.background' + }, description: 'Background color of menu items.' + }, { + id: 'menu.selectionForeground', defaults: { + dark: 'list.activeSelectionForeground', light: 'list.activeSelectionForeground', hc: 'list.activeSelectionForeground' + }, description: 'Foreground color of the selected menu item in menus.' + }, { id: 'menu.selectionBackground', defaults: { dark: 'list.activeSelectionBackground', light: 'list.activeSelectionBackground', hc: 'list.activeSelectionBackground' }, diff --git a/packages/core/src/browser/dialogs.ts b/packages/core/src/browser/dialogs.ts index 4822837ca6091..1dd1d872519de 100644 --- a/packages/core/src/browser/dialogs.ts +++ b/packages/core/src/browser/dialogs.ts @@ -383,6 +383,7 @@ export class SingleTextInputDialog extends AbstractDialog { this.inputField = document.createElement('input'); this.inputField.type = 'text'; + this.inputField.className = 'theia-input'; this.inputField.setAttribute('style', 'flex: 0;'); this.inputField.value = props.initialValue || ''; if (props.initialSelectionRange) { diff --git a/packages/core/src/browser/style/dialog.css b/packages/core/src/browser/style/dialog.css index d4c55578fdb8c..9fe037c141abc 100644 --- a/packages/core/src/browser/style/dialog.css +++ b/packages/core/src/browser/style/dialog.css @@ -79,13 +79,10 @@ } input { - font-size: var(--theia-ui-font-size1); line-height: var(--theia-content-line-height); border-width: 1px; border-style: solid; border-color: var(--theia-border-color1); - background: var(--theia-layout-color2); - color: var(--theia-ui-font-color1); padding-left: 5px; } @@ -101,15 +98,15 @@ input { display: none; } .p-Widget.dialogOverlay .error { - color: var(--theia-editorError-foreground); + color: var(--theia-inputValidation-errorForeground); } .p-Widget.dialogOverlay .error.main { - color: var(--theia-editorError-foreground); - border-color: var(--theia-editorError-border); + color: var(--theia-inputValidation-errorForeground); + border-color: var(--theia-inputValidation-errorBorder); } .p-Widget.dialogOverlay .error > .theia-button.main { - background-color: var(--theia-editorError-foreground); - color: var(--theia-ui-font-color1); + background-color: var(--theia-inputValidation-errorBackground); + color: var(--theia-inputValidation-errorForeground); } .p-Widget.dialogOverlay .error > .dialogErrorMessage { margin-top: calc(var(--theia-ui-padding)*3); diff --git a/packages/core/src/browser/style/index.css b/packages/core/src/browser/style/index.css index 45b6435a89303..1543c6dc4657c 100644 --- a/packages/core/src/browser/style/index.css +++ b/packages/core/src/browser/style/index.css @@ -52,6 +52,17 @@ blockquote { border: var(--theia-border-width) solid var(--theia-textBlockQuote-border); } +.theia-input { + background: var(--theia-input-background); + color: var(--theia-input-foreground); + border: var(--theia-border-width) solid var(--theia-input-border); + font-family: var(--theia-ui-font-family); +} + +.theia-input::placeholder { + color: var(--theia-input-placeholderForeground); +} + .theia-maximized { position: fixed !important; top: 0 !important; @@ -114,6 +125,10 @@ blockquote { font-size: var(--theia-ui-font-size1); } +.p-Widget .error { + color: var(--theia-errorForeground); +} + .p-Widget.p-mod-hidden { display: none !important; } @@ -197,10 +212,6 @@ select option { background: var(--theia-dropdown-listBackground); } -textarea { - font-family: var(--theia-ui-font-family); -} - .theia-transparent-overlay { background-color: transparent; position: absolute; diff --git a/packages/core/src/browser/tree/search-box.ts b/packages/core/src/browser/tree/search-box.ts index 6d9051ed9afcd..339c78bcc7801 100644 --- a/packages/core/src/browser/tree/search-box.ts +++ b/packages/core/src/browser/tree/search-box.ts @@ -176,6 +176,7 @@ export class SearchBox extends BaseWidget { input.type = 'text'; input.onkeydown = ev => this.handle.bind(this)(ev); input.classList.add( + 'theia-input', SearchBox.Styles.SEARCH_INPUT ); this.node.appendChild(input); diff --git a/packages/debug/src/browser/model/debug-breakpoint.tsx b/packages/debug/src/browser/model/debug-breakpoint.tsx index b0071de275666..62c92d0220eb6 100644 --- a/packages/debug/src/browser/model/debug-breakpoint.tsx +++ b/packages/debug/src/browser/model/debug-breakpoint.tsx @@ -186,7 +186,7 @@ export class DebugBreakpoint extends DebugBreakpointData implements TreeElement const decoration = this.getDecoration(); return
- + {this.labelProvider.getName(this.uri)} {this.labelProvider.getLongName(this.uri.parent)} diff --git a/packages/filesystem/src/browser/file-dialog/file-dialog.ts b/packages/filesystem/src/browser/file-dialog/file-dialog.ts index 0688b71069700..139f6a0e18dbb 100644 --- a/packages/filesystem/src/browser/file-dialog/file-dialog.ts +++ b/packages/filesystem/src/browser/file-dialog/file-dialog.ts @@ -350,7 +350,7 @@ export class SaveFileDialog extends FileDialog { this.fileNameField = document.createElement('input'); this.fileNameField.type = 'text'; - this.fileNameField.classList.add(FILENAME_TEXTFIELD_CLASS); + this.fileNameField.classList.add('theia-input', FILENAME_TEXTFIELD_CLASS); this.fileNameField.value = this.props.inputValue || ''; fileNamePanel.appendChild(this.fileNameField); diff --git a/packages/filesystem/src/browser/file-upload-service.ts b/packages/filesystem/src/browser/file-upload-service.ts index e97a892a707a6..15b3efc498b84 100644 --- a/packages/filesystem/src/browser/file-upload-service.ts +++ b/packages/filesystem/src/browser/file-upload-service.ts @@ -61,9 +61,11 @@ export class FileUploadService { const targetInput = document.createElement('input'); targetInput.type = 'text'; targetInput.name = FileUploadService.TARGET; + targetInput.classList.add('theia-input'); const fileInput = document.createElement('input'); fileInput.type = 'file'; + fileInput.classList.add('theia-input'); fileInput.name = FileUploadService.UPLOAD; fileInput.multiple = true; diff --git a/packages/keymaps/src/browser/keybindings-widget.tsx b/packages/keymaps/src/browser/keybindings-widget.tsx index 6ffdbcf167d8d..986d4f947b2c9 100644 --- a/packages/keymaps/src/browser/keybindings-widget.tsx +++ b/packages/keymaps/src/browser/keybindings-widget.tsx @@ -305,7 +305,7 @@ export class KeybindingWidget extends ReactWidget {
0) ? '' : 'no-kb'} + className={`theia-input${(this.items.length > 0) ? '' : ' no-kb'}`} type='text' placeholder='Search keybindings' autoComplete='off' diff --git a/packages/mini-browser/src/browser/mini-browser-content.ts b/packages/mini-browser/src/browser/mini-browser-content.ts index 1fb4d5bd99291..f0bce73e65242 100644 --- a/packages/mini-browser/src/browser/mini-browser-content.ts +++ b/packages/mini-browser/src/browser/mini-browser-content.ts @@ -454,6 +454,7 @@ export class MiniBrowserContent extends BaseWidget { protected createInput(parent: HTMLElement): HTMLInputElement { const input = document.createElement('input'); input.type = 'text'; + input.classList.add('theia-input'); this.toDispose.pushAll([ addEventListener(input, 'keydown', this.handleInputChange.bind(this)), addEventListener(input, 'click', () => { diff --git a/packages/scm/src/browser/scm-widget.tsx b/packages/scm/src/browser/scm-widget.tsx index 8df8c3ac98682..d0c961a45ad59 100644 --- a/packages/scm/src/browser/scm-widget.tsx +++ b/packages/scm/src/browser/scm-widget.tsx @@ -204,7 +204,7 @@ export class ScmWidget extends ReactWidget implements StatefulWidget { const message = format(input.placeholder || '', keybinding); return
{'files to ' + kind}
Date: Thu, 12 Dec 2019 20:25:22 +0000 Subject: [PATCH 36/65] [git] remove usage of old css colors Signed-off-by: Anton Kosyakov --- .../style/variables-bright.useable.css | 5 - .../browser/style/variables-dark.useable.css | 5 - packages/git/src/browser/style/history.css | 74 +++------ packages/git/src/browser/style/index.css | 142 ++++-------------- packages/scm/src/browser/style/index.css | 43 ++++-- .../src/browser/styles/index.css | 12 -- 6 files changed, 78 insertions(+), 203 deletions(-) diff --git a/packages/core/src/browser/style/variables-bright.useable.css b/packages/core/src/browser/style/variables-bright.useable.css index cc209bd0df78e..2daf923f924b3 100644 --- a/packages/core/src/browser/style/variables-bright.useable.css +++ b/packages/core/src/browser/style/variables-bright.useable.css @@ -25,7 +25,6 @@ is not optimized for dense, information rich UIs. --theia-panel-border-width: 2px; --theia-border-color0: var(--md-grey-100); --theia-border-color1: var(--md-grey-200); - --theia-border-color2: var(--md-grey-300); --theia-border-color3: var(--md-grey-500); @@ -223,10 +222,6 @@ is not optimized for dense, information rich UIs. --theia-ui-button-color-secondary-disabled: var(--theia-disabled-color1); --theia-ui-button-font-color-secondary-disabled: var(--theia-ui-font-color2); - /* Expand/collapse element */ - --theia-ui-expand-button-color: var(--theia-accent-color4); - --theia-ui-expand-button-font-color: var(--theia-ui-font-color1); - /* Dialogs */ --theia-ui-dialog-header-color: var(--theia-brand-color1); --theia-ui-dialog-header-font-color: var(--theia-inverse-ui-font-color0); diff --git a/packages/core/src/browser/style/variables-dark.useable.css b/packages/core/src/browser/style/variables-dark.useable.css index f94befa57637e..666ef8e1a2b87 100644 --- a/packages/core/src/browser/style/variables-dark.useable.css +++ b/packages/core/src/browser/style/variables-dark.useable.css @@ -25,7 +25,6 @@ is not optimized for dense, information rich UIs. --theia-panel-border-width: 2px; --theia-border-color0: var(--md-grey-900); --theia-border-color1: var(--md-grey-800); - --theia-border-color2: var(--md-grey-600); --theia-border-color3: var(--md-grey-400); @@ -223,10 +222,6 @@ is not optimized for dense, information rich UIs. --theia-ui-button-color-secondary-disabled: var(--theia-disabled-color0); --theia-ui-button-font-color-secondary-disabled: var(--theia-ui-font-color2); - /* Expand/collapse element */ - --theia-ui-expand-button-color: black; - --theia-ui-expand-button-font-color: var(--theia-ui-font-color1); - /* Dialogs */ --theia-ui-dialog-header-color: var(--theia-brand-color0); --theia-ui-dialog-header-font-color: var(--theia-ui-font-color1); diff --git a/packages/git/src/browser/style/history.css b/packages/git/src/browser/style/history.css index 6f7368efa0831..86b532d8d28cc 100644 --- a/packages/git/src/browser/style/history.css +++ b/packages/git/src/browser/style/history.css @@ -18,7 +18,7 @@ margin: 3px 0; } -.theia-git .commitListElement.first .containerHead{ +.theia-git .commitListElement.first .containerHead { border: none; } @@ -27,13 +27,24 @@ height: 50px; display: flex; align-items: center; - border-top: 1px solid var(--theia-layout-color4); + border-top: 1px solid var(--theia-contrastBorder); } .theia-git .commitListElement .containerHead:hover { + background-color: var(--theia-list-hoverBackground); + color: var(--theia-list-hoverForeground); cursor: pointer; } +.theia-git:focus-within .commitListElement .containerHead.theia-mod-selected { + background: var(--theia-list-focusBackground); + color: var(--theia-list-focusForeground); +} + +.theia-git:not(:focus-within) .commitListElement .containerHead.theia-mod-selected { + background: var(--theia-list-inactiveFocusBackground); +} + .theia-git .commitListElement .containerHead .headContent { display: flex; width: 100%; @@ -73,16 +84,16 @@ visibility: visible; } -.theia-git .commitListElement .containerHead .headContent .expansionToggle > .toggle{ +.theia-git .commitListElement .containerHead .headContent .expansionToggle > .toggle { display: flex; - background: var(--theia-ui-expand-button-color); + background: var(--theia-list-focusBackground); padding: 5px; border-radius: 7px; margin-left: 5px; align-items: center; justify-content: flex-end; min-width: 30px; - color: var(--theia-ui-expand-button-font-color); + color: var(--theia-theia-list-focusForeground); } .theia-git .commitBody { @@ -94,7 +105,7 @@ } .theia-git .commitTime { - color: var(--theia-ui-font-color2); + color: var(--theia-descriptionForeground); font-size: smaller; } @@ -107,57 +118,6 @@ height: 100%; } -.theia-git .git-diff-container .history-lazy-loading { - position: absolute; - height: 50px; - width: 100%; - bottom: -80px; - opacity: 0; - font-weight: bold; - justify-content: center; - align-items: center; - display: flex; - background: var(--theia-layout-color4); - border: var(--theia-border-width) var(--theia-border-color2) solid; - box-sizing: border-box; -} - -.theia-git .git-diff-container .history-lazy-loading.show { - bottom: 0px; - opacity:0; - animation: showFrames ease-out 0.2s forwards; - -webkit-animation: showFrames ease-out 0.2s forwards; - } - - @keyframes showFrames{ - 0% { - opacity:0; - bottom:-80px ; - } - 100% { - opacity:1; - bottom:0px; - } - } - -.theia-git .git-diff-container .history-lazy-loading.hide { - bottom: 80px; - opacity:1; - animation: hideFrames ease-out 0.2s forwards; - -webkit-animation: hideFrames ease-out 0.2s forwards; - } - - @keyframes hideFrames{ - 0% { - opacity:1; - bottom: 0px ; - } - 100% { - opacity:0; - bottom: -80px ; - } - } - .theia-git .git-diff-container .subject { font-size: var(--theia-ui-font-size2); font-weight: bold; diff --git a/packages/git/src/browser/style/index.css b/packages/git/src/browser/style/index.css index b0726518c0eda..c93cb53652de0 100644 --- a/packages/git/src/browser/style/index.css +++ b/packages/git/src/browser/style/index.css @@ -50,19 +50,39 @@ padding-right: var(--theia-ui-padding); } -.theia-git .gitItem .file-icon { - display: initial; -} - .theia-git .gitItem:hover { - background-color: var(--theia-layout-color2); + background-color: var(--theia-list-hoverBackground); + color: var(--theia-list-hoverForeground); cursor: pointer; } +.theia-git:focus-within .gitItem:focus { + background: var(--theia-list-focusBackground); + color: var(--theia-list-focusForeground); +} + +.theia-git:not(:focus-within) .gitItem:not(:focus) { + background: var(--theia-list-inactiveFocusBackground); +} + +.theia-git:focus-within .gitItem.theia-mod-selected { + background: var(--theia-list-activeSelectionBackground); + color: var(--theia-list-activeSelectionForeground); +} + +.theia-git:not(:focus-within) .gitItem.theia-mod-selected { + background: var(--theia-list-inactiveSelectionBackground); + color: var(--theia-list-inactiveSelectionForeground); +} + +.theia-git .gitItem .file-icon { + display: initial; +} + .theia-git .gitItem .path { - color: var(--theia-ui-font-color2); font-size: var(--theia-ui-font-size0); margin-left: 3px; + opacity: .7; } .theia-git .gitItem .status { @@ -71,125 +91,29 @@ } .theia-git .gitItem .status.new { - color: var(--theia-success-color0); + color: var(--theia-gitDecoration-untrackedResourceForeground); } .theia-git .gitItem .status.new.staged { - color: var(--theia-success-color0); + color: var(--theia-gitDecoration-addedResourceForeground); } .theia-git .gitItem .status.modified { - color: var(--theia-brand-color0); + color: var(--theia-gitDecoration-modifiedResourceForeground); } .theia-git .gitItem .status.deleted { - color: var(--theia-editorWarning-foreground); + color: var(--theia-gitDecoration-deletedResourceForeground); } .theia-git .gitItem .status.renamed { - color: var(--theia-brand-color0); + color: var(--theia-gitDecoration-untrackedResourceForeground); } .theia-git .gitItem .status.conflicted { - color: var(--theia-error-color0); + color: var(--theia-gitDecoration-conflictingResourceForeground); } .theia-git .gitItem .status.copied { - color: var(--theia-brand-color0); -} - -.theia-git div:focus .theia-mod-selected{ - background: var(--theia-accent-color3); -} - -.theia-git .theia-mod-selected{ - background: var(--theia-accent-color4); -} - -.theia-git-main-container { - display: flex; - flex-direction: column; - height: 100%; -} - -.theia-git-commit-message-container textarea { - line-height: var(--theia-content-line-height); - font-size: var(--theia-ui-font-size1); - color: var(--theia-ui-font-color1); - background: var(--theia-layout-color2); - border-style: solid; - border-width: 1px; - resize: none; - box-sizing: border-box; - padding-left: 4px; -} - -.theia-git-commit-message { - width: 100%; -} - -.theia-git-commit-message-idle { - border-color: var(--theia-border-color0); -} - -.theia-git-commit-message-info { - border-color: var(--theia-info-color0); -} - -.theia-git-commit-message-success { - border-color: var(--theia-success-color0); -} - -.theia-git-commit-message-warning { - border-color: var(--theia-editorWarning-foreground); -} - -.theia-git-commit-message-error { - border-color: var(--theia-error-color0) !important; -} - -.theia-git-message, -.theia-git-commit-validation-message { - padding: 4px 4px 4px 4px; -} - -.theia-git-validation-message-idle { - background-color: var(--theia-border-color0) !important; -} - -.theia-git-validation-message-info { - background-color: var(--theia-info-color0) !important; - color: var(--theia-info-font-color0); -} - -.theia-git-validation-message-success { - background-color: var(--theia-success-color0) !important; - color: var(--theia-success-font-color0); -} - -.theia-git-message-warning, -.theia-git-validation-message-warning { - background-color: var(--theia-editorWarning-foreground) !important; - color: var(--theia-warn-font-color0); -} - -.theia-git-validation-message-error { - background-color: var(--theia-error-color0) !important; - color: var(--theia-error-font-color0); -} - -.git-tab-icon { - -webkit-mask: url('git.svg'); - mask: url('git.svg'); -} - -.git-theia-header { - padding: 5px; - display: flex; - justify-content: space-between; -} - -.git-theia-header:hover { - background-color: var(--theia-layout-color2); - cursor: pointer; + color: var(--theia-gitDecoration-modifiedResourceForeground); } diff --git a/packages/scm/src/browser/style/index.css b/packages/scm/src/browser/style/index.css index 7bfcc4221d455..c43f1307fcd03 100644 --- a/packages/scm/src/browser/style/index.css +++ b/packages/scm/src/browser/style/index.css @@ -67,14 +67,6 @@ background-color: var(--theia-error-color2) !important; } -.theia-scm div:focus .theia-mod-selected { - background: var(--theia-accent-color3); -} - -.theia-scm .theia-mod-selected{ - background: var(--theia-accent-color4); -} - .theia-scm-main-container { display: flex; flex-direction: column; @@ -186,19 +178,39 @@ padding: 0px calc(var(--theia-ui-padding)/2); } -.theia-scm .scmItem .file-icon { - display: initial; -} - .theia-scm .scmItem:hover { - background-color: var(--theia-layout-color2); + background-color: var(--theia-list-hoverBackground); + color: var(--theia-list-hoverForeground); cursor: pointer; } +.theia-scm:focus-within .scmItem:focus { + background: var(--theia-list-focusBackground); + color: var(--theia-list-focusForeground); +} + +.theia-scm:not(:focus-within) .scmItem:not(:focus) { + background: var(--theia-list-inactiveFocusBackground); +} + +.theia-scm:focus-within .scmItem.theia-mod-selected { + background: var(--theia-list-activeSelectionBackground); + color: var(--theia-list-activeSelectionForeground); +} + +.theia-scm:not(:focus-within) .scmItem.theia-mod-selected { + background: var(--theia-list-inactiveSelectionBackground); + color: var(--theia-list-inactiveSelectionForeground); +} + +.theia-scm .scmItem .file-icon { + display: initial; +} + .theia-scm .scmItem .path { - color: var(--theia-ui-font-color2); font-size: var(--theia-ui-font-size0); margin-left: var(--theia-ui-padding); + opacity: .7; } .theia-scm .scmItem .status { @@ -218,7 +230,8 @@ } .scm-theia-header:hover { - background-color: var(--theia-layout-color2); + background-color: var(--theia-list-hoverBackground); + color: var(--theia-list-hoverForeground); cursor: pointer; } diff --git a/packages/search-in-workspace/src/browser/styles/index.css b/packages/search-in-workspace/src/browser/styles/index.css index ffacd5be1a78b..efaf7adc6f381 100644 --- a/packages/search-in-workspace/src/browser/styles/index.css +++ b/packages/search-in-workspace/src/browser/styles/index.css @@ -219,18 +219,6 @@ display:flex; } -.t-siw-search-container .result .result-head .result-no { - background: var(--theia-ui-expand-button-color); - padding: 3px 8px; - border-radius: 7px; - font-size: var(--theia-ui-font-size0); -} - -.t-siw-search-container .result .result-head .expand-icon { - margin: 0 3px; - width: 7px; -} - .t-siw-search-container .result .result-head .fa, .t-siw-search-container .result .result-head .theia-file-icons-js { margin: 0 3px; From a25c8c3277321db8d3491b94882352751a7a03b1 Mon Sep 17 00:00:00 2001 From: Jan Bicker Date: Fri, 13 Dec 2019 05:54:19 +0000 Subject: [PATCH 37/65] Applied color variables to scrollbars Signed-off-by: Jan Bicker --- .../core/src/browser/style/scrollbars.css | 53 ++++++++++++------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/packages/core/src/browser/style/scrollbars.css b/packages/core/src/browser/style/scrollbars.css index dcf6d10e5ec5e..8f960a58023ae 100644 --- a/packages/core/src/browser/style/scrollbars.css +++ b/packages/core/src/browser/style/scrollbars.css @@ -23,7 +23,7 @@ } ::-webkit-scrollbar-thumb { - background: var(--theia-scrollbar-thumb-color); + background: var(--theia-scrollbarSlider-background); } ::-webkit-scrollbar:hover { @@ -31,7 +31,11 @@ } ::-webkit-scrollbar-thumb:hover { - background: var(--theia-scrollbar-active-thumb-color); + background: var(--theia-scrollbarSlider-hoverBackground); +} + +::-webkit-scrollbar-thumb:active { + background: var(--theia-scrollbarSlider-activeBackground); } ::-webkit-scrollbar-corner { @@ -53,7 +57,7 @@ #theia-dialog-shell .ps__rail-x > .ps__thumb-x { height: var(--theia-scrollbar-width); bottom: calc((var(--theia-scrollbar-rail-width) - var(--theia-scrollbar-width)) / 2); - background: var(--theia-scrollbar-thumb-color); + background: var(--theia-scrollbarSlider-background); border-radius: 0px; } @@ -83,7 +87,7 @@ #theia-dialog-shell .ps__rail-y > .ps__thumb-y { width: var(--theia-scrollbar-width); right: calc((var(--theia-scrollbar-rail-width) - var(--theia-scrollbar-width)) / 2); - background: var(--theia-scrollbar-thumb-color); + background: var(--theia-scrollbarSlider-background); border-radius: 0px; } @@ -113,12 +117,23 @@ background-color: var(--theia-scrollbar-active-rail-color); } -#theia-app-shell .ps [class^='ps__rail']:hover > [class^='ps__thumb'], -#theia-app-shell .ps [class^='ps__rail']:focus > [class^='ps__thumb'], -#theia-dialog-shell .ps [class^='ps__rail']:hover > [class^='ps__thumb'], -#theia-dialog-shell .ps [class^='ps__rail']:focus > [class^='ps__thumb'] - { - background: var(--theia-scrollbar-active-thumb-color); +#theia-app-shell .ps [class^='ps__rail'].ps--clicking > [class^='ps__thumb'], +#theia-dialog-shell .ps [class^='ps__rail'].ps--clicking > [class^='ps__thumb']{ + background-color: var(--theia-scrollbarSlider-activeBackground); +} + +#theia-app-shell .ps [class^='ps__rail'] > [class^='ps__thumb']:hover, +#theia-app-shell .ps [class^='ps__rail'] > [class^='ps__thumb']:focus, +#theia-dialog-shell .ps [class^='ps__rail'] > [class^='ps__thumb']:hover, +#theia-dialog-shell .ps [class^='ps__rail'] > [class^='ps__thumb']:focus +{ + background: var(--theia-scrollbarSlider-hoverBackground); +} + +#theia-app-shell .ps [class^='ps__rail'] > [class^='ps__thumb']:active, +#theia-dialog-shell .ps [class^='ps__rail'] > [class^='ps__thumb']:active +{ + background: var(--theia-scrollbarSlider-activeBackground); } #theia-app-shell .ps:hover > [class^='ps__rail'], @@ -128,6 +143,7 @@ #theia-dialog-shell .ps--focus > [class^='ps__rail'], #theia-dialog-shell .ps--scrolling-y > [class^='ps__rail'] { opacity: 1; + background: transparent; } @@ -144,7 +160,7 @@ .vs .monaco-scrollable-element > .scrollbar > .slider, .vs-dark .monaco-scrollable-element > .scrollbar > .slider { - background: var(--theia-scrollbar-thumb-color) !important; + background: var(--theia-scrollbarSlider-background) !important; } .vs .monaco-scrollable-element > .scrollbar:hover, @@ -152,13 +168,10 @@ background: var(--theia-scrollbar-active-rail-color); } -.vs .monaco-scrollable-element > .scrollbar:hover > .slider, -.vs-dark .monaco-scrollable-element > .scrollbar:hover > .slider { - background: var(--theia-scrollbar-active-thumb-color) !important; -} - -.monaco-scrollable-element > .visible.scrollbar.vertical:hover > .slider { - background: var(--theia-scrollbar-thumb-color) !important; +.monaco-scrollable-element > .visible.scrollbar.vertical > .slider:hover, +.vs .monaco-scrollable-element > .scrollbar > .slider:hover, +.vs-dark .monaco-scrollable-element > .scrollbar > .slider:hover { + background: var(--theia-scrollbarSlider-hoverBackground) !important; } .monaco-scrollable-element > .scrollbar.vertical > .slider { @@ -166,7 +179,7 @@ } .monaco-scrollable-element > .scrollbar.vertical > .slider.active { - background: var(--theia-scrollbar-active-thumb-color) !important; + background: var(--theia-scrollbarSlider-hoverBackground) !important; } .monaco-scrollable-element > .scrollbar.horizontal > .slider { @@ -174,5 +187,5 @@ } .monaco-scrollable-element > .shadow.top { - box-shadow: var(--theia-widget-shadow) 0px 6px 6px -6px inset !important; + box-shadow: var(--theia-scrollbar-shadow) 0px 6px 6px -6px inset !important; } From feecb3ad94fe560461235401a13980bb9490a9d9 Mon Sep 17 00:00:00 2001 From: Jan Bicker Date: Fri, 13 Dec 2019 09:00:48 +0000 Subject: [PATCH 38/65] Additional changes regarding Input control colors Signed-off-by: Jan Bicker --- packages/core/src/browser/style/dialog.css | 8 -------- packages/core/src/browser/style/index.css | 3 +++ packages/core/src/browser/style/sidepanel.css | 2 +- packages/mini-browser/src/browser/style/index.css | 10 +++++----- packages/scm/src/browser/style/index.css | 8 ++++---- .../search-in-workspace/src/browser/styles/index.css | 3 +-- 6 files changed, 14 insertions(+), 20 deletions(-) diff --git a/packages/core/src/browser/style/dialog.css b/packages/core/src/browser/style/dialog.css index 9fe037c141abc..36fbf04efb972 100644 --- a/packages/core/src/browser/style/dialog.css +++ b/packages/core/src/browser/style/dialog.css @@ -78,14 +78,6 @@ min-height: 21px; } -input { - line-height: var(--theia-content-line-height); - border-width: 1px; - border-style: solid; - border-color: var(--theia-border-color1); - padding-left: 5px; -} - .dialogOverlay :focus { box-shadow: 0px 0px 1px 1px var(--theia-accent-color3); outline: none; diff --git a/packages/core/src/browser/style/index.css b/packages/core/src/browser/style/index.css index 1543c6dc4657c..b0a57399fcd83 100644 --- a/packages/core/src/browser/style/index.css +++ b/packages/core/src/browser/style/index.css @@ -57,6 +57,9 @@ blockquote { color: var(--theia-input-foreground); border: var(--theia-border-width) solid var(--theia-input-border); font-family: var(--theia-ui-font-family); + font-size: var(--theia-ui-font-size1); + line-height: var(--theia-content-line-height); + padding-left: 5px; } .theia-input::placeholder { diff --git a/packages/core/src/browser/style/sidepanel.css b/packages/core/src/browser/style/sidepanel.css index e4d242a98e34b..07a6421959e86 100644 --- a/packages/core/src/browser/style/sidepanel.css +++ b/packages/core/src/browser/style/sidepanel.css @@ -194,7 +194,7 @@ background: var(--theia-panel-background); } -#theia-bottom-content-panel input { +#theia-bottom-content-panel .theia-input { border-color: var(--theia-panelInput-border); } diff --git a/packages/mini-browser/src/browser/style/index.css b/packages/mini-browser/src/browser/style/index.css index 2806054e217ea..00a8b38d48fe0 100644 --- a/packages/mini-browser/src/browser/style/index.css +++ b/packages/mini-browser/src/browser/style/index.css @@ -45,30 +45,30 @@ padding: 0 10px; } -.theia-mini-browser-toolbar input { +.theia-mini-browser-toolbar .theia-input { width: 100%; line-height: var(--theia-private-mini-browser-height); margin-left: 4px; margin-right: 4px; } -.theia-mini-browser-toolbar-read-only input { +.theia-mini-browser-toolbar-read-only .theia-input { width: 100%; line-height: var(--theia-private-mini-browser-height); margin-left: 4px; margin-right: 4px; cursor: pointer; - background: var(--theia-layout-color0); + background: var(--theia-input-background); border: none; text-decoration: underline; outline: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; - color: var(--theia-ui-button-color); + color: var(--theia-input-foreground); } -.theia-mini-browser-toolbar-read-only input:hover { +.theia-mini-browser-toolbar-read-only .theia-input:hover { color: var(--theia-ui-button-color-hover); } diff --git a/packages/scm/src/browser/style/index.css b/packages/scm/src/browser/style/index.css index c43f1307fcd03..097890c49730b 100644 --- a/packages/scm/src/browser/style/index.css +++ b/packages/scm/src/browser/style/index.css @@ -105,11 +105,11 @@ } .theia-scm-input-message-idle:not(:focus) { - border-color: var(--theia-border-color0); + border-color: var(--theia-input-border); } .theia-scm-input-message-info { - border-color: var(--theia-info-color0); + border-color: var(--theia-inputValidation-infoBorder); } .theia-scm-input-message-success { @@ -117,11 +117,11 @@ } .theia-scm-input-message-warning { - border-color: var(--theia-editorWarning-foreground); + border-color: var(--theia-inputValidation-warningBorder); } .theia-scm-input-message-error { - border-color: var(--theia-error-color0) !important; + border-color: var(--theia-inputValidation-errorBorder) !important; } .theia-scm-message, diff --git a/packages/search-in-workspace/src/browser/styles/index.css b/packages/search-in-workspace/src/browser/styles/index.css index efaf7adc6f381..26439a3f79438 100644 --- a/packages/search-in-workspace/src/browser/styles/index.css +++ b/packages/search-in-workspace/src/browser/styles/index.css @@ -33,10 +33,9 @@ min-width: 6px; } -.t-siw-search-container input[type="text"] { +.t-siw-search-container .theia-input { flex: 1; line-height: var(--theia-content-line-height); - font-size: var(--theia-ui-font-size1); padding-left: 8px; color: var(--theia-ui-font-color1); padding: 3px 0 3px 4px; From 5cf0ef2b38c0b221360486b9c8dfd5ca82754d29 Mon Sep 17 00:00:00 2001 From: Jan Bicker Date: Fri, 13 Dec 2019 09:33:41 +0000 Subject: [PATCH 39/65] Fixed Activity Bar: borders are now applied to full height Signed-off-by: Jan Bicker --- packages/core/src/browser/style/sidepanel.css | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/core/src/browser/style/sidepanel.css b/packages/core/src/browser/style/sidepanel.css index 07a6421959e86..73da55df2ef6b 100644 --- a/packages/core/src/browser/style/sidepanel.css +++ b/packages/core/src/browser/style/sidepanel.css @@ -56,13 +56,19 @@ } .p-TabBar.theia-app-left .p-TabBar-tab { - border-right: var(--theia-panel-border-width) solid var(--theia-activityBar-border); - margin-right: var(--theia-panel-border-width); + margin-right: var(--theia-panel-border-width); +} + +.p-TabBar.theia-app-left.theia-app-sides { + border-right: var(--theia-panel-border-width) solid var(--theia-activityBar-border); } .p-TabBar.theia-app-right .p-TabBar-tab { - border-left: var(--theia-panel-border-width) solid var(--theia-activityBar-border); - margin-left: var(--theia-panel-border-width); + margin-left: var(--theia-panel-border-width); +} + +.p-Widget.p-TabBar.theia-app-right.theia-app-sides { + border-left: var(--theia-panel-border-width) solid var(--theia-activityBar-border); } .p-TabBar.theia-app-sides .p-TabBar-tab.p-mod-current { From eadc8b2aee99f21d84c0df85bbbae56d8b2044d0 Mon Sep 17 00:00:00 2001 From: Jan Bicker Date: Fri, 13 Dec 2019 09:57:47 +0000 Subject: [PATCH 40/65] Introduced border to left and right side content panels. Signed-off-by: Jan Bicker --- packages/core/src/browser/style/sidepanel.css | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/core/src/browser/style/sidepanel.css b/packages/core/src/browser/style/sidepanel.css index 73da55df2ef6b..eaa7486fb7214 100644 --- a/packages/core/src/browser/style/sidepanel.css +++ b/packages/core/src/browser/style/sidepanel.css @@ -155,6 +155,14 @@ max-width: var(--theia-private-sidebar-tab-width); } +#theia-left-content-panel > .p-Panel { + border-right: var(--theia-panel-border-width) solid var(--theia-activityBar-border); +} + +#theia-right-content-panel > .p-Panel { + border-left: var(--theia-panel-border-width) solid var(--theia-activityBar-border); +} + .theia-side-panel { background-color: var(--theia-sideBar-background); } From ed9109947642379c914d7d0341b439879fb8f85c Mon Sep 17 00:00:00 2001 From: Jan Bicker Date: Fri, 13 Dec 2019 10:40:04 +0000 Subject: [PATCH 41/65] Got rid of '--theia-ui-button-*'-Variables introduced defaults for secondary and disabled buttons replaced occurrences of old variables in css with the new variables Signed-off-by: Jan Bicker --- .../browser/common-frontend-contribution.ts | 55 +++++++++++++++++++ packages/core/src/browser/style/index.css | 14 ++--- .../style/variables-bright.useable.css | 12 ---- .../browser/style/variables-dark.useable.css | 12 ---- .../mini-browser/src/browser/style/index.css | 2 +- .../dialogs/style/modal-notification.css | 6 +- 6 files changed, 66 insertions(+), 35 deletions(-) diff --git a/packages/core/src/browser/common-frontend-contribution.ts b/packages/core/src/browser/common-frontend-contribution.ts index 82b9d77d49f39..4e3a26b2cfce0 100644 --- a/packages/core/src/browser/common-frontend-contribution.ts +++ b/packages/core/src/browser/common-frontend-contribution.ts @@ -1355,6 +1355,61 @@ export class CommonFrontendContribution implements FrontendApplicationContributi hc: '#707070' }, description: 'ANSI white background color' + }, + + // Theia defaults + // Buttons + { + id: 'button.secondary.foreground', + defaults: { + dark: Color.white, + light: Color.white, + hc: Color.white + }, description: 'Foreground color of secondary buttons.' + }, + { + id: 'button.secondary.disabled.foreground', + defaults: { + dark: Color.white, + light: Color.white, + hc: Color.white + }, description: 'Foreground color of secondary buttons.' + }, + { + id: 'button.secondary.background', + defaults: { + dark: Color.lighten('button.background', 0.5), + light: Color.lighten('button.background', 0.5) + }, description: 'Background color of secondary buttons.' + }, + { + id: 'button.secondary.hoverBackground', + defaults: { + dark: Color.lighten('button.secondary.background', 0.2), + light: Color.lighten('button.secondary.background', 0.2) + }, description: 'Background color when hovering secondary buttons.' + }, + { + id: 'button.secondary.disabled.background', + defaults: { + dark: Color.transparent('button.secondary.background', 0.6), + light: Color.transparent('button.secondary.background', 0.6) + }, description: 'Background color when hovering secondary buttons.' + }, + { + id: 'button.disabled.foreground', + defaults: { + dark: Color.transparent('button.foreground', 0.5), + light: Color.transparent('button.foreground', 0.5), + hc: Color.transparent('button.foreground', 0.5) + }, description: 'Foreground color of secondary buttons.' + }, + { + id: 'button.disabled.background', + defaults: { + dark: Color.transparent('button.background', 0.5), + light: Color.transparent('button.background', 0.5) + }, description: 'Background color of secondary buttons.' } ); } diff --git a/packages/core/src/browser/style/index.css b/packages/core/src/browser/style/index.css index b0a57399fcd83..4adcc01d72c30 100644 --- a/packages/core/src/browser/style/index.css +++ b/packages/core/src/browser/style/index.css @@ -182,24 +182,24 @@ button.theia-button:hover, .theia-button:hover, .theia-button:focus { } button.secondary, .theia-button.secondary { - color: var(--theia-ui-button-font-color-secondary); - background-color: var(--theia-ui-button-color-secondary); + color: var(--theia-button-secondary-foreground); + background-color: var(--theia-button-secondary-background); } button.secondary:hover, .theia-button.secondary:hover { - background-color: var(--theia-ui-button-color-secondary-hover); + background-color: var(--theia-button-secondary-hoverBackground); } button.theia-button[disabled], .theia-button[disabled] { opacity: 0.6; - color: var(--theia-ui-button-font-color-disabled); - background-color: var(--theia-ui-button-color-disabled); + color: var(--theia-button-disabled-foreground); + background-color: var(--theia-button-disabled-background); cursor: default; } button.secondary[disabled], .theia-button.secondary[disabled] { - color: var(--theia-ui-button-font-color-secondary-disabled); - background-color: var(--theia-ui-button-color-secondary-disabled); + color: var(--theia-button-secondary-disabled-foreground); + background-color: var(--theia-button-secondary-disabled-background); } select { diff --git a/packages/core/src/browser/style/variables-bright.useable.css b/packages/core/src/browser/style/variables-bright.useable.css index 2daf923f924b3..93790cd975386 100644 --- a/packages/core/src/browser/style/variables-bright.useable.css +++ b/packages/core/src/browser/style/variables-bright.useable.css @@ -210,18 +210,6 @@ is not optimized for dense, information rich UIs. --theia-statusBar-font-color: var(--theia-inverse-ui-font-color0); --theia-statusBar-font-size: 12px; - /* Buttons */ - --theia-ui-button-color: var(--theia-brand-color1); - --theia-ui-button-color-hover: var(--theia-brand-color0); - --theia-ui-button-font-color: var(--theia-inverse-ui-font-color0); - --theia-ui-button-color-secondary: var(--theia-secondary-brand-color1); - --theia-ui-button-color-secondary-hover: var(--theia-secondary-brand-color0); - --theia-ui-button-font-color-secondary: var(--theia-inverse-ui-font-color0); - --theia-ui-button-color-disabled: var(--theia-accent-color3); - --theia-ui-button-font-color-disabled: var(--theia-ui-font-color2); - --theia-ui-button-color-secondary-disabled: var(--theia-disabled-color1); - --theia-ui-button-font-color-secondary-disabled: var(--theia-ui-font-color2); - /* Dialogs */ --theia-ui-dialog-header-color: var(--theia-brand-color1); --theia-ui-dialog-header-font-color: var(--theia-inverse-ui-font-color0); diff --git a/packages/core/src/browser/style/variables-dark.useable.css b/packages/core/src/browser/style/variables-dark.useable.css index 666ef8e1a2b87..6c487be214b67 100644 --- a/packages/core/src/browser/style/variables-dark.useable.css +++ b/packages/core/src/browser/style/variables-dark.useable.css @@ -210,18 +210,6 @@ is not optimized for dense, information rich UIs. --theia-statusBar-font-color: var(--theia-ui-font-color0); --theia-statusBar-font-size: 12px; - /* Buttons */ - --theia-ui-button-color: var(--theia-brand-color0); - --theia-ui-button-color-hover: var(--theia-brand-color1); - --theia-ui-button-font-color: var(--theia-ui-font-color1); - --theia-ui-button-color-secondary: var(--theia-secondary-brand-color0); - --theia-ui-button-color-secondary-hover: var(--theia-secondary-brand-color1); - --theia-ui-button-font-color-secondary: var(--theia-ui-font-color1); - --theia-ui-button-color-disabled: var(--theia-accent-color3); - --theia-ui-button-font-color-disabled: var(--theia-ui-font-color2); - --theia-ui-button-color-secondary-disabled: var(--theia-disabled-color0); - --theia-ui-button-font-color-secondary-disabled: var(--theia-ui-font-color2); - /* Dialogs */ --theia-ui-dialog-header-color: var(--theia-brand-color0); --theia-ui-dialog-header-font-color: var(--theia-ui-font-color1); diff --git a/packages/mini-browser/src/browser/style/index.css b/packages/mini-browser/src/browser/style/index.css index 00a8b38d48fe0..567aeab90e5aa 100644 --- a/packages/mini-browser/src/browser/style/index.css +++ b/packages/mini-browser/src/browser/style/index.css @@ -69,7 +69,7 @@ } .theia-mini-browser-toolbar-read-only .theia-input:hover { - color: var(--theia-ui-button-color-hover); + color: var(--theia-button-hoverBackground); } .theia-mini-browser-button { diff --git a/packages/plugin-ext/src/main/browser/dialogs/style/modal-notification.css b/packages/plugin-ext/src/main/browser/dialogs/style/modal-notification.css index b168e1b5c53f4..e5d7a9df7dc0d 100644 --- a/packages/plugin-ext/src/main/browser/dialogs/style/modal-notification.css +++ b/packages/plugin-ext/src/main/browser/dialogs/style/modal-notification.css @@ -89,8 +89,8 @@ } .modal-Notification .buttons > button { - background-color: var(--theia-ui-button-color); - color: var(--theia-ui-button-font-color); + background-color: var(--theia-button-background); + color: var(--theia-button-foreground); border: none; border-radius: 0; text-align: center; @@ -104,5 +104,5 @@ } .modal-Notification .buttons > button:hover { - background-color: var(--theia-accent-color1); + background-color: var(--theia-button-hoverBackground); } From 8ac04cb837fa805bcf22c2cd98cef64ccb051454 Mon Sep 17 00:00:00 2001 From: Jan Bicker Date: Fri, 13 Dec 2019 13:58:36 +0000 Subject: [PATCH 42/65] Removed old color keys for output, dialogs, statusbar, menu, scrollbar and adapted respective css Signed-off-by: Jan Bicker --- .../browser/common-frontend-contribution.ts | 35 +++++++++---------- packages/core/src/browser/style/index.css | 20 +++++------ .../core/src/browser/style/scrollbars.css | 26 ++------------ packages/core/src/browser/style/sidepanel.css | 2 +- .../style/variables-bright.useable.css | 21 +---------- .../browser/style/variables-dark.useable.css | 19 ---------- .../src/browser/style/notifications.css | 3 +- packages/output/src/browser/style/output.css | 1 - 8 files changed, 32 insertions(+), 95 deletions(-) diff --git a/packages/core/src/browser/common-frontend-contribution.ts b/packages/core/src/browser/common-frontend-contribution.ts index 4e3a26b2cfce0..62abd8e1aeb53 100644 --- a/packages/core/src/browser/common-frontend-contribution.ts +++ b/packages/core/src/browser/common-frontend-contribution.ts @@ -756,7 +756,6 @@ export class CommonFrontendContribution implements FrontendApplicationContributi // if not yet contributed by Monaco, check runtime css variables to learn { id: 'selection.background', defaults: { dark: '#217daf', light: '#c0dbf1' }, description: 'Overall border color for focused elements. This color is only used if not overridden by a component.' }, { id: 'icon.foreground', defaults: { dark: '#C5C5C5', light: '#424242', hc: '#FFFFFF' }, description: 'The default color for icons in the workbench.' }, - { id: 'contrastBorder', defaults: { hc: '#6FC3DF' }, description: 'An extra border around elements to separate them from others for greater contrast.' }, // Window border colors should be aligned with https://code.visualstudio.com/api/references/theme-color#window-border { @@ -1360,44 +1359,44 @@ export class CommonFrontendContribution implements FrontendApplicationContributi // Theia defaults // Buttons { - id: 'button.secondary.foreground', + id: 'secondaryButton.foreground', defaults: { - dark: Color.white, - light: Color.white, - hc: Color.white + dark: 'button.foreground', + light: 'button.foreground', + hc: 'button.foreground' }, description: 'Foreground color of secondary buttons.' }, { - id: 'button.secondary.disabled.foreground', + id: 'secondaryButton.disabledForeground', defaults: { - dark: Color.white, - light: Color.white, - hc: Color.white + dark: Color.transparent('secondaryButton.foreground', 0.5), + light: Color.transparent('secondaryButton.foreground', 0.5), + hc: Color.transparent('secondaryButton.foreground', 0.5), }, description: 'Foreground color of secondary buttons.' }, { - id: 'button.secondary.background', + id: 'secondaryButton.background', defaults: { dark: Color.lighten('button.background', 0.5), light: Color.lighten('button.background', 0.5) }, description: 'Background color of secondary buttons.' }, { - id: 'button.secondary.hoverBackground', + id: 'secondaryButton.hoverBackground', defaults: { - dark: Color.lighten('button.secondary.background', 0.2), - light: Color.lighten('button.secondary.background', 0.2) + dark: Color.lighten('secondaryButton.background', 0.2), + light: Color.lighten('secondaryButton.background', 0.2) }, description: 'Background color when hovering secondary buttons.' }, { - id: 'button.secondary.disabled.background', + id: 'secondaryButton.disabledBackground', defaults: { - dark: Color.transparent('button.secondary.background', 0.6), - light: Color.transparent('button.secondary.background', 0.6) + dark: Color.transparent('secondaryButton.background', 0.6), + light: Color.transparent('secondaryButton.background', 0.6) }, description: 'Background color when hovering secondary buttons.' }, { - id: 'button.disabled.foreground', + id: 'button.disabledForeground', defaults: { dark: Color.transparent('button.foreground', 0.5), light: Color.transparent('button.foreground', 0.5), @@ -1405,7 +1404,7 @@ export class CommonFrontendContribution implements FrontendApplicationContributi }, description: 'Foreground color of secondary buttons.' }, { - id: 'button.disabled.background', + id: 'button.disabledBackground', defaults: { dark: Color.transparent('button.background', 0.5), light: Color.transparent('button.background', 0.5) diff --git a/packages/core/src/browser/style/index.css b/packages/core/src/browser/style/index.css index 4adcc01d72c30..819726708c2ac 100644 --- a/packages/core/src/browser/style/index.css +++ b/packages/core/src/browser/style/index.css @@ -26,7 +26,7 @@ body { padding: 0; overflow: hidden; font-family: var(--theia-ui-font-family); - background: var(--theia-layout-color0); + background: var(--theia-editor-background); color: var(--theia-foreground); border: 1px solid var(--theia-window-activeBorder); } @@ -75,7 +75,7 @@ blockquote { width: auto !important; height: auto !important; z-index: 255 !important; - background: var(--theia-layout-color0); + background: var(--theia-editor-background); } .theia-ApplicationShell { @@ -84,7 +84,7 @@ blockquote { left: 0; right: 0; bottom: 0; - background: var(--theia-layout-color0); + background: var(--theia-editor-background); } .theia-preload { @@ -182,24 +182,24 @@ button.theia-button:hover, .theia-button:hover, .theia-button:focus { } button.secondary, .theia-button.secondary { - color: var(--theia-button-secondary-foreground); - background-color: var(--theia-button-secondary-background); + color: var(--theia-secondaryButton-foreground); + background-color: var(--theia-secondaryButton-background); } button.secondary:hover, .theia-button.secondary:hover { - background-color: var(--theia-button-secondary-hoverBackground); + background-color: var(--theia-secondaryButton-hoverBackground); } button.theia-button[disabled], .theia-button[disabled] { opacity: 0.6; - color: var(--theia-button-disabled-foreground); - background-color: var(--theia-button-disabled-background); + color: var(--theia-button-disabledForeground); + background-color: var(--theia-button-disabledBackground); cursor: default; } button.secondary[disabled], .theia-button.secondary[disabled] { - color: var(--theia-button-secondary-disabled-foreground); - background-color: var(--theia-button-secondary-disabled-background); + color: var(--theia-secondaryButton-disabledForeground); + background-color: var(--theia-secondaryButton-disabledBackground); } select { diff --git a/packages/core/src/browser/style/scrollbars.css b/packages/core/src/browser/style/scrollbars.css index 8f960a58023ae..49b2fb5ccf232 100644 --- a/packages/core/src/browser/style/scrollbars.css +++ b/packages/core/src/browser/style/scrollbars.css @@ -19,7 +19,7 @@ ::-webkit-scrollbar { height: var(--theia-scrollbar-width); width: var(--theia-scrollbar-width); - background: var(--theia-scrollbar-rail-color); + background: transparent; } ::-webkit-scrollbar-thumb { @@ -27,7 +27,7 @@ } ::-webkit-scrollbar:hover { - background: var(--theia-scrollbar-active-rail-color); + background: transparent; } ::-webkit-scrollbar-thumb:hover { @@ -50,7 +50,6 @@ #theia-app-shell .ps__rail-x, #theia-dialog-shell .ps__rail-x { height: var(--theia-scrollbar-rail-width); - background: var(--theia-scrollbar-rail-color); } #theia-app-shell .ps__rail-x > .ps__thumb-x, @@ -80,7 +79,6 @@ #theia-app-shell .ps__rail-y, #theia-dialog-shell .ps__rail-y { width: var(--theia-scrollbar-rail-width); - background: var(--theia-scrollbar-rail-color); } #theia-app-shell .ps__rail-y > .ps__thumb-y, @@ -108,15 +106,6 @@ width: var(--theia-scrollbar-width); } -#theia-app-shell .ps [class^='ps__rail']:hover, -#theia-app-shell .ps [class^='ps__rail']:focus, -#theia-app-shell .ps [class^='ps__rail'].ps--clicking, -#theia-dialog-shell .ps [class^='ps__rail']:hover, -#theia-dialog-shell .ps [class^='ps__rail']:focus, -#theia-dialog-shell .ps [class^='ps__rail'].ps--clicking { - background-color: var(--theia-scrollbar-active-rail-color); -} - #theia-app-shell .ps [class^='ps__rail'].ps--clicking > [class^='ps__thumb'], #theia-dialog-shell .ps [class^='ps__rail'].ps--clicking > [class^='ps__thumb']{ background-color: var(--theia-scrollbarSlider-activeBackground); @@ -152,22 +141,11 @@ |----------------------------------------------------------------------------*/ /* Make horizontal scrollbar, decorations overview ruler and vertical scrollbar arrows opaque */ -.vs .monaco-scrollable-element > .scrollbar, -.vs-dark .monaco-scrollable-element > .scrollbar, -.decorationsOverviewRuler { - background: var(--theia-scrollbar-rail-color); -} - .vs .monaco-scrollable-element > .scrollbar > .slider, .vs-dark .monaco-scrollable-element > .scrollbar > .slider { background: var(--theia-scrollbarSlider-background) !important; } -.vs .monaco-scrollable-element > .scrollbar:hover, -.vs-dark .monaco-scrollable-element > .scrollbar:hover { - background: var(--theia-scrollbar-active-rail-color); -} - .monaco-scrollable-element > .visible.scrollbar.vertical > .slider:hover, .vs .monaco-scrollable-element > .scrollbar > .slider:hover, .vs-dark .monaco-scrollable-element > .scrollbar > .slider:hover { diff --git a/packages/core/src/browser/style/sidepanel.css b/packages/core/src/browser/style/sidepanel.css index eaa7486fb7214..4ed325a1e10d4 100644 --- a/packages/core/src/browser/style/sidepanel.css +++ b/packages/core/src/browser/style/sidepanel.css @@ -183,7 +183,7 @@ z-index: 1000; } -.p-TabBar.theia-app-sides > .ps__rail-y >.ps__thumb-y { +#theia-app-shell .p-TabBar.theia-app-sides > .ps__rail-y >.ps__thumb-y { width: var(--theia-private-sidebar-scrollbar-width); right: calc((var(--theia-private-sidebar-scrollbar-rail-width) - var(--theia-private-sidebar-scrollbar-width)) / 2); } diff --git a/packages/core/src/browser/style/variables-bright.useable.css b/packages/core/src/browser/style/variables-bright.useable.css index 93790cd975386..b835d390960ce 100644 --- a/packages/core/src/browser/style/variables-bright.useable.css +++ b/packages/core/src/browser/style/variables-bright.useable.css @@ -194,29 +194,10 @@ is not optimized for dense, information rich UIs. /* Scrollbars */ --theia-scrollbar-width: 10px; --theia-scrollbar-rail-width: 10px; - --theia-scrollbar-thumb-color: hsla(0,0%,61%,.4); - --theia-scrollbar-rail-color: transparent; - --theia-scrollbar-active-thumb-color: hsla(0,0%,39%,.4); - --theia-scrollbar-active-rail-color: transparent; - --theia-scrollbar-box-shadow-color: #DDD; - - /* Menu */ - --theia-menu-color0: var(--theia-layout-color3); - --theia-menu-color1: var(--theia-layout-color0); - --theia-menu-color2: var(--theia-layout-color3); /* Statusbar */ - --theia-statusbar-color: var(--theia-brand-color0); - --theia-statusBar-font-color: var(--theia-inverse-ui-font-color0); --theia-statusBar-font-size: 12px; - - /* Dialogs */ - --theia-ui-dialog-header-color: var(--theia-brand-color1); - --theia-ui-dialog-header-font-color: var(--theia-inverse-ui-font-color0); - - /* Output */ - --theia-output-font-color: var(--theia-ui-font-color1); - + /* Opacity for disabled mod */ --theia-mod-disabled-opacity: 0.4; } diff --git a/packages/core/src/browser/style/variables-dark.useable.css b/packages/core/src/browser/style/variables-dark.useable.css index 6c487be214b67..a6f316889ecb2 100644 --- a/packages/core/src/browser/style/variables-dark.useable.css +++ b/packages/core/src/browser/style/variables-dark.useable.css @@ -194,29 +194,10 @@ is not optimized for dense, information rich UIs. /* Scrollbars */ --theia-scrollbar-width: 10px; --theia-scrollbar-rail-width: 10px; - --theia-scrollbar-thumb-color: hsla(0,0%,39%,.4); - --theia-scrollbar-rail-color: transparent; - --theia-scrollbar-active-thumb-color: hsla(0,0%,61%,.4); - --theia-scrollbar-active-rail-color: transparent; - --theia-scrollbar-box-shadow-color: #000; - - /* Menu */ - --theia-menu-color0: var(--theia-layout-color4); - --theia-menu-color1: var(--theia-layout-color4); - --theia-menu-color2: var(--theia-layout-color1); /* Statusbar */ - --theia-statusbar-color: var(--theia-brand-color0); - --theia-statusBar-font-color: var(--theia-ui-font-color0); --theia-statusBar-font-size: 12px; - /* Dialogs */ - --theia-ui-dialog-header-color: var(--theia-brand-color0); - --theia-ui-dialog-header-font-color: var(--theia-ui-font-color1); - - /* Output */ - --theia-output-font-color: var(--theia-ui-font-color1); - /* Opacity for disabled mod */ --theia-mod-disabled-opacity: 0.4; } diff --git a/packages/messages/src/browser/style/notifications.css b/packages/messages/src/browser/style/notifications.css index ccf6696c4d68f..e111c28b4ccbb 100644 --- a/packages/messages/src/browser/style/notifications.css +++ b/packages/messages/src/browser/style/notifications.css @@ -271,7 +271,6 @@ .theia-notification-list-scroll-container .ps__rail-y { width: var(--theia-scrollbar-rail-width); - background: var(--theia-scrollbar-rail-color); } .theia-notification-list-scroll-container .ps__rail-y:hover > .ps__thumb-y, @@ -284,6 +283,6 @@ .theia-notification-list-scroll-container .ps__rail-y > .ps__thumb-y { width: var(--theia-scrollbar-width); right: calc((var(--theia-scrollbar-rail-width) - var(--theia-scrollbar-width)) / 2); - background: var(--theia-scrollbar-thumb-color); + background: var(--theia-scrollbarSlider-background); border-radius: 0px; } diff --git a/packages/output/src/browser/style/output.css b/packages/output/src/browser/style/output.css index 68e4b24b274c2..aac3bd8a01569 100644 --- a/packages/output/src/browser/style/output.css +++ b/packages/output/src/browser/style/output.css @@ -16,7 +16,6 @@ #outputView { font-size: var(--theia-ui-font-size1); - color: var(--theia-output-font-color); } #outputView #outputContents { From 2f0c599b7f916f267957fa35d2b8a77713e94293 Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Fri, 13 Dec 2019 14:26:42 +0000 Subject: [PATCH 43/65] =?UTF-8?q?[theming]=C2=A0remove=20--theia-ui-font-c?= =?UTF-8?q?olor1=20css=20color?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Anton Kosyakov --- .../callhierarchy/src/browser/style/index.css | 1 - .../browser/common-frontend-contribution.ts | 178 ++++++++++++------ .../core/src/browser/style/search-box.css | 2 +- packages/core/src/browser/style/sidepanel.css | 6 +- packages/core/src/browser/style/tabs.css | 48 ++--- packages/core/src/browser/style/tree.css | 4 +- .../style/variables-bright.useable.css | 5 - .../browser/style/variables-dark.useable.css | 5 - .../core/src/browser/style/view-container.css | 5 +- packages/debug/src/browser/style/index.css | 1 - .../src/browser/style/extension-detail.css | 2 - .../src/browser/style/extension-sidebar.css | 1 - .../src/browser/style/index.css | 4 - .../filesystem/src/browser/style/index.css | 7 +- packages/git/src/browser/style/diff.css | 4 - packages/git/src/browser/style/git-icons.css | 1 - packages/git/src/browser/style/index.css | 1 - packages/keymaps/src/browser/style/index.css | 4 +- packages/markers/src/browser/style/index.css | 1 - .../mini-browser/src/browser/style/index.css | 6 +- packages/monaco/src/browser/style/index.css | 2 +- .../navigator/src/browser/style/index.css | 1 - packages/output/src/browser/style/output.css | 4 +- .../src/main/browser/style/index.css | 6 - packages/scm/src/browser/style/index.css | 1 - .../src/browser/styles/index.css | 2 - .../typehierarchy/src/browser/style/index.css | 1 - 27 files changed, 164 insertions(+), 139 deletions(-) diff --git a/packages/callhierarchy/src/browser/style/index.css b/packages/callhierarchy/src/browser/style/index.css index 1ba5de2c09ef5..cd8b13f127397 100644 --- a/packages/callhierarchy/src/browser/style/index.css +++ b/packages/callhierarchy/src/browser/style/index.css @@ -16,7 +16,6 @@ .theia-CallHierarchyTree { font-size: var(--theia-ui-font-size1); - color: var(--theia-ui-font-color1); } .theia-CallHierarchyTree .theia-TreeNode { diff --git a/packages/core/src/browser/common-frontend-contribution.ts b/packages/core/src/browser/common-frontend-contribution.ts index 62abd8e1aeb53..44431b8c1d8f2 100644 --- a/packages/core/src/browser/common-frontend-contribution.ts +++ b/packages/core/src/browser/common-frontend-contribution.ts @@ -739,15 +739,15 @@ export class CommonFrontendContribution implements FrontendApplicationContributi this.quickOpenService.open({ onType: (_, accept) => accept(items) }, { - placeholder: 'Select File Icon Theme', - fuzzyMatchLabel: true, - selectIndex: () => items.findIndex(item => item.id === this.iconThemes.current), - onClose: () => { - if (resetTo) { - this.iconThemes.current = resetTo; + placeholder: 'Select File Icon Theme', + fuzzyMatchLabel: true, + selectIndex: () => items.findIndex(item => item.id === this.iconThemes.current), + onClose: () => { + if (resetTo) { + this.iconThemes.current = resetTo; + } } - } - }); + }); } registerColors(colors: ColorRegistry): void { @@ -938,20 +938,20 @@ export class CommonFrontendContribution implements FrontendApplicationContributi id: 'tab.hoverBackground', description: 'Tab background color when hovering. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' }, { - id: 'tab.unfocusedHoverBackground', defaults: { - dark: Color.transparent('tab.hoverBackground', 0.5), - light: Color.transparent('tab.hoverBackground', 0.7) - }, description: 'Tab background color in an unfocused group when hovering. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' - }, + id: 'tab.unfocusedHoverBackground', defaults: { + dark: Color.transparent('tab.hoverBackground', 0.5), + light: Color.transparent('tab.hoverBackground', 0.7) + }, description: 'Tab background color in an unfocused group when hovering. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' + }, { id: 'tab.hoverBorder', description: 'Border to highlight tabs when hovering. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' }, { - id: 'tab.unfocusedHoverBorder', defaults: { - dark: Color.transparent('tab.hoverBorder', 0.5), - light: Color.transparent('tab.hoverBorder', 0.7) - }, description: 'Border to highlight tabs in an unfocused group when hovering. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' - }, + id: 'tab.unfocusedHoverBorder', defaults: { + dark: Color.transparent('tab.hoverBorder', 0.5), + light: Color.transparent('tab.hoverBorder', 0.7) + }, description: 'Border to highlight tabs in an unfocused group when hovering. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.' + }, { id: 'tab.activeModifiedBorder', defaults: { dark: '#3399CC', @@ -1108,21 +1108,21 @@ export class CommonFrontendContribution implements FrontendApplicationContributi light: Color.transparent('titleBar.activeForeground', 0.6) }, description: 'Title bar foreground when the window is inactive. Note that this color is currently only supported on macOS.' }, { - id: 'titleBar.activeBackground', defaults: { - dark: '#3C3C3C', - light: '#DDDDDD', - hc: '#000000' - }, description: 'Title bar background when the window is active. Note that this color is currently only supported on macOS.' - }, { - id: 'titleBar.inactiveBackground', defaults: { - dark: Color.transparent('titleBar.activeBackground', 0.6), - light: Color.transparent('titleBar.activeBackground', 0.6) - }, description: 'Title bar background when the window is inactive. Note that this color is currently only supported on macOS.' - }, { - id: 'titleBar.border', defaults: { - hc: 'contrastBorder' - }, description: 'Title bar border color. Note that this color is currently only supported on macOS.' - }, + id: 'titleBar.activeBackground', defaults: { + dark: '#3C3C3C', + light: '#DDDDDD', + hc: '#000000' + }, description: 'Title bar background when the window is active. Note that this color is currently only supported on macOS.' + }, { + id: 'titleBar.inactiveBackground', defaults: { + dark: Color.transparent('titleBar.activeBackground', 0.6), + light: Color.transparent('titleBar.activeBackground', 0.6) + }, description: 'Title bar background when the window is inactive. Note that this color is currently only supported on macOS.' + }, { + id: 'titleBar.border', defaults: { + hc: 'contrastBorder' + }, description: 'Title bar border color. Note that this color is currently only supported on macOS.' + }, // Menu Bar colors should be aligned with https://code.visualstudio.com/api/references/theme-color#menu-bar-colors { @@ -1132,33 +1132,33 @@ export class CommonFrontendContribution implements FrontendApplicationContributi hc: 'titleBar.activeForeground' }, description: 'Foreground color of the selected menu item in the menubar.' }, { - id: 'menubar.selectionBackground', defaults: { - dark: Color.transparent('#ffffff', 0.1), - light: Color.transparent('#000000', 0.1) - }, description: 'Background color of the selected menu item in the menubar.' - }, { - id: 'menubar.selectionBorder', defaults: { - hc: 'activeContrastBorder' - }, description: 'Border color of the selected menu item in the menubar.' - }, + id: 'menubar.selectionBackground', defaults: { + dark: Color.transparent('#ffffff', 0.1), + light: Color.transparent('#000000', 0.1) + }, description: 'Background color of the selected menu item in the menubar.' + }, { + id: 'menubar.selectionBorder', defaults: { + hc: 'activeContrastBorder' + }, description: 'Border color of the selected menu item in the menubar.' + }, { id: 'menu.border', defaults: { hc: 'contrastBorder' }, description: 'Border color of menus.' }, { - id: 'menu.foreground', defaults: { - dark: 'dropdown.foreground', light: 'foreground', hc: 'dropdown.foreground' + id: 'menu.foreground', defaults: { + dark: 'dropdown.foreground', light: 'foreground', hc: 'dropdown.foreground' + }, + description: 'Foreground color of menu items.' + }, { + id: 'menu.background', defaults: { + dark: 'dropdown.background', light: 'dropdown.background', hc: 'dropdown.background' + }, description: 'Background color of menu items.' + }, { + id: 'menu.selectionForeground', defaults: { + dark: 'list.activeSelectionForeground', light: 'list.activeSelectionForeground', hc: 'list.activeSelectionForeground' + }, description: 'Foreground color of the selected menu item in menus.' }, - description: 'Foreground color of menu items.' - }, { - id: 'menu.background', defaults: { - dark: 'dropdown.background', light: 'dropdown.background', hc: 'dropdown.background' - }, description: 'Background color of menu items.' - }, { - id: 'menu.selectionForeground', defaults: { - dark: 'list.activeSelectionForeground', light: 'list.activeSelectionForeground', hc: 'list.activeSelectionForeground' - }, description: 'Foreground color of the selected menu item in menus.' - }, { id: 'menu.selectionBackground', defaults: { dark: 'list.activeSelectionBackground', light: 'list.activeSelectionBackground', hc: 'list.activeSelectionBackground' }, @@ -1182,6 +1182,76 @@ export class CommonFrontendContribution implements FrontendApplicationContributi { id: 'welcomePage.buttonHoverBackground', defaults: { dark: Color.rgba(200, 235, 255, .072), light: Color.rgba(0, 0, 0, .10) }, description: 'Hover background color for the buttons on the Welcome page.' }, { id: 'walkThrough.embeddedEditorBackground', defaults: { dark: Color.rgba(0, 0, 0, .4), light: '#f4f4f4' }, description: 'Background color for the embedded editors on the Interactive Playground.' }, + // Settings Editor colors should be aligned with https://code.visualstudio.com/api/references/theme-color#settings-editor-colors + { + id: 'settings.headerForeground', defaults: { + light: '#444444', dark: '#e7e7e7', hc: '#ffffff' + }, description: 'The foreground color for a section header or active title.' + }, { + id: 'settings.modifiedItemIndicator', defaults: { + light: Color.rgba(102, 175, 224), + dark: Color.rgba(12, 125, 157), + hc: Color.rgba(0, 73, 122) + }, description: 'The color of the modified setting indicator.' + }, { + id: 'settings.dropdownBackground', defaults: + { dark: 'dropdown.background', light: 'dropdown.background', hc: 'dropdown.background' }, + description: 'Settings editor dropdown background.' + }, { + id: 'settings.dropdownForeground', defaults: { + dark: 'dropdown.foreground', light: 'dropdown.foreground', hc: 'dropdown.foreground' + }, description: 'Settings editor dropdown foreground.' + }, + { + id: 'settings.dropdownBorder', defaults: { + dark: 'dropdown.border', light: 'dropdown.border', hc: 'dropdown.border' + }, description: 'Settings editor dropdown border.' + }, + { + id: 'settings.dropdownListBorder', defaults: { + dark: 'editorWidget.border', light: 'editorWidget.border', hc: 'editorWidget.border' + }, description: 'Settings editor dropdown list border. This surrounds the options and separates the options from the description.' + }, + { + id: 'settings.checkboxBackground', defaults: { + dark: 'checkbox.background', light: 'checkbox.background', hc: 'checkbox.background' + }, description: 'Settings editor checkbox background.' + }, { + id: 'settings.checkboxForeground', defaults: { + dark: 'checkbox.foreground', light: 'checkbox.foreground', hc: 'checkbox.foreground' + }, description: 'Settings editor checkbox foreground.' + }, { + id: 'settings.checkboxBorder', defaults: + { + dark: 'checkbox.border', light: 'checkbox.border', hc: 'checkbox.border' + }, description: 'Settings editor checkbox border.' + }, { + id: 'settings.textInputBackground', defaults: { + dark: 'input.background', light: 'input.background', hc: 'input.background' + }, description: 'Settings editor text input box background.' + }, { + id: 'settings.textInputForeground', defaults: { + dark: 'input.foreground', light: 'input.foreground', hc: 'input.foreground' + }, description: 'Settings editor text input box foreground.' + }, { + id: 'settings.textInputBorder', defaults: { + dark: 'input.border', light: 'input.border', hc: 'input.border' + }, description: 'Settings editor text input box border.' + }, { + id: 'settings.numberInputBackground', defaults: { + dark: 'input.background', light: 'input.background', hc: 'input.background' + }, description: 'Settings editor number input box background.' + }, { + id: 'settings.numberInputForeground', defaults: { + dark: 'input.foreground', light: 'input.foreground', hc: 'input.foreground' + }, description: 'Settings editor number input box foreground.' + }, + { + id: 'settings.numberInputBorder', defaults: { + dark: 'input.border', light: 'input.border', hc: 'input.border' + }, description: 'Settings editor number input box border.' + }, + // Theia Variable colors { id: 'variable.name.color', defaults: { diff --git a/packages/core/src/browser/style/search-box.css b/packages/core/src/browser/style/search-box.css index 4c86f1ecffd13..497de88dcca2a 100644 --- a/packages/core/src/browser/style/search-box.css +++ b/packages/core/src/browser/style/search-box.css @@ -41,7 +41,7 @@ flex-grow: 0; font-family: FontAwesome; font-size: calc(var(--theia-content-font-size) * 0.8); - color: var(--theia-ui-font-color1); + color: var(--theia-editorWidget-foreground); } .theia-search-button-next:before { diff --git a/packages/core/src/browser/style/sidepanel.css b/packages/core/src/browser/style/sidepanel.css index 4ed325a1e10d4..62b4ea10fdfe4 100644 --- a/packages/core/src/browser/style/sidepanel.css +++ b/packages/core/src/browser/style/sidepanel.css @@ -137,7 +137,7 @@ opacity: 0.6; text-align: center; background: none; - color: var(--theia-tab-icon-color); + color: var(--theia-activityBar-inactiveForeground); } .p-TabBar.theia-app-left .p-TabBar-tabLabel { @@ -273,7 +273,7 @@ } .theia-sidepanel-toolbar .theia-sidepanel-title { - color: var(--theia-ui-font-color1); + color: var(--theia-settings-headerForeground); flex: 1; margin-left: 14px; text-transform: uppercase; @@ -281,7 +281,7 @@ } .theia-sidepanel-toolbar .p-TabBar-toolbar .item { - color: var(--theia-ui-font-color1); + color: var(--theia-icon-foreground); } .theia-sidepanel-toolbar .p-TabBar-toolbar .item > div{ diff --git a/packages/core/src/browser/style/tabs.css b/packages/core/src/browser/style/tabs.css index c881d2246c289..7b13908316771 100644 --- a/packages/core/src/browser/style/tabs.css +++ b/packages/core/src/browser/style/tabs.css @@ -14,8 +14,6 @@ |----------------------------------------------------------------------------*/ .p-TabBar { - color: var(--theia-ui-font-color1); - background: var(--theia-layout-color1); font-size: var(--theia-ui-font-size1); } @@ -39,7 +37,8 @@ align-items: center; } -.p-TabBar[data-orientation='horizontal'] .p-TabBar-tab .theia-tab-icon-label { +.p-TabBar[data-orientation='horizontal'] .p-TabBar-tab .theia-tab-icon-label, +.p-TabBar-tab.p-mod-drag-image .theia-tab-icon-label { display: flex; line-height: var(--theia-content-line-height); align-items: center; @@ -163,7 +162,7 @@ body.theia-editor-highlightModifiedTabs } .p-TabBar-tab-secondary-label { - color: var(--theia-brand-color2); + color: var(--theia-settings-headerForeground); cursor: pointer; font-size: var(--theia-ui-font-size0); margin-left: 5px; @@ -171,7 +170,7 @@ body.theia-editor-highlightModifiedTabs -webkit-appearance: none; -moz-appearance: none; - background-image: linear-gradient(45deg, transparent 50%, var(--theia-ui-font-color1) 50%), linear-gradient(135deg, var(--theia-ui-font-color1) 50%, transparent 50%); + background-image: linear-gradient(45deg, transparent 50%, var(--theia-icon-foreground) 50%), linear-gradient(135deg, var(--theia-icon-foreground) 50%, transparent 50%); background-position: calc(100% - 6px) 8px, calc(100% - 2px) 8px, 100% 0; background-size: 4px 5px; background-repeat: no-repeat; @@ -186,10 +185,11 @@ body.theia-editor-highlightModifiedTabs background-repeat: no-repeat; } -.p-TabBar.theia-app-centers .p-TabBar-tabIcon { +.p-TabBar.theia-app-centers .p-TabBar-tabIcon, +.p-TabBar-tab.p-mod-drag-image .p-TabBar-tabIcon { background-size: 13px; background-position-y: 3px; - background-color: var(--theia-tab-icon-color); + background: var(--theia-icon-foreground); -webkit-mask-repeat: no-repeat; -webkit-mask-size: 13px; mask-repeat: no-repeat; @@ -197,13 +197,15 @@ body.theia-editor-highlightModifiedTabs padding-right: calc(var(--theia-ui-padding)/2); } -.p-TabBar[data-orientation='horizontal'] .file-icon.p-TabBar-tabIcon { +.p-TabBar[data-orientation='horizontal'] .p-TabBar-tabIcon.file-icon, +.p-TabBar-tab.p-mod-drag-image .p-TabBar-tabIcon.file-icon { background: none; padding-bottom: 0px; min-height: 20px; } -.p-TabBar[data-orientation='horizontal'] .fa.p-TabBar-tabIcon { +.p-TabBar[data-orientation='horizontal'] .p-TabBar-tabIcon.fa, +.p-TabBar-tab.p-mod-drag-image .p-TabBar-tabIcon.fa { background: none; min-height: 0; } @@ -237,7 +239,8 @@ body.theia-editor-highlightModifiedTabs background-image: var(--theia-icon-close); } -.p-TabBar.theia-app-centers .p-TabBar-tab > .p-TabBar-tabIcon.no-icon { +.p-TabBar.theia-app-centers .p-TabBar-tab > .p-TabBar-tabIcon.no-icon, +.p-TabBar-tab.p-mod-drag-image > .p-TabBar-tabIcon.no-icon { display: none; } @@ -274,27 +277,16 @@ body.theia-editor-highlightModifiedTabs .p-TabBar-tab.p-mod-drag-image { transform: translateX(-40%) translateY(-58%); opacity: 0.8; + line-height: var(--theia-private-horizontal-tab-height); + height: var(--theia-private-horizontal-tab-height); min-height: var(--theia-private-horizontal-tab-height); padding: 0px 10px; font-size: var(--theia-ui-font-size1); - line-height: var(--theia-private-horizontal-tab-height); - color: var(--theia-ui-font-color1); - background: var(--theia-layout-color4); - border: var(--theia-border-width) solid var(--theia-border-color1); - box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3); -} - -.p-TabBar-tab.p-mod-drag-image > .p-TabBar-tabIcon, -.p-TabBar-tab.p-mod-drag-image > .p-TabBar-tabLabel { - display: inline-block; -} -.p-TabBar-tab.p-mod-drag-image > .p-TabBar-tabIcon.no-icon { - display: none; -} - -.p-TabBar-tab.p-mod-drag-image > .p-TabBar-tabIcon { - width: 15px; - line-height: 1.7; + background: var(--theia-editorGroupHeader-tabsBackground); + border: var(--theia-border-width) solid var(--theia-contrastBorder); + box-shadow: 1px 1px 2px var(--theia-widget-shadow); + display: flex; + align-items: center; } /*----------------------------------------------------------------------------- diff --git a/packages/core/src/browser/style/tree.css b/packages/core/src/browser/style/tree.css index d337184799e51..03f01ad2b43d6 100644 --- a/packages/core/src/browser/style/tree.css +++ b/packages/core/src/browser/style/tree.css @@ -16,7 +16,6 @@ .theia-Tree { overflow: hidden; - color: var(--theia-ui-font-color1); font-size: var(--theia-ui-font-size1); max-height: calc(100% - var(--theia-border-width)); position: relative; @@ -122,13 +121,12 @@ .theia-TreeNodeSegment mark { background-color: var(--theia-list-filterMatchBackground); - color: var(--theia-ui-font-color1); } .theia-tree-source-node-placeholder { text-align: center; font-style: italic; - opacity: var(--theia-mod-disabled-opacity);; + opacity: var(--theia-mod-disabled-opacity); } .theia-tree-element-node { diff --git a/packages/core/src/browser/style/variables-bright.useable.css b/packages/core/src/browser/style/variables-bright.useable.css index b835d390960ce..1de9377886cc3 100644 --- a/packages/core/src/browser/style/variables-bright.useable.css +++ b/packages/core/src/browser/style/variables-bright.useable.css @@ -43,16 +43,12 @@ is not optimized for dense, information rich UIs. --theia-ui-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; /** deprecated ui font colors */ - --theia-ui-font-color0: var(--theia-foreground); - --theia-ui-font-color1: var(--md-grey-700); --theia-ui-font-color2: var(--md-grey-500); --theia-ui-font-color3: var(--theia-badge-background); /* Special font colors */ --theia-ui-icon-font-color: #ffffff; - --theia-ui-bar-font-color0: var(--theia-ui-font-color0); - --theia-ui-bar-font-color1: var(--theia-ui-font-color1); /* Use the inverse UI colors against the brand/accent/warn/error colors. */ @@ -79,7 +75,6 @@ is not optimized for dense, information rich UIs. --theia-ui-padding: 6px; /* Tab Icon Colors */ - --theia-tab-icon-color: var(--theia-ui-font-color1); --theia-tab-font-color: #000; /* Main layout colors (bright to dark) diff --git a/packages/core/src/browser/style/variables-dark.useable.css b/packages/core/src/browser/style/variables-dark.useable.css index a6f316889ecb2..955c480f2def2 100644 --- a/packages/core/src/browser/style/variables-dark.useable.css +++ b/packages/core/src/browser/style/variables-dark.useable.css @@ -43,16 +43,12 @@ is not optimized for dense, information rich UIs. --theia-ui-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; /* deprecated ui font colors */ - --theia-ui-font-color0: var(--theia-foreground); - --theia-ui-font-color1: var(--md-grey-300); --theia-ui-font-color2: var(--md-grey-500); --theia-ui-font-color3: var(--theia-badge-background); /* Special font colors */ --theia-ui-icon-font-color: #d4d4d4; - --theia-ui-bar-font-color0: #eeeeee; - --theia-ui-bar-font-color1: #d4d4d4; /* Use the inverse UI colors against the brand/accent/warn/error colors. */ @@ -79,7 +75,6 @@ is not optimized for dense, information rich UIs. --theia-ui-padding: 6px; /* Tab Colors */ - --theia-tab-icon-color: rgb(255, 255, 255); --theia-tab-font-color: #FFF; /* Main layout colors (dark to bright) diff --git a/packages/core/src/browser/style/view-container.css b/packages/core/src/browser/style/view-container.css index 2343ca9cbe014..f6ef78858704e 100644 --- a/packages/core/src/browser/style/view-container.css +++ b/packages/core/src/browser/style/view-container.css @@ -104,10 +104,11 @@ } .theia-view-container-drag-image { - background: var(--theia-menu-color0); + background: var(--theia-sideBarSectionHeader-background); + color: var(--theia-sideBarSectionHeader-foreground); line-height: var(--theia-content-line-height); position: absolute; - color: var(--theia-ui-font-color1); + z-index: 999; text-transform: uppercase; font-size: var(--theia-ui-font-size0); font-weight: 500; diff --git a/packages/debug/src/browser/style/index.css b/packages/debug/src/browser/style/index.css index c937da15de018..cc5b26d1ced1a 100644 --- a/packages/debug/src/browser/style/index.css +++ b/packages/debug/src/browser/style/index.css @@ -19,7 +19,6 @@ display: flex; flex-direction: column; height: 100%; - color: var(--theia-ui-font-color1); } .theia-side-panel .theia-debug-container .theia-ExpansionToggle { diff --git a/packages/extension-manager/src/browser/style/extension-detail.css b/packages/extension-manager/src/browser/style/extension-detail.css index a0f0dcc3d152f..20859ae52a0fe 100644 --- a/packages/extension-manager/src/browser/style/extension-detail.css +++ b/packages/extension-manager/src/browser/style/extension-detail.css @@ -44,7 +44,6 @@ } .theia-extension-detail .extensionAuthor { - border-right: var(--theia-ui-font-color1) 1px solid; padding-right: 10px; box-sizing: border-box; margin-right: 10px; @@ -65,7 +64,6 @@ } .theia-extension-detail .extensionDocumentation { - color: var(--theia-ui-font-color1); height: 100%; } diff --git a/packages/extension-manager/src/browser/style/extension-sidebar.css b/packages/extension-manager/src/browser/style/extension-sidebar.css index 09c9c3db1a564..3333b23117a2d 100644 --- a/packages/extension-manager/src/browser/style/extension-sidebar.css +++ b/packages/extension-manager/src/browser/style/extension-sidebar.css @@ -43,7 +43,6 @@ border-style: solid; border-color: var(--theia-border-color1); background: var(--theia-layout-color2); - color: var(--theia-ui-font-color1); padding-left: 5px; } diff --git a/packages/extension-manager/src/browser/style/index.css b/packages/extension-manager/src/browser/style/index.css index de6a20f79ad73..2c9d0e882ce97 100644 --- a/packages/extension-manager/src/browser/style/index.css +++ b/packages/extension-manager/src/browser/style/index.css @@ -14,9 +14,6 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ -.fa-spinner { - color: var(--theia-ui-font-color1); -} .spinnerContainer { width: 100%; @@ -41,7 +38,6 @@ .extensionHeaderContainer { background: var(--theia-layout-color1); margin-bottom: 5px; - color: var(--theia-ui-font-color1); } .extensionButton { diff --git a/packages/filesystem/src/browser/style/index.css b/packages/filesystem/src/browser/style/index.css index f56e53a75ca14..8f4bfdeacaee7 100644 --- a/packages/filesystem/src/browser/style/index.css +++ b/packages/filesystem/src/browser/style/index.css @@ -26,7 +26,10 @@ font-size: var(--theia-ui-font-size1); display: inline-block; padding: 1px calc(var(--theia-ui-padding)*2); - color: var(--theia-ui-font-color1); border-radius: 10px; - background: var(--theia-accent-color2); + + background: var(--theia-list-activeSelectionBackground); + color: var(--theia-list-activeSelectionForeground); + outline: 1px solid var(--theia-contrastActiveBorder); + outline-offset: -1px; } diff --git a/packages/git/src/browser/style/diff.css b/packages/git/src/browser/style/diff.css index 112c1a60bb93e..e383cfe833b49 100644 --- a/packages/git/src/browser/style/diff.css +++ b/packages/git/src/browser/style/diff.css @@ -14,10 +14,6 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ -.theia-git { - color: var(--theia-ui-font-color1); -} - .theia-git-diff-icon { -webkit-mask: url('git-diff.svg'); mask: url('git-diff.svg'); diff --git a/packages/git/src/browser/style/git-icons.css b/packages/git/src/browser/style/git-icons.css index c3d6274a1a24c..40dd3ca566472 100644 --- a/packages/git/src/browser/style/git-icons.css +++ b/packages/git/src/browser/style/git-icons.css @@ -17,7 +17,6 @@ .icon-git-commit { mask-repeat: no-repeat; mask-position: center; - background-color: var(--theia-ui-font-color1); -webkit-mask-repeat: no-repeat; -webkit-mask-position: center; mask-image: url('~octicons/build/svg/git-commit.svg'); diff --git a/packages/git/src/browser/style/index.css b/packages/git/src/browser/style/index.css index c93cb53652de0..c8cc2a20dd233 100644 --- a/packages/git/src/browser/style/index.css +++ b/packages/git/src/browser/style/index.css @@ -15,7 +15,6 @@ ********************************************************************************/ .theia-git { - color: var(--theia-ui-font-color1); padding: 5px; box-sizing: border-box; } diff --git a/packages/keymaps/src/browser/style/index.css b/packages/keymaps/src/browser/style/index.css index e22a73f4f1d95..07e56af69cc15 100644 --- a/packages/keymaps/src/browser/style/index.css +++ b/packages/keymaps/src/browser/style/index.css @@ -43,7 +43,7 @@ .kb table { border-spacing: 0; border-collapse: separate; - color: var(--theia-ui-font-color1); + background-color: var(--theia-editor-background); width: 100%; table-layout: fixed; } @@ -106,7 +106,7 @@ .kb table tbody tr:hover .kb-action-item { visibility: visible; - color: var(--theia-ui-font-color1); + color: var(--theia-icon-foreground); text-decoration: none; } diff --git a/packages/markers/src/browser/style/index.css b/packages/markers/src/browser/style/index.css index 587173a9b7da5..c5e453f6cc9ac 100644 --- a/packages/markers/src/browser/style/index.css +++ b/packages/markers/src/browser/style/index.css @@ -16,7 +16,6 @@ .theia-marker-container { font-size: var(--theia-ui-font-size1); - color: var(--theia-ui-font-color1); } .theia-side-panel .theia-marker-container .noMarkers { diff --git a/packages/mini-browser/src/browser/style/index.css b/packages/mini-browser/src/browser/style/index.css index 567aeab90e5aa..c979756b16891 100644 --- a/packages/mini-browser/src/browser/style/index.css +++ b/packages/mini-browser/src/browser/style/index.css @@ -78,16 +78,16 @@ flex-grow: 0; font-family: FontAwesome; font-size: calc(var(--theia-content-font-size) * 0.8); - color: var(--theia-ui-font-color1); + color: var(--theia-icon-foreground); margin: 0px 4px 0px 4px; } .theia-mini-browser-button:not(.theia-mini-browser-button-disabled):hover { - color: var(--theia-ui-font-color2); + cursor: pointer; } .theia-mini-browser-button-disabled { - color: var(--theia-disabled-color0); + opacity: var(--theia-mod-disabled-opacity); } .theia-mini-browser-previous::before { diff --git a/packages/monaco/src/browser/style/index.css b/packages/monaco/src/browser/style/index.css index fa3af9b6bc4df..85531704d102b 100644 --- a/packages/monaco/src/browser/style/index.css +++ b/packages/monaco/src/browser/style/index.css @@ -13,7 +13,7 @@ } .monaco-keybinding-key { - color: var(--theia-ui-font-color1) !important; + color: var(--theia-quickInput-foreground) !important; } /* diff --git a/packages/navigator/src/browser/style/index.css b/packages/navigator/src/browser/style/index.css index d4f61b4712d56..01e8a9302aa0c 100644 --- a/packages/navigator/src/browser/style/index.css +++ b/packages/navigator/src/browser/style/index.css @@ -20,7 +20,6 @@ .theia-navigator-container { font-size: var(--theia-ui-font-size1); - color: var(--theia-ui-font-color1); padding: 5px; position: relative; } diff --git a/packages/output/src/browser/style/output.css b/packages/output/src/browser/style/output.css index aac3bd8a01569..2b277750b3d6b 100644 --- a/packages/output/src/browser/style/output.css +++ b/packages/output/src/browser/style/output.css @@ -32,11 +32,9 @@ #outputView #outputChannelList { line-height: var(--theia-content-line-height); font-size: var(--theia-ui-font-size1); - color: var(--theia-ui-font-color1); - + -webkit-appearance: none; -moz-appearance: none; - background-image: linear-gradient(45deg, transparent 50%, var(--theia-ui-font-color1) 50%), linear-gradient(135deg, var(--theia-ui-font-color1) 50%, transparent 50%); background-position: calc(100% - 6px) 8px, calc(100% - 2px) 8px, 100% 0; background-size: 4px 5px; background-repeat: no-repeat; diff --git a/packages/plugin-ext/src/main/browser/style/index.css b/packages/plugin-ext/src/main/browser/style/index.css index 2724f2bc9317c..f265b9e15fbc6 100644 --- a/packages/plugin-ext/src/main/browser/style/index.css +++ b/packages/plugin-ext/src/main/browser/style/index.css @@ -14,10 +14,6 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ -.fa-spinner { - color: var(--theia-ui-font-color1); -} - .spinnerContainer { width: 100%; height: 100%; @@ -39,9 +35,7 @@ } .pluginHeaderContainer { - background: var(--theia-layout-color1); margin-bottom: 5px; - color: var(--theia-ui-font-color1); } .theia-plugin-test-tab-icon { diff --git a/packages/scm/src/browser/style/index.css b/packages/scm/src/browser/style/index.css index 097890c49730b..5a3641d74534c 100644 --- a/packages/scm/src/browser/style/index.css +++ b/packages/scm/src/browser/style/index.css @@ -14,7 +14,6 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ .theia-scm { - color: var(--theia-ui-font-color1); padding: 5px; box-sizing: border-box; height: 100%; diff --git a/packages/search-in-workspace/src/browser/styles/index.css b/packages/search-in-workspace/src/browser/styles/index.css index 26439a3f79438..77256f62fe0b3 100644 --- a/packages/search-in-workspace/src/browser/styles/index.css +++ b/packages/search-in-workspace/src/browser/styles/index.css @@ -20,7 +20,6 @@ } .t-siw-search-container { - color: var(--theia-ui-font-color1); padding: 5px ; display: flex; flex-direction: column; @@ -37,7 +36,6 @@ flex: 1; line-height: var(--theia-content-line-height); padding-left: 8px; - color: var(--theia-ui-font-color1); padding: 3px 0 3px 4px; } diff --git a/packages/typehierarchy/src/browser/style/index.css b/packages/typehierarchy/src/browser/style/index.css index 64878e4e2cf52..b23db3f19c68e 100644 --- a/packages/typehierarchy/src/browser/style/index.css +++ b/packages/typehierarchy/src/browser/style/index.css @@ -16,7 +16,6 @@ .theia-type-hierarchy-tree { font-size: var(--theia-ui-font-size0); - color: var(--theia-ui-font-color1); } .theia-type-hierarchy-tree .theia-caption-suffix { From abdc152cd27607f5a2a6177d5babdf840956f34c Mon Sep 17 00:00:00 2001 From: Jan Bicker Date: Fri, 13 Dec 2019 15:16:07 +0000 Subject: [PATCH 44/65] Removed old color variables for highlighted words Signed-off-by: Jan Bicker --- .../src/browser/style/variables-bright.useable.css | 8 -------- .../core/src/browser/style/variables-dark.useable.css | 8 -------- .../search-in-workspace/src/browser/styles/index.css | 11 +++-------- 3 files changed, 3 insertions(+), 24 deletions(-) diff --git a/packages/core/src/browser/style/variables-bright.useable.css b/packages/core/src/browser/style/variables-bright.useable.css index 1de9377886cc3..3a77cc908e69d 100644 --- a/packages/core/src/browser/style/variables-bright.useable.css +++ b/packages/core/src/browser/style/variables-bright.useable.css @@ -156,14 +156,6 @@ is not optimized for dense, information rich UIs. /* Background for selected text */ --theia-selected-text-background: var(--theia-accent-color3); - /* Colors to highlight words in widgets like tree or editors */ - - --theia-word-highlight-color0: rgba(168, 172, 148, 0.7); - --theia-word-highlight-color1: rgba(253, 255, 0, 0.2); - --theia-word-highlight-match-color0: rgba(234, 92, 0, 0.33); - --theia-word-highlight-match-color1: rgba(234, 92, 0, 0.5); - --theia-word-highlight-replace-color0: rgba(155, 185, 85, 0.2); - /* Icons */ --theia-icon-close: url(../icons/close-bright.svg); --theia-sprite-y-offset: 0px; diff --git a/packages/core/src/browser/style/variables-dark.useable.css b/packages/core/src/browser/style/variables-dark.useable.css index 955c480f2def2..6e516d7b2dc9c 100644 --- a/packages/core/src/browser/style/variables-dark.useable.css +++ b/packages/core/src/browser/style/variables-dark.useable.css @@ -156,14 +156,6 @@ is not optimized for dense, information rich UIs. /* Background for selected text */ --theia-selected-text-background: var(--theia-accent-color2); - /* Colors to highlight words in widgets like tree or editors */ - - --theia-word-highlight-color0: rgba(81, 92, 106, 0.7); - --theia-word-highlight-color1: rgba(255, 255, 255, 0.04); - --theia-word-highlight-match-color0: rgba(234, 92, 0, 0.33); - --theia-word-highlight-match-color1: rgba(234, 92, 0, 0.5); - --theia-word-highlight-replace-color0: rgba(155, 185, 85, 0.2); - /* Icons */ --theia-icon-close: url(../icons/close-dark.svg); --theia-sprite-y-offset: -20px; diff --git a/packages/search-in-workspace/src/browser/styles/index.css b/packages/search-in-workspace/src/browser/styles/index.css index 77256f62fe0b3..59d7ebec5ea70 100644 --- a/packages/search-in-workspace/src/browser/styles/index.css +++ b/packages/search-in-workspace/src/browser/styles/index.css @@ -14,11 +14,6 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ - :root { - --theia-current-search-match-color: var(--theia-word-highlight-color0); - --theia-range-highlight: var(--theia-word-highlight-color1); - } - .t-siw-search-container { padding: 5px ; display: flex; @@ -266,15 +261,15 @@ } .search-in-workspace-editor-match { - background: var(--theia-word-highlight-match-color0); + background: var(--theia-editor-findMatchHighlightBackground); } .current-search-in-workspace-editor-match { - background: var(--theia-current-search-match-color) + background: var(--theia-editor-findMatchBackground) } .current-match-range-highlight { - background: var(--theia-range-highlight); + background: var(--theia-editor-findRangeHighlightBackground); } .result-node-buttons { From 570a55596333d7442c387284140afaf9b13c54df Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Fri, 13 Dec 2019 15:25:54 +0000 Subject: [PATCH 45/65] [theming] remove old font and icon colors Signed-off-by: Anton Kosyakov --- .../callhierarchy/src/browser/style/index.css | 2 +- packages/core/src/browser/style/sidepanel.css | 4 ++-- packages/core/src/browser/style/tabs.css | 2 +- packages/core/src/browser/style/tree.css | 2 +- .../style/variables-bright.useable.css | 24 ------------------- .../browser/style/variables-dark.useable.css | 24 ------------------- packages/debug/src/browser/style/index.css | 6 ++--- .../src/browser/style/extension-detail.css | 1 - .../src/browser/style/extension-sidebar.css | 1 - .../src/browser/style/index.css | 1 - packages/keymaps/src/browser/style/index.css | 1 - packages/markers/src/browser/style/index.css | 4 ++-- .../src/browser/monaco-outline-decorator.ts | 2 +- packages/monaco/src/browser/style/index.css | 2 +- .../src/main/browser/style/tree.css | 2 +- .../src/browser/preferences-decorator.ts | 2 +- .../src/browser/markdown/style/markdown.css | 18 ++++++++++---- packages/scm/src/browser/style/index.css | 4 ---- .../src/browser/style/scm-amend-component.css | 2 +- .../src/browser/styles/index.css | 6 ++--- .../src/browser/tree/typehierarchy-tree.ts | 2 +- 21 files changed, 33 insertions(+), 79 deletions(-) diff --git a/packages/callhierarchy/src/browser/style/index.css b/packages/callhierarchy/src/browser/style/index.css index cd8b13f127397..1e1aef45291a3 100644 --- a/packages/callhierarchy/src/browser/style/index.css +++ b/packages/callhierarchy/src/browser/style/index.css @@ -48,7 +48,7 @@ } .theia-CallHierarchyTree .definitionNode .container { - color: var(--theia-ui-font-color2); + color: var(--theia-descriptionForeground); } .call-hierarchy-tab-icon::before { diff --git a/packages/core/src/browser/style/sidepanel.css b/packages/core/src/browser/style/sidepanel.css index 62b4ea10fdfe4..00864569656c6 100644 --- a/packages/core/src/browser/style/sidepanel.css +++ b/packages/core/src/browser/style/sidepanel.css @@ -33,7 +33,7 @@ .p-TabBar.theia-app-sides { display: block; - color: var(--theia-tab-font-color); + color: var(--theia-activityBar-foreground); background: var(--theia-activityBar-background); font-size: var(--theia-ui-font-size1); min-width: var(--theia-private-sidebar-tab-width); @@ -72,7 +72,7 @@ } .p-TabBar.theia-app-sides .p-TabBar-tab.p-mod-current { - color: var(--theia-tab-font-color); + color: var(--theia-activityBar-foreground); opacity: 1.0; background: none; min-height: var(--theia-private-sidebar-tab-height); diff --git a/packages/core/src/browser/style/tabs.css b/packages/core/src/browser/style/tabs.css index 7b13908316771..a5144388f26b5 100644 --- a/packages/core/src/browser/style/tabs.css +++ b/packages/core/src/browser/style/tabs.css @@ -151,7 +151,7 @@ body.theia-editor-highlightModifiedTabs .p-TabBar.theia-app-centers .p-TabBar-tabLabelDetails { margin-left: 5px; - color: var(--theia-ui-font-color2); + color: var(--theia-descriptionForeground); flex: 1 1 auto; overflow: hidden; white-space: nowrap; diff --git a/packages/core/src/browser/style/tree.css b/packages/core/src/browser/style/tree.css index 03f01ad2b43d6..04b824ae43bf4 100644 --- a/packages/core/src/browser/style/tree.css +++ b/packages/core/src/browser/style/tree.css @@ -94,7 +94,7 @@ } .theia-TreeNode.theia-mod-not-selectable { - color: var(--theia-ui-font-color2); + color: var(--theia-descriptionForeground); } .theia-TreeNode.theia-mod-not-selectable:hover { background: none; diff --git a/packages/core/src/browser/style/variables-bright.useable.css b/packages/core/src/browser/style/variables-bright.useable.css index 3a77cc908e69d..8941d7afb46cd 100644 --- a/packages/core/src/browser/style/variables-bright.useable.css +++ b/packages/core/src/browser/style/variables-bright.useable.css @@ -23,9 +23,6 @@ is not optimized for dense, information rich UIs. --theia-border-width: 1px; --theia-panel-border-width: 2px; - --theia-border-color0: var(--md-grey-100); - --theia-border-color1: var(--md-grey-200); - --theia-border-color3: var(--md-grey-500); /* UI fonts: Family, size and color (dark to bright) @@ -42,30 +39,12 @@ is not optimized for dense, information rich UIs. --theia-ui-icon-font-size: 14px; /* Ensures px perfect FontAwesome icons */ --theia-ui-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - /** deprecated ui font colors */ - --theia-ui-font-color2: var(--md-grey-500); - --theia-ui-font-color3: var(--theia-badge-background); - - /* Special font colors */ - - --theia-ui-icon-font-color: #ffffff; - - /* Use the inverse UI colors against the brand/accent/warn/error colors. */ - - --theia-inverse-ui-font-color0: rgba(255,255,255,1.0); - --theia-inverse-ui-font-color2: rgba(255,255,255,0.7); - --theia-inverse-ui-font-color3: rgba(255,255,255,0.5); - /* Content fonts: Family, size and color (dark to bright) Content font variables are used for typography of user-generated content. */ --theia-content-font-size: 13px; --theia-content-line-height: 22px; - --theia-content-font-color0: black; - --theia-content-font-color1: black; - --theia-content-font-color2: var(--md-grey-700); - --theia-content-font-color3: var(--md-grey-500); --theia-code-font-size: 13px; --theia-code-line-height: 17px; @@ -74,9 +53,6 @@ is not optimized for dense, information rich UIs. --theia-terminal-font-family: monospace; --theia-ui-padding: 6px; - /* Tab Icon Colors */ - --theia-tab-font-color: #000; - /* Main layout colors (bright to dark) ------------------------------------ */ diff --git a/packages/core/src/browser/style/variables-dark.useable.css b/packages/core/src/browser/style/variables-dark.useable.css index 6e516d7b2dc9c..4c5b46ced749f 100644 --- a/packages/core/src/browser/style/variables-dark.useable.css +++ b/packages/core/src/browser/style/variables-dark.useable.css @@ -23,9 +23,6 @@ is not optimized for dense, information rich UIs. --theia-border-width: 1px; --theia-panel-border-width: 2px; - --theia-border-color0: var(--md-grey-900); - --theia-border-color1: var(--md-grey-800); - --theia-border-color3: var(--md-grey-400); /* UI fonts: Family, size and color (bright to dark) @@ -42,30 +39,12 @@ is not optimized for dense, information rich UIs. --theia-ui-icon-font-size: 14px; /* Ensures px perfect FontAwesome icons */ --theia-ui-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - /* deprecated ui font colors */ - --theia-ui-font-color2: var(--md-grey-500); - --theia-ui-font-color3: var(--theia-badge-background); - - /* Special font colors */ - - --theia-ui-icon-font-color: #d4d4d4; - - /* Use the inverse UI colors against the brand/accent/warn/error colors. */ - - --theia-inverse-ui-font-color0: rgba(0,0,0,1.0); - --theia-inverse-ui-font-color2: rgba(0,0,0,0.7); - --theia-inverse-ui-font-color3: rgba(0,0,0,0.5); - /* Content fonts: Family, size and color (bright to dark) Content font variables are used for typography of user-generated content. */ --theia-content-font-size: 13px; --theia-content-line-height: 22px; - --theia-content-font-color0: white; - --theia-content-font-color1: white; - --theia-content-font-color2: var(--md-grey-500); - --theia-content-font-color3: var(--md-grey-700); --theia-code-font-size: 13px; --theia-code-line-height: 17px; @@ -74,9 +53,6 @@ is not optimized for dense, information rich UIs. --theia-terminal-font-family: monospace; --theia-ui-padding: 6px; - /* Tab Colors */ - --theia-tab-font-color: #FFF; - /* Main layout colors (dark to bright) ------------------------------------ */ diff --git a/packages/debug/src/browser/style/index.css b/packages/debug/src/browser/style/index.css index cc5b26d1ced1a..5c2a09a85e742 100644 --- a/packages/debug/src/browser/style/index.css +++ b/packages/debug/src/browser/style/index.css @@ -53,7 +53,7 @@ .theia-source-breakpoint .path { font-size: var(--theia-ui-font-size0); - color: var(--theia-ui-font-color2); + color: var(--theia-descriptionForeground); } .theia-source-breakpoint .line-info { @@ -65,8 +65,8 @@ .theia-source-breakpoint .line, .theia-debug-stack-frame .line { - background: var(--theia-ui-font-color2); - color: var(--theia-inverse-ui-font-color0); + background: var(--theia-descriptionForeground); + color: var(--theia-editor-background); padding: calc(var(--theia-ui-padding)/3); font-size: var(--theia-ui-font-size0); line-height: calc(var(--theia-private-horizontal-tab-height)/2); diff --git a/packages/extension-manager/src/browser/style/extension-detail.css b/packages/extension-manager/src/browser/style/extension-detail.css index 20859ae52a0fe..8513b2a35f65e 100644 --- a/packages/extension-manager/src/browser/style/extension-detail.css +++ b/packages/extension-manager/src/browser/style/extension-detail.css @@ -22,7 +22,6 @@ .theia-extension-detail .extensionHeaderContainer { background: var(--theia-layout-color0); padding: 15px 22px; - border-bottom: 3px solid var(--theia-border-color1); } .theia-extension-detail .extensionTitleContainer { diff --git a/packages/extension-manager/src/browser/style/extension-sidebar.css b/packages/extension-manager/src/browser/style/extension-sidebar.css index 3333b23117a2d..c9c8c07746da1 100644 --- a/packages/extension-manager/src/browser/style/extension-sidebar.css +++ b/packages/extension-manager/src/browser/style/extension-sidebar.css @@ -41,7 +41,6 @@ line-height: var(--theia-content-line-height); border-width: 1px; border-style: solid; - border-color: var(--theia-border-color1); background: var(--theia-layout-color2); padding-left: 5px; } diff --git a/packages/extension-manager/src/browser/style/index.css b/packages/extension-manager/src/browser/style/index.css index 2c9d0e882ce97..00a3d1e138bff 100644 --- a/packages/extension-manager/src/browser/style/index.css +++ b/packages/extension-manager/src/browser/style/index.css @@ -44,7 +44,6 @@ background-color: var(--theia-success-color1); padding: 2px; box-sizing: border-box; - color: var(--theia-ui-icon-font-color); width: 65px; text-align: center; font-size: var(--theia-ui-font-size0); diff --git a/packages/keymaps/src/browser/style/index.css b/packages/keymaps/src/browser/style/index.css index 07e56af69cc15..6ee5ec8c22fbb 100644 --- a/packages/keymaps/src/browser/style/index.css +++ b/packages/keymaps/src/browser/style/index.css @@ -111,7 +111,6 @@ } .kb table th { - border-bottom: 2px solid var(--theia-ui-font-color3); word-break: keep-all; padding-bottom: 5px; padding-top: 5px; diff --git a/packages/markers/src/browser/style/index.css b/packages/markers/src/browser/style/index.css index c5e453f6cc9ac..ef8b90320761f 100644 --- a/packages/markers/src/browser/style/index.css +++ b/packages/markers/src/browser/style/index.css @@ -47,7 +47,7 @@ .theia-marker-container .markerFileNode .path { font-size: var(--theia-ui-font-size0); - color: var(--theia-ui-font-color2); + color: var(--theia-descriptionForeground); align-self: flex-end; white-space: nowrap; } @@ -71,7 +71,7 @@ .theia-marker-container .markerNode .position, .theia-marker-container .markerNode .owner, .theia-marker-container .markerNode .code { - color: var(--theia-ui-font-color2); + color: var(--theia-descriptionForeground); white-space: nowrap; } diff --git a/packages/monaco/src/browser/monaco-outline-decorator.ts b/packages/monaco/src/browser/monaco-outline-decorator.ts index 8786e9f741a5b..5b8ba79baeb5d 100644 --- a/packages/monaco/src/browser/monaco-outline-decorator.ts +++ b/packages/monaco/src/browser/monaco-outline-decorator.ts @@ -55,7 +55,7 @@ export class MonacoOutlineDecorator implements TreeDecorator { const captionSuffixes: TreeDecoration.CaptionAffix[] = [{ data: (node.detail || ''), fontData: { - color: 'var(--theia-ui-font-color2)', + color: 'var(--theia-descriptionForeground)', } }]; diff --git a/packages/monaco/src/browser/style/index.css b/packages/monaco/src/browser/style/index.css index 85531704d102b..7512eb7984890 100644 --- a/packages/monaco/src/browser/style/index.css +++ b/packages/monaco/src/browser/style/index.css @@ -46,7 +46,7 @@ } .quick-open-entry .quick-open-row .monaco-icon-label .monaco-icon-label-description-container .label-description { - color: var(--theia-ui-font-color2); + color: var(--theia-descriptionForeground); font-size: calc(var(--theia-ui-font-size0) * 0.95); } diff --git a/packages/plugin-ext/src/main/browser/style/tree.css b/packages/plugin-ext/src/main/browser/style/tree.css index 71e9184520462..43566e3ba9d05 100644 --- a/packages/plugin-ext/src/main/browser/style/tree.css +++ b/packages/plugin-ext/src/main/browser/style/tree.css @@ -33,7 +33,7 @@ } .theia-tree-view-description { - color: var(--theia-ui-font-color2); + color: var(--theia-descriptionForeground); font-size: var(--theia-ui-font-size0); margin-left: var(--theia-ui-padding); } diff --git a/packages/preferences/src/browser/preferences-decorator.ts b/packages/preferences/src/browser/preferences-decorator.ts index 8c1b21965eb0b..2c11c39b5c7cb 100644 --- a/packages/preferences/src/browser/preferences-decorator.ts +++ b/packages/preferences/src/browser/preferences-decorator.ts @@ -58,7 +58,7 @@ export class PreferencesDecorator implements TreeDecorator { }, { data: ' ' + description, - fontData: { color: 'var(--theia-ui-font-color2)' } + fontData: { color: 'var(--theia-descriptionForeground)' } }] }] as [string, TreeDecoration.Data]; })); diff --git a/packages/preview/src/browser/markdown/style/markdown.css b/packages/preview/src/browser/markdown/style/markdown.css index f15a86382926a..edf356e212992 100644 --- a/packages/preview/src/browser/markdown/style/markdown.css +++ b/packages/preview/src/browser/markdown/style/markdown.css @@ -50,7 +50,7 @@ } .markdown-preview .line:hover:before { - border-left: 3px solid var(--theia-border-color3); + border-left: 3px solid var(--theia-editor-foreground); } .markdown-preview .line .line:hover:before { @@ -114,7 +114,11 @@ .markdown-preview table > thead > tr > th { text-align: left; border-bottom: 1px solid; - border-color: var(--theia-content-font-color3); + border-color: rgba(255, 255, 255, 0.69); +} + +.theia-light .markdown-preview table > thead > tr > th { + border-color: rgba(0, 0, 0, 0.69); } .markdown-preview table > thead > tr > th, @@ -156,7 +160,7 @@ .markdown-preview, .markdown-preview pre code { - color: var(--theia-content-font-color0); + color: var(--theia-editor-foreground); } .markdown-preview pre:not(.hljs), @@ -167,5 +171,11 @@ .markdown-preview h1, .markdown-preview hr, .markdown-preview table > tbody > tr + tr > td { - border-color: var(--theia-content-font-color3); + border-color: rgba(255, 255, 255, 0.18); +} + +.theia-light .markdown-preview h1, +.theia-light .markdown-preview hr, +.theia-light .markdown-preview table > tbody > tr + tr > td { + border-color: rgba(0, 0, 0, 0.18); } diff --git a/packages/scm/src/browser/style/index.css b/packages/scm/src/browser/style/index.css index 5a3641d74534c..8b926c4a55742 100644 --- a/packages/scm/src/browser/style/index.css +++ b/packages/scm/src/browser/style/index.css @@ -128,10 +128,6 @@ padding: 4px 4px 4px 4px; } -.theia-scm-validation-message-idle { - background-color: var(--theia-border-color0) !important; -} - .theia-scm-validation-message-info { background-color: var(--theia-info-color0) !important; color: var(--theia-info-font-color0); diff --git a/packages/scm/src/browser/style/scm-amend-component.css b/packages/scm/src/browser/style/scm-amend-component.css index 0b0ee446de623..c278fbab0044c 100644 --- a/packages/scm/src/browser/style/scm-amend-component.css +++ b/packages/scm/src/browser/style/scm-amend-component.css @@ -72,7 +72,7 @@ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; - color: var(--theia-ui-font-color2); + color: var(--theia-descriptionForeground); font-size: smaller; } diff --git a/packages/search-in-workspace/src/browser/styles/index.css b/packages/search-in-workspace/src/browser/styles/index.css index 59d7ebec5ea70..68b1ef71883dd 100644 --- a/packages/search-in-workspace/src/browser/styles/index.css +++ b/packages/search-in-workspace/src/browser/styles/index.css @@ -221,7 +221,7 @@ } .t-siw-search-container .result .result-head .file-path { - color: var(--theia-ui-font-color2); + color: var(--theia-descriptionForeground); font-size: var(--theia-ui-font-size0); margin-left: 3px; } @@ -378,11 +378,11 @@ } .t-siw-search-container .searchHeader .search-info { - color: var(--theia-ui-font-color2); + color: var(--theia-descriptionForeground); margin-left: 17px; } .theia-siw-lineNumber { - color: var(--theia-ui-font-color2); + opacity: .7; padding-right: 4px; } diff --git a/packages/typehierarchy/src/browser/tree/typehierarchy-tree.ts b/packages/typehierarchy/src/browser/tree/typehierarchy-tree.ts index 25f8fe6f52bb9..6e12d76dfa510 100644 --- a/packages/typehierarchy/src/browser/tree/typehierarchy-tree.ts +++ b/packages/typehierarchy/src/browser/tree/typehierarchy-tree.ts @@ -161,7 +161,7 @@ export namespace TypeHierarchyTree { const captionSuffixes: TreeDecoration.CaptionAffix[] = [{ data: new URI(item.uri).displayName, fontData: { - color: 'var(--theia-ui-font-color2)', + color: 'var(--theia-descriptionForeground)', } }]; if (item.detail) { From b4f8c755da373c64cd3a2d76799083712bffbdc0 Mon Sep 17 00:00:00 2001 From: Jan Bicker Date: Fri, 13 Dec 2019 16:42:25 +0000 Subject: [PATCH 46/65] Removed State colors (warn, error, success, info) introduced new variables for state backgrounds, adapted respective css. --- .../browser/common-frontend-contribution.ts | 33 +++++++++++++++++++ .../src/browser/connection-status-service.ts | 2 +- .../core/src/browser/style/alert-messages.css | 10 +++--- .../style/variables-bright.useable.css | 25 -------------- .../browser/style/variables-dark.useable.css | 28 ---------------- .../src/browser/style/index.css | 2 +- .../src/browser/problem/problem-decorator.ts | 2 +- .../problem/problem-tabbar-decorator.ts | 2 +- packages/markers/src/browser/style/index.css | 2 +- .../mini-browser/src/browser/style/index.css | 4 +-- .../plugin-ext/src/main/style/status-bar.css | 4 +-- packages/scm/src/browser/style/index.css | 10 +++--- .../src/browser/styles/index.css | 6 ++-- .../src/browser/tree/typehierarchy-tree.ts | 2 +- 14 files changed, 56 insertions(+), 76 deletions(-) diff --git a/packages/core/src/browser/common-frontend-contribution.ts b/packages/core/src/browser/common-frontend-contribution.ts index 44431b8c1d8f2..11e9d08067bc5 100644 --- a/packages/core/src/browser/common-frontend-contribution.ts +++ b/packages/core/src/browser/common-frontend-contribution.ts @@ -1427,6 +1427,39 @@ export class CommonFrontendContribution implements FrontendApplicationContributi }, // Theia defaults + // Base + { + id: 'errorBackground', + defaults: { + dark: 'inputValidation.errorBackground', + light: 'inputValidation.errorBackground', + hc: 'inputValidation.errorBackground' + }, description: 'Background color of error widgets (like alerts or notifications).' + }, + { + id: 'warningBackground', + defaults: { + dark: 'inputValidation.warningBackground', + light: 'inputValidation.warningBackground', + hc: 'inputValidation.warningBackground' + }, description: 'Background color of warn widgets (like alerts or notifications).' + }, + { + id: 'successBackground', + defaults: { + dark: 'gitDecoration.untrackedResourceForeground', + light: 'gitDecoration.untrackedResourceForeground', + hc: 'gitDecoration.untrackedResourceForeground' + }, description: 'Background color of success widgets (like alerts or notifications).' + }, + { + id: 'infoBackground', + defaults: { + dark: 'inputValidation.infoBackground', + light: 'inputValidation.infoBackground', + hc: 'inputValidation.infoBackground' + }, description: 'Background color of info widgets (like alerts or notifications).' + }, // Buttons { id: 'secondaryButton.foreground', diff --git a/packages/core/src/browser/connection-status-service.ts b/packages/core/src/browser/connection-status-service.ts index ae75281247731..54e3be3717111 100644 --- a/packages/core/src/browser/connection-status-service.ts +++ b/packages/core/src/browser/connection-status-service.ts @@ -211,6 +211,6 @@ export class ApplicationConnectionStatusContribution extends DefaultFrontendAppl priority: 5000 }); this.statusBar.setBackgroundColor('var(--theia-editorWarning-foreground)'); - this.statusBar.setColor('var(--theia-warn-font-color0)'); + this.statusBar.setColor('var(--theia-statusBar-foreground)'); } } diff --git a/packages/core/src/browser/style/alert-messages.css b/packages/core/src/browser/style/alert-messages.css index bb697c71d5ce8..6b3bbf212b4d6 100644 --- a/packages/core/src/browser/style/alert-messages.css +++ b/packages/core/src/browser/style/alert-messages.css @@ -26,28 +26,28 @@ /* information message */ .theia-info-alert { - background-color: var(--theia-brand-color0); + background-color: var(--theia-infoBackground); color: #ffffff; padding: 10px; } /* success message */ .theia-success-alert { - background-color: var(--theia-success-color0); + background-color: var(--theia-successBackground); color: #ffffff; padding: 10px; } /* warning message */ .theia-warning-alert { - background-color: var(--theia-editorWarning-foreground); - color: var(--theia-warn-font-color0); + background-color: var(--theia-inputValidation-warningBackground); + color: var(--theia-inputValidation-warningForeground); padding: 10px; } /* error message */ .theia-error-alert { - background-color: var(--theia-error-color0); + background-color: var(--theia-errorBackground); color: #ffffff; padding: 10px; } diff --git a/packages/core/src/browser/style/variables-bright.useable.css b/packages/core/src/browser/style/variables-bright.useable.css index 8941d7afb46cd..bc43769398917 100644 --- a/packages/core/src/browser/style/variables-bright.useable.css +++ b/packages/core/src/browser/style/variables-bright.useable.css @@ -94,41 +94,16 @@ is not optimized for dense, information rich UIs. /* State colors (warn, error, success, info) ------------------------------------------ */ - --theia-warn-color1: var(--md-amber-400); - --theia-warn-color2: var(--md-amber-300); - --theia-warn-color3: var(--md-amber-200); - - --theia-warn-font-color0: var(--md-grey-900); - - --theia-error-color0: var(--md-red-400); - --theia-error-color2: var(--md-red-200); - --theia-error-color3: var(--md-red-100); - - --theia-error-font-color0: var(--md-grey-300); - --theia-success-color0: var(--md-green-500); - --theia-success-color1: var(--md-green-300); --theia-success-color2: var(--md-green-100); - --theia-success-color3: var(--md-green-50); --theia-success-font-color0: var(--md-grey-300); --theia-info-color0: var(--md-cyan-700); --theia-info-color1: var(--md-cyan-500); - --theia-info-color2: var(--md-cyan-300); - --theia-info-color3: var(--md-cyan-100); --theia-info-font-color0: var(--md-grey-300); - --theia-disabled-color0: var(--md-grey-500); - --theia-disabled-color1: var(--md-grey-300); - --theia-disabled-color2: var(--md-grey-200); - --theia-disabled-color3: var(--md-grey-50); - - --theia-added-color0: rgba(0, 255, 0, 0.8); - --theia-removed-color0: rgba(230, 0, 0, 0.8); - --theia-modified-color0: rgba(0, 100, 150, 0.8); - /* Background for selected text */ --theia-selected-text-background: var(--theia-accent-color3); diff --git a/packages/core/src/browser/style/variables-dark.useable.css b/packages/core/src/browser/style/variables-dark.useable.css index 4c5b46ced749f..74c68a4003344 100644 --- a/packages/core/src/browser/style/variables-dark.useable.css +++ b/packages/core/src/browser/style/variables-dark.useable.css @@ -94,44 +94,16 @@ is not optimized for dense, information rich UIs. /* State colors (warn, error, success, info) ------------------------------------------ */ - --theia-warn-color1: var(--md-amber-500); - --theia-warn-color2: var(--md-amber-400); - --theia-warn-color3: var(--md-amber-300); - - --theia-warn-font-color0: var(--md-grey-900); - - --theia-error-color0: var(--md-red-700); - --theia-error-color2: var(--md-red-300); - --theia-error-color3: var(--md-red-100); - - --theia-error-font-color0: var(--md-grey-300); - --theia-success-color0: var(--md-green-700); - --theia-success-color1: var(--md-green-500); --theia-success-color2: var(--md-green-300); - --theia-success-color3: var(--md-green-100); --theia-success-font-color0: var(--md-grey-300); --theia-info-color0: var(--md-cyan-700); --theia-info-color1: var(--md-cyan-500); - --theia-info-color2: var(--md-cyan-300); - --theia-info-color3: var(--md-cyan-100); --theia-info-font-color0: var(--md-grey-300); - --theia-disabled-color0: var(--md-grey-700); - --theia-disabled-color1: var(--md-grey-500); - --theia-disabled-color2: var(--md-grey-300); - --theia-disabled-color3: var(--md-grey-100); - - --theia-added-color0: rgba(0, 255, 0, 0.8); - --theia-removed-color0: rgba(230, 0, 0, 0.8); - --theia-modified-color0: rgba(0, 100, 150, 0.8); - - /* Background for selected text */ - --theia-selected-text-background: var(--theia-accent-color2); - /* Icons */ --theia-icon-close: url(../icons/close-dark.svg); --theia-sprite-y-offset: -20px; diff --git a/packages/extension-manager/src/browser/style/index.css b/packages/extension-manager/src/browser/style/index.css index 00a3d1e138bff..e2277637774ed 100644 --- a/packages/extension-manager/src/browser/style/index.css +++ b/packages/extension-manager/src/browser/style/index.css @@ -73,7 +73,7 @@ } .extensionButton.installed:hover { - background-color: var(--theia-error-color0); + background-color: var(--theia-errorBackground); } .extensionButton.outdated:hover { diff --git a/packages/markers/src/browser/problem/problem-decorator.ts b/packages/markers/src/browser/problem/problem-decorator.ts index ee10b5a9dfc42..0ec4933314abd 100644 --- a/packages/markers/src/browser/problem/problem-decorator.ts +++ b/packages/markers/src/browser/problem/problem-decorator.ts @@ -155,7 +155,7 @@ export class ProblemDecorator implements TreeDecorator { protected getOverlayIconColor(marker: Marker): TreeDecoration.Color { const { severity } = marker.data; switch (severity) { - case 1: return 'var(--theia-error-color0)'; + case 1: return 'var(--theia-errorBackground)'; case 2: return 'var(--theia-editorWarning-foreground)'; case 3: return 'var(--theia-info-color0)'; default: return 'var(--theia-success-color0)'; diff --git a/packages/markers/src/browser/problem/problem-tabbar-decorator.ts b/packages/markers/src/browser/problem/problem-tabbar-decorator.ts index 001ced2f20eba..8c29b533a6383 100644 --- a/packages/markers/src/browser/problem/problem-tabbar-decorator.ts +++ b/packages/markers/src/browser/problem/problem-tabbar-decorator.ts @@ -139,7 +139,7 @@ export class ProblemTabBarDecorator implements TabBarDecorator { protected getOverlayIconColor(marker: Marker): WidgetDecoration.Color { const { severity } = marker.data; switch (severity) { - case 1: return 'var(--theia-error-color0)'; + case 1: return 'var(--theia-errorBackground)'; case 2: return 'var(--theia-editorWarning-foreground)'; case 3: return 'var(--theia-info-color0)'; default: return 'var(--theia-success-color0)'; diff --git a/packages/markers/src/browser/style/index.css b/packages/markers/src/browser/style/index.css index ef8b90320761f..f1560f85cb1a5 100644 --- a/packages/markers/src/browser/style/index.css +++ b/packages/markers/src/browser/style/index.css @@ -53,7 +53,7 @@ } .theia-marker-container .error { - color: var(--theia-error-color0); + color: var(--theia-errorBackground); } .theia-marker-container .warning { diff --git a/packages/mini-browser/src/browser/style/index.css b/packages/mini-browser/src/browser/style/index.css index c979756b16891..add5e532afb78 100644 --- a/packages/mini-browser/src/browser/style/index.css +++ b/packages/mini-browser/src/browser/style/index.css @@ -143,8 +143,8 @@ .theia-mini-browser-error-bar { height: 19px; padding-left: var(--theia-ui-padding); - background-color: var(--theia-editorWarning-foreground); - color: var(--theia-warn-font-color0); + background-color: var(--theia-warningBackground); + color: var(--theia-inputValidation-infoForeground); font-size: var(--theia-statusBar-font-size); z-index: 1000; /* Above the transparent overlay (`z-index: 999;`). */ } diff --git a/packages/plugin-ext/src/main/style/status-bar.css b/packages/plugin-ext/src/main/style/status-bar.css index dfe58cf481310..587d13ff03c7d 100644 --- a/packages/plugin-ext/src/main/style/status-bar.css +++ b/packages/plugin-ext/src/main/style/status-bar.css @@ -19,7 +19,7 @@ } #theia-statusBar .development-host-offline { - background-color: var(--theia-error-color0); + background-color: var(--theia-errorBackground); } #theia-statusBar .hosted-plugin { @@ -31,5 +31,5 @@ } #theia-statusBar .hosted-plugin-failed { - background-color: var(--theia-error-color0); + background-color: var(--theia-errorBackground); } diff --git a/packages/scm/src/browser/style/index.css b/packages/scm/src/browser/style/index.css index 8b926c4a55742..5c762e5eca84b 100644 --- a/packages/scm/src/browser/style/index.css +++ b/packages/scm/src/browser/style/index.css @@ -63,7 +63,7 @@ } .theia-scm .warn { - background-color: var(--theia-error-color2) !important; + background-color: var(--theia-inputValidation-warningBackground) !important; } .theia-scm-main-container { @@ -140,13 +140,13 @@ .theia-scm-message-warning, .theia-scm-validation-message-warning { - background-color: var(--theia-editorWarning-foreground) !important; - color: var(--theia-warn-font-color0); + background-color: var(--theia-warningBackground) !important; + color: var(--theia-inputValidation-warningForeground); } .theia-scm-validation-message-error { - background-color: var(--theia-error-color0) !important; - color: var(--theia-error-font-color0); + background-color: var(--theia-errorBackground) !important; + color: var(--theia-errorForeground); } .no-select { diff --git a/packages/search-in-workspace/src/browser/styles/index.css b/packages/search-in-workspace/src/browser/styles/index.css index 68b1ef71883dd..f77aa68e991c8 100644 --- a/packages/search-in-workspace/src/browser/styles/index.css +++ b/packages/search-in-workspace/src/browser/styles/index.css @@ -127,13 +127,13 @@ } .t-siw-search-container .searchHeader .search-notification div{ - background-color: var(--theia-editorWarning-foreground); + background-color: var(--theia-warningBackground); width: calc(100% + 2px); margin-left: -1px; - color: var(--theia-warn-font-color0); + color: var(--theia-inputValidation-warningForeground); z-index: 1000; position: absolute; - border: 1px solid var(--theia-editorWarning-foreground); + border: 1px solid var(--theia-inputValidation-warningBorder); box-sizing: border-box; padding: 3px; } diff --git a/packages/typehierarchy/src/browser/tree/typehierarchy-tree.ts b/packages/typehierarchy/src/browser/tree/typehierarchy-tree.ts index 6e12d76dfa510..f7577b1b81208 100644 --- a/packages/typehierarchy/src/browser/tree/typehierarchy-tree.ts +++ b/packages/typehierarchy/src/browser/tree/typehierarchy-tree.ts @@ -174,7 +174,7 @@ export namespace TypeHierarchyTree { }); } const data = `${TypeHierarchyDirection.Children === direction ? 'â–¼' : 'â–²'}`; - const color = `var(${TypeHierarchyDirection.Children === direction ? '--theia-error-color2' : '--theia-success-color2'})`; + const color = `var(${TypeHierarchyDirection.Children === direction ? '--theia-errorForeground' : '--theia-success-color2'})`; return { captionSuffixes, captionPrefixes: [{ From 37608f6053cd5cd1894a17624e2b1ce1f29f47e7 Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Fri, 13 Dec 2019 17:16:50 +0000 Subject: [PATCH 47/65] [theming] remove old layout, branding and accent colors Signed-off-by: Anton Kosyakov --- .../browser/color-application-contribution.ts | 20 ++++++++ .../browser/frontend-application-module.ts | 2 + packages/core/src/browser/style/dialog.css | 2 +- packages/core/src/browser/style/dockpanel.css | 6 +-- packages/core/src/browser/style/index.css | 2 +- .../src/browser/style/quick-title-bar.css | 2 +- .../core/src/browser/style/search-box.css | 10 ++-- packages/core/src/browser/style/tabs.css | 5 -- packages/core/src/browser/style/tree.css | 2 +- .../style/variables-bright.useable.css | 47 ++----------------- .../browser/style/variables-dark.useable.css | 38 --------------- .../core/src/browser/style/view-container.css | 4 +- .../src/browser/style/extension-detail.css | 3 -- .../src/browser/style/extension-sidebar.css | 7 --- .../src/browser/style/index.css | 9 ---- packages/keymaps/src/browser/style/index.css | 11 +---- .../src/browser/problem/problem-decorator.ts | 2 +- .../problem/problem-tabbar-decorator.ts | 2 +- .../mini-browser/src/browser/style/index.css | 2 +- .../src/browser/monaco-theming-service.ts | 17 +++++-- packages/monaco/src/browser/style/index.css | 21 +-------- .../dialogs/style/modal-notification.css | 2 +- .../src/main/browser/style/plugin-sidebar.css | 2 +- .../src/main/browser/style/tree.css | 8 ---- .../src/browser/markdown/style/markdown.css | 42 ++++++++++++----- .../src/browser/style/scm-amend-component.css | 3 +- .../src/browser/styles/index.css | 6 +-- .../src/browser/tree/typehierarchy-tree.ts | 2 +- 28 files changed, 98 insertions(+), 181 deletions(-) diff --git a/packages/core/src/browser/color-application-contribution.ts b/packages/core/src/browser/color-application-contribution.ts index 398339a7231ed..3dfee669d19d7 100644 --- a/packages/core/src/browser/color-application-contribution.ts +++ b/packages/core/src/browser/color-application-contribution.ts @@ -39,11 +39,16 @@ export class ColorApplicationContribution implements FrontendApplicationContribu @inject(ContributionProvider) @named(ColorContribution) protected readonly colorContributions: ContributionProvider; + private static themeBackgroundId = 'theme.background'; + onStart(): void { for (const contribution of this.colorContributions.getContributions()) { contribution.registerColors(this.colors); } + this.updateThemeBackground(); + ThemeService.get().onThemeChange(() => this.updateThemeBackground()); + this.update(); ThemeService.get().onThemeChange(() => this.update()); this.colors.onDidChange(() => this.update()); @@ -73,4 +78,19 @@ export class ColorApplicationContribution implements FrontendApplicationContribu this.onDidChangeEmitter.fire(undefined); } + protected updateThemeBackground(): void { + const color = this.colors.getCurrentColor('editor.background'); + if (color) { + window.localStorage.setItem(ColorApplicationContribution.themeBackgroundId, color); + } else { + window.localStorage.removeItem(ColorApplicationContribution.themeBackgroundId); + } + } + + static initBackground(): void { + const value = window.localStorage.getItem(this.themeBackgroundId) || '#1d1d1d'; + const documentElement = document.documentElement; + documentElement.style.setProperty('--theia-editor-background', value); + } + } diff --git a/packages/core/src/browser/frontend-application-module.ts b/packages/core/src/browser/frontend-application-module.ts index bbcdae6668274..25681e2412ba2 100644 --- a/packages/core/src/browser/frontend-application-module.ts +++ b/packages/core/src/browser/frontend-application-module.ts @@ -92,6 +92,8 @@ import { TreeLabelProvider } from './tree/tree-label-provider'; export { bindResourceProvider, bindMessageService, bindPreferenceService }; +ColorApplicationContribution.initBackground(); + export const frontendApplicationModule = new ContainerModule((bind, unbind, isBound, rebind) => { const themeService = ThemeService.get(); themeService.register(...BuiltinThemeProvider.themes); diff --git a/packages/core/src/browser/style/dialog.css b/packages/core/src/browser/style/dialog.css index 36fbf04efb972..abac64c4144d3 100644 --- a/packages/core/src/browser/style/dialog.css +++ b/packages/core/src/browser/style/dialog.css @@ -79,7 +79,7 @@ } .dialogOverlay :focus { - box-shadow: 0px 0px 1px 1px var(--theia-accent-color3); + box-shadow: 0px 0px 1px 1px var(--theia-focusBorder); outline: none; } diff --git a/packages/core/src/browser/style/dockpanel.css b/packages/core/src/browser/style/dockpanel.css index dc07695ed6d6d..e633647893ae6 100644 --- a/packages/core/src/browser/style/dockpanel.css +++ b/packages/core/src/browser/style/dockpanel.css @@ -18,10 +18,6 @@ padding: 0px; } -.p-SplitPanel-handle { - background: var(--theia-layout-color1); -} - .p-DockPanel-widget { min-width: 100px; min-height: 100px; @@ -37,7 +33,7 @@ .p-DockPanel-overlay { background: var(--theia-editorGroup-dropBackground); - border: var(--theia-border-width) dashed var(--theia-brand-color1); + border: var(--theia-border-width) dashed var(--theia-contrastActiveBorder); transition-property: top, left, right, bottom; transition-duration: 150ms; transition-timing-function: ease; diff --git a/packages/core/src/browser/style/index.css b/packages/core/src/browser/style/index.css index 819726708c2ac..8373fc028f7d5 100644 --- a/packages/core/src/browser/style/index.css +++ b/packages/core/src/browser/style/index.css @@ -94,7 +94,7 @@ blockquote { right: 0; bottom: 0; z-index: 50000; - background: var(--theia-layout-color0); + background: var(--theia-editor-background); background-image: var(--theia-preloader); background-size: 60px 60px; background-repeat: no-repeat; diff --git a/packages/core/src/browser/style/quick-title-bar.css b/packages/core/src/browser/style/quick-title-bar.css index 2bcd044d5fa14..7a32fd2c1c332 100644 --- a/packages/core/src/browser/style/quick-title-bar.css +++ b/packages/core/src/browser/style/quick-title-bar.css @@ -19,7 +19,7 @@ padding: calc(var(--theia-ui-padding)/2); justify-content: space-between; align-items: center; - background: var(--theia-layout-color4); + background: var(--theia-titleBar-activeBackground); } .theia-quick-title-left-bar { diff --git a/packages/core/src/browser/style/search-box.css b/packages/core/src/browser/style/search-box.css index 497de88dcca2a..5a7a7a3765476 100644 --- a/packages/core/src/browser/style/search-box.css +++ b/packages/core/src/browser/style/search-box.css @@ -48,9 +48,15 @@ content: "\f107"; } +.theia-search-button-next:hover, +.theia-search-button-previous:hover, +.theia-search-button-close:hover { + cursor: pointer; + background-color: var(--theia-editorHoverWidget-background); +} + .theia-search-button-next:hover:before { content: "\f107"; - background-color: var(--theia-layout-color2); } .theia-search-button-previous:before { @@ -59,7 +65,6 @@ .theia-search-button-previous:hover:before { content: "\f106"; - background-color: var(--theia-layout-color2); } .theia-search-button-close:before { @@ -68,7 +73,6 @@ .theia-search-button-close:hover:before { content: "\f00d"; - background-color: var(--theia-layout-color2); } .theia-non-selectable { diff --git a/packages/core/src/browser/style/tabs.css b/packages/core/src/browser/style/tabs.css index a5144388f26b5..edb623c8e9b2c 100644 --- a/packages/core/src/browser/style/tabs.css +++ b/packages/core/src/browser/style/tabs.css @@ -33,7 +33,6 @@ min-width: 35px; line-height: var(--theia-private-horizontal-tab-height); padding: 0px 8px; - background: var(--theia-layout-color2); align-items: center; } @@ -44,10 +43,6 @@ align-items: center; } -.p-TabBar[data-orientation='horizontal'] .p-TabBar-tab:hover:not(.p-mod-current) { - background: var(--theia-accent-color3); -} - /*----------------------------------------------------------------------------- | Tabs in the center area (main and bottom) diff --git a/packages/core/src/browser/style/tree.css b/packages/core/src/browser/style/tree.css index 04b824ae43bf4..5b1965204fef6 100644 --- a/packages/core/src/browser/style/tree.css +++ b/packages/core/src/browser/style/tree.css @@ -26,7 +26,7 @@ outline-style: solid; outline-offset: -1px; opacity: 1 !important; - outline-color: var(--theia-accent-color3); + outline-color: var(--theia-focusBorder); } .theia-Tree:focus, diff --git a/packages/core/src/browser/style/variables-bright.useable.css b/packages/core/src/browser/style/variables-bright.useable.css index bc43769398917..34f8679847c0c 100644 --- a/packages/core/src/browser/style/variables-bright.useable.css +++ b/packages/core/src/browser/style/variables-bright.useable.css @@ -19,13 +19,13 @@ is not optimized for dense, information rich UIs. :root { - /* Borders: Width and color (bright to dark) */ + /* Borders */ --theia-border-width: 1px; --theia-panel-border-width: 2px; - /* UI fonts: Family, size and color (dark to bright) + /* UI fonts --------------------------------------------------- The UI font CSS variables are used for the typography all of the Theia user interface elements that are not directly user-generated content. @@ -39,7 +39,7 @@ is not optimized for dense, information rich UIs. --theia-ui-icon-font-size: 14px; /* Ensures px perfect FontAwesome icons */ --theia-ui-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - /* Content fonts: Family, size and color (dark to bright) + /* Content fonts Content font variables are used for typography of user-generated content. */ @@ -53,44 +53,6 @@ is not optimized for dense, information rich UIs. --theia-terminal-font-family: monospace; --theia-ui-padding: 6px; - /* Main layout colors (bright to dark) - ------------------------------------ */ - - --theia-layout-color0: #ffffff; - --theia-layout-color1: #f3f3f3; - --theia-layout-color2: #ececec; - --theia-layout-color3: #dcdcdc; - --theia-layout-color4: #dcdcdc; - - /* Brand colors */ - - --theia-brand-color0: var(--md-blue-700); - --theia-brand-color1: var(--md-blue-500); - --theia-brand-color2: var(--md-blue-300); - --theia-brand-color3: var(--md-blue-100); - - /* Secondary Brand colors */ - - --theia-secondary-brand-color0: var(--md-grey-700); - --theia-secondary-brand-color1: var(--md-grey-500); - --theia-secondary-brand-color2: var(--md-grey-300); - --theia-secondary-brand-color3: var(--md-grey-100); - - /* Accent colors (dark to bright): Use these to create contrast to layout colors. */ - - --theia-accent-color0: var(--md-blue-900); - --theia-accent-color1: #2b75c0; - --theia-accent-color2: #4496da; - --theia-accent-color3: #c0dbf1; - --theia-accent-color4: #d7eaf8; - - /* Accent colors with opacity */ - - --theia-transparent-accent-color0: hsla(210, 63%, 46%, 0.3); - --theia-transparent-accent-color1: hsla(207, 66%, 56%, 0.3); - --theia-transparent-accent-color2: hsla(207, 64%, 85%, 0.3); - --theia-transparent-accent-color3: hsla(205, 70%, 91%, 0.3); - /* State colors (warn, error, success, info) ------------------------------------------ */ @@ -104,9 +66,6 @@ is not optimized for dense, information rich UIs. --theia-info-font-color0: var(--md-grey-300); - /* Background for selected text */ - --theia-selected-text-background: var(--theia-accent-color3); - /* Icons */ --theia-icon-close: url(../icons/close-bright.svg); --theia-sprite-y-offset: 0px; diff --git a/packages/core/src/browser/style/variables-dark.useable.css b/packages/core/src/browser/style/variables-dark.useable.css index 74c68a4003344..27f54557893fc 100644 --- a/packages/core/src/browser/style/variables-dark.useable.css +++ b/packages/core/src/browser/style/variables-dark.useable.css @@ -53,44 +53,6 @@ is not optimized for dense, information rich UIs. --theia-terminal-font-family: monospace; --theia-ui-padding: 6px; - /* Main layout colors (dark to bright) - ------------------------------------ */ - - --theia-layout-color0: #1d1d1d; - --theia-layout-color1: #252526; - --theia-layout-color2: #333333; - --theia-layout-color3: #383838; - --theia-layout-color4: #383838; - - /* Brand colors */ - - --theia-brand-color0: var(--md-blue-700); - --theia-brand-color1: var(--md-blue-500); - --theia-brand-color2: var(--md-blue-300); - --theia-brand-color3: var(--md-blue-100); - - /* Secondary Brand colors */ - - --theia-secondary-brand-color0: var(--md-grey-700); - --theia-secondary-brand-color1: var(--md-grey-600); - --theia-secondary-brand-color2: var(--md-grey-400); - --theia-secondary-brand-color3: var(--md-grey-200); - - /* Accent colors (bright to dark): Use these to create contrast to layout colors. */ - - --theia-accent-color0: var(--md-light-blue-300); - --theia-accent-color1: #259fd8; - --theia-accent-color2: #217daf; - --theia-accent-color3: #265f8a; - --theia-accent-color4: #24455e; - - /* Accent colors with opacity */ - - --theia-transparent-accent-color0: hsla(199, 71%, 50%, 0.3); - --theia-transparent-accent-color1: hsla(201, 68%, 41%, 0.3); - --theia-transparent-accent-color2: hsla(206, 57%, 35%, 0.3); - --theia-transparent-accent-color3: hsla(206, 45%, 25%, 0.3); - /* State colors (warn, error, success, info) ------------------------------------------ */ diff --git a/packages/core/src/browser/style/view-container.css b/packages/core/src/browser/style/view-container.css index f6ef78858704e..c70a7cec57a4b 100644 --- a/packages/core/src/browser/style/view-container.css +++ b/packages/core/src/browser/style/view-container.css @@ -96,8 +96,8 @@ } .theia-view-container .part.drop-target { - background: rgba(33, 150, 243, 0.1); - border: var(--theia-border-width) dashed var(--theia-brand-color1); + background: var(--theia-sideBar-dropBackground); + border: var(--theia-border-width) dashed var(--theia-contrastActiveBorder); transition-property: top, left, right, bottom; transition-duration: 150ms; transition-timing-function: ease; diff --git a/packages/extension-manager/src/browser/style/extension-detail.css b/packages/extension-manager/src/browser/style/extension-detail.css index 8513b2a35f65e..4b31a8db876d8 100644 --- a/packages/extension-manager/src/browser/style/extension-detail.css +++ b/packages/extension-manager/src/browser/style/extension-detail.css @@ -20,7 +20,6 @@ } .theia-extension-detail .extensionHeaderContainer { - background: var(--theia-layout-color0); padding: 15px 22px; } @@ -72,7 +71,6 @@ .theia-extension-detail a { font-weight: bold; - color: var(--theia-accent-color0); } .theia-extension-detail code { @@ -83,7 +81,6 @@ } .theia-extension-detail pre code { - background: var(--theia-layout-color2); display: block; padding: 10px; } diff --git a/packages/extension-manager/src/browser/style/extension-sidebar.css b/packages/extension-manager/src/browser/style/extension-sidebar.css index c9c8c07746da1..07e7a85fc1a7e 100644 --- a/packages/extension-manager/src/browser/style/extension-sidebar.css +++ b/packages/extension-manager/src/browser/style/extension-sidebar.css @@ -16,7 +16,6 @@ .theia-extensions { min-width: 250px !important; - background-color: var(--theia-layout-color0); display: flex; flex-direction: column; } @@ -41,7 +40,6 @@ line-height: var(--theia-content-line-height); border-width: 1px; border-style: solid; - background: var(--theia-layout-color2); padding-left: 5px; } @@ -55,17 +53,12 @@ .theia-extensions .extensionHeaderContainer { padding: 3px 15px; font-size: var(--theia-ui-font-size0); - background: var(--theia-layout-color0); } .theia-side-panel .theia-extensions .extensionHeaderContainer { padding-left: 20px; } -.theia-extensions .extensionHeaderContainer:hover { - background: var(--theia-layout-color2); -} - .theia-extensions .extensionHeaderContainer .row { margin: 3px 0; } diff --git a/packages/extension-manager/src/browser/style/index.css b/packages/extension-manager/src/browser/style/index.css index e2277637774ed..81a2f13e875d9 100644 --- a/packages/extension-manager/src/browser/style/index.css +++ b/packages/extension-manager/src/browser/style/index.css @@ -36,7 +36,6 @@ } .extensionHeaderContainer { - background: var(--theia-layout-color1); margin-bottom: 5px; } @@ -68,17 +67,9 @@ background-color: var(--theia-editorError-foreground); } -.extensionButton.outdated { - background-color: var(--theia-accent-color2); -} - .extensionButton.installed:hover { background-color: var(--theia-errorBackground); } -.extensionButton.outdated:hover { - background-color: var(--theia-accent-color1); -} - @import './extension-sidebar.css'; @import './extension-detail.css'; diff --git a/packages/keymaps/src/browser/style/index.css b/packages/keymaps/src/browser/style/index.css index 6ee5ec8c22fbb..9cfe8459e1fb0 100644 --- a/packages/keymaps/src/browser/style/index.css +++ b/packages/keymaps/src/browser/style/index.css @@ -101,7 +101,7 @@ } .kb table tbody tr:hover { - background-color: var(--theia-accent-color4); + background-color: var(--theia-list-focusBackground); } .kb table tbody tr:hover .kb-action-item { @@ -118,7 +118,7 @@ vertical-align: middle; position: sticky; top: 0; - background-color: var(--theia-layout-color2); + background-color: var(--theia-editorWidget-background); } .kb table .th-action { @@ -148,13 +148,6 @@ justify-content: center; } -.monaco-keybinding-key { - background-color: var(--theia-layout-color2) !important; - border: none !important; - border-bottom-color: var(--theia-layout-color3) !important; - font-size: 12px !important; -} - .no-kb { border: 1px solid var(--theia-editorWarning-foreground); } diff --git a/packages/markers/src/browser/problem/problem-decorator.ts b/packages/markers/src/browser/problem/problem-decorator.ts index 0ec4933314abd..d5fc8b6d7480f 100644 --- a/packages/markers/src/browser/problem/problem-decorator.ts +++ b/packages/markers/src/browser/problem/problem-decorator.ts @@ -136,7 +136,7 @@ export class ProblemDecorator implements TreeDecorator { color, background: { shape: 'circle', - color: 'var(--theia-layout-color0)' + color: 'transparent' } } }; diff --git a/packages/markers/src/browser/problem/problem-tabbar-decorator.ts b/packages/markers/src/browser/problem/problem-tabbar-decorator.ts index 8c29b533a6383..ad857da64af6a 100644 --- a/packages/markers/src/browser/problem/problem-tabbar-decorator.ts +++ b/packages/markers/src/browser/problem/problem-tabbar-decorator.ts @@ -110,7 +110,7 @@ export class ProblemTabBarDecorator implements TabBarDecorator { color, background: { shape: 'circle', - color: 'var(--theia-layout-color0)' + color: 'transparent' } } }; diff --git a/packages/mini-browser/src/browser/style/index.css b/packages/mini-browser/src/browser/style/index.css index add5e532afb78..aec6047572d5b 100644 --- a/packages/mini-browser/src/browser/style/index.css +++ b/packages/mini-browser/src/browser/style/index.css @@ -128,7 +128,7 @@ bottom: 0; left: 0; z-index: 10; - background: var(--theia-layout-color3); + background: var(--theia-editor-background); background-image: var(--theia-preloader); background-size: 60px 60px; background-repeat: no-repeat; diff --git a/packages/monaco/src/browser/monaco-theming-service.ts b/packages/monaco/src/browser/monaco-theming-service.ts index 117c63c86fb54..d7eb341471845 100644 --- a/packages/monaco/src/browser/monaco-theming-service.ts +++ b/packages/monaco/src/browser/monaco-theming-service.ts @@ -120,9 +120,11 @@ export class MonacoThemingService { } static init(): void { - ThemeService.get().onThemeChange(e => - MonacoThemingService.store(MonacoThemingService.monacoThemes.get(e.newTheme.id)) - ); + this.updateBodyUiTheme(); + ThemeService.get().onThemeChange(e => { + this.updateBodyUiTheme(); + MonacoThemingService.store(MonacoThemingService.monacoThemes.get(e.newTheme.id)); + }); try { const value = window.localStorage.getItem('monacoTheme'); if (value) { @@ -135,6 +137,15 @@ export class MonacoThemingService { } } + protected static toUpdateUiTheme = new DisposableCollection(); + protected static updateBodyUiTheme(): void { + this.toUpdateUiTheme.dispose(); + const type = ThemeService.get().getCurrentTheme().type; + const uiTheme: MonacoTheme['uiTheme'] = type === 'hc' ? 'hc-black' : type === 'light' ? 'vs' : 'vs-dark'; + document.body.classList.add(uiTheme); + this.toUpdateUiTheme.push(Disposable.create(() => document.body.classList.remove(uiTheme))); + } + static store(state: MonacoThemingService.MonacoThemeState | undefined): void { if (state) { window.localStorage.setItem('monacoTheme', JSON.stringify(state)); diff --git a/packages/monaco/src/browser/style/index.css b/packages/monaco/src/browser/style/index.css index 7512eb7984890..60bfd6411f74b 100644 --- a/packages/monaco/src/browser/style/index.css +++ b/packages/monaco/src/browser/style/index.css @@ -4,18 +4,6 @@ font-size: inherit !important; } -.monaco-editor, .monaco-editor-background { - background: var(--theia-layout-color0); -} - -.monaco-editor .margin { - background: var(--theia-layout-color0); -} - -.monaco-keybinding-key { - color: var(--theia-quickInput-foreground) !important; -} - /* * set z-index to 0, so tabs are not above overlay widgets */ @@ -41,12 +29,7 @@ color: var(--theia-quickInput-foreground) !important; } -.quick-open-entry .quick-open-row .monaco-icon-label .monaco-icon-label-description-container .monaco-highlighted-label .highlight { - color: var(--theia-accent-color1); -} - .quick-open-entry .quick-open-row .monaco-icon-label .monaco-icon-label-description-container .label-description { - color: var(--theia-descriptionForeground); font-size: calc(var(--theia-ui-font-size0) * 0.95); } @@ -60,8 +43,8 @@ border-bottom-style: solid; border-top-width: 0; border-bottom-width: 0; - border-top-color: var(--theia-accent-color2); - border-bottom-color: var(--theia-accent-color2); + border-top-color: var(--theia-peekView-border); + border-bottom-color: var(--theia-peekView-border); position: relative; } diff --git a/packages/plugin-ext/src/main/browser/dialogs/style/modal-notification.css b/packages/plugin-ext/src/main/browser/dialogs/style/modal-notification.css index e5d7a9df7dc0d..432d7cf0feed6 100644 --- a/packages/plugin-ext/src/main/browser/dialogs/style/modal-notification.css +++ b/packages/plugin-ext/src/main/browser/dialogs/style/modal-notification.css @@ -46,7 +46,7 @@ line-height: inherit; vertical-align: middle; font-size: 120%; - color: var(--theia-accent-color2); + color: var(--theia-editorInfo-foreground); } .modal-Notification .icon .error { diff --git a/packages/plugin-ext/src/main/browser/style/plugin-sidebar.css b/packages/plugin-ext/src/main/browser/style/plugin-sidebar.css index c8f89b8a39e45..5f74fc26187e6 100644 --- a/packages/plugin-ext/src/main/browser/style/plugin-sidebar.css +++ b/packages/plugin-ext/src/main/browser/style/plugin-sidebar.css @@ -38,7 +38,7 @@ } .theia-plugins .pluginHeaderContainer:hover { - background: var(--theia-layout-color2); + background: var(--theia-list-hoverBackground); } .theia-plugins .pluginHeaderContainer .row { diff --git a/packages/plugin-ext/src/main/browser/style/tree.css b/packages/plugin-ext/src/main/browser/style/tree.css index 43566e3ba9d05..8811d44f58807 100644 --- a/packages/plugin-ext/src/main/browser/style/tree.css +++ b/packages/plugin-ext/src/main/browser/style/tree.css @@ -14,14 +14,6 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ -.theia-TreeNodeHyperlink { - color: var(--theia-accent-color1); -} - -.theia-TreeNodeHyperlink:focus { - border: none; -} - .theia-tree-view-icon { padding-right: var(--theia-ui-padding); -webkit-font-smoothing: antialiased; diff --git a/packages/preview/src/browser/markdown/style/markdown.css b/packages/preview/src/browser/markdown/style/markdown.css index edf356e212992..6bae2da9624d5 100644 --- a/packages/preview/src/browser/markdown/style/markdown.css +++ b/packages/preview/src/browser/markdown/style/markdown.css @@ -63,12 +63,10 @@ } .markdown-preview a { - color: var(--theia-accent-color1); text-decoration: none; } .markdown-preview a:hover { - color: var(--theia-accent-color1); text-decoration: underline; } @@ -136,8 +134,8 @@ margin: 0 7px 0 5px; padding: 0 16px 0 10px; border-left: 5px solid; - background: var(--theia-accent-color4); - border-color: var(--theia-brand-color2); + background: var(--theia-textBlockQuote-background); + border-color: var(--theia-textBlockQuote-border); } .markdown-preview code { @@ -161,17 +159,33 @@ .markdown-preview, .markdown-preview pre code { color: var(--theia-editor-foreground); + tab-size: 4; } -.markdown-preview pre:not(.hljs), -.markdown-preview code > div { - background-color: var(--theia-accent-color4); +/** Theming */ + +.theia-light .markdown-preview pre { + background-color: rgba(220, 220, 220, 0.4); } -.markdown-preview h1, -.markdown-preview hr, -.markdown-preview table > tbody > tr + tr > td { - border-color: rgba(255, 255, 255, 0.18); +.theia-dark .markdown-preview pre { + background-color: rgba(10, 10, 10, 0.4); +} + +.theia-high-contrast .markdown-preview pre { + background-color: rgb(0, 0, 0); +} + +.vscode-high-contrast .markdown-preview h1 { + border-color: rgb(0, 0, 0); +} + +.theia-light .markdown-preview table > thead > tr > th { + border-color: rgba(0, 0, 0, 0.69); +} + +.theia-dark .markdown-preview table > thead > tr > th { + border-color: rgba(255, 255, 255, 0.69); } .theia-light .markdown-preview h1, @@ -179,3 +193,9 @@ .theia-light .markdown-preview table > tbody > tr + tr > td { border-color: rgba(0, 0, 0, 0.18); } + +.theia-dark .markdown-preview h1, +.theia-dark .markdown-preview hr, +.theia-dark .markdown-preview table > tbody > tr + tr > td { + border-color: rgba(255, 255, 255, 0.18); +} diff --git a/packages/scm/src/browser/style/scm-amend-component.css b/packages/scm/src/browser/style/scm-amend-component.css index c278fbab0044c..2cd72fcf8cec0 100644 --- a/packages/scm/src/browser/style/scm-amend-component.css +++ b/packages/scm/src/browser/style/scm-amend-component.css @@ -17,7 +17,7 @@ .theia-scm-commit-container { display: flex; flex-direction: column; - border-top: 1px solid var(--theia-layout-color4); + border-top: 1px solid var(--theia-sideBarSectionHeader-border); width: 100%; padding-top: 6px; } @@ -25,7 +25,6 @@ .theia-scm-amend-outer-container { display: flex; flex-direction: column; - border-top: 1px dotted var(--theia-layout-color4); width: 100%; overflow: auto; } diff --git a/packages/search-in-workspace/src/browser/styles/index.css b/packages/search-in-workspace/src/browser/styles/index.css index f77aa68e991c8..ff33c3b4767bc 100644 --- a/packages/search-in-workspace/src/browser/styles/index.css +++ b/packages/search-in-workspace/src/browser/styles/index.css @@ -322,7 +322,7 @@ } .replace-toggle:hover { - background: var(--theia-layout-color2); + background: rgba(0, 0, 0, 0.1); } .search-and-replace-fields { @@ -373,8 +373,8 @@ } .highlighted-count-container { - background-color: var(--theia-brand-color0); - color: #ffffff; + background-color: var(--theia-list-activeSelectionBackground); + color: var(--theia-list-activeSelectionForeground); } .t-siw-search-container .searchHeader .search-info { diff --git a/packages/typehierarchy/src/browser/tree/typehierarchy-tree.ts b/packages/typehierarchy/src/browser/tree/typehierarchy-tree.ts index f7577b1b81208..6383a47bf5888 100644 --- a/packages/typehierarchy/src/browser/tree/typehierarchy-tree.ts +++ b/packages/typehierarchy/src/browser/tree/typehierarchy-tree.ts @@ -168,7 +168,7 @@ export namespace TypeHierarchyTree { captionSuffixes.unshift({ data: item.detail, fontData: { - color: 'var(--theia-accent-color0)', + color: 'var(--theia-list-highlightForeground)', style: 'italic' } }); From c5735ee1e5b234598a9a3bb7f88891c60a26bfa2 Mon Sep 17 00:00:00 2001 From: Jan Bicker Date: Mon, 16 Dec 2019 14:57:33 +0000 Subject: [PATCH 48/65] Replaced old color variables for States with VSCode Theme colors --- .../browser/common-frontend-contribution.ts | 22 +++---------------- .../core/src/browser/style/alert-messages.css | 19 +++++----------- packages/core/src/browser/style/index.css | 4 ---- .../style/variables-bright.useable.css | 13 ----------- .../browser/style/variables-dark.useable.css | 13 ----------- .../src/browser/problem/problem-decorator.ts | 6 ++--- .../problem/problem-tabbar-decorator.ts | 6 ++--- packages/markers/src/browser/style/index.css | 6 ++--- .../mini-browser/src/browser/style/index.css | 4 ++-- .../plugin-ext/src/main/style/status-bar.css | 6 ++--- packages/scm/src/browser/style/index.css | 14 ++++++------ .../src/browser/styles/index.css | 4 ++-- .../src/browser/tree/typehierarchy-tree.ts | 2 +- 13 files changed, 33 insertions(+), 86 deletions(-) diff --git a/packages/core/src/browser/common-frontend-contribution.ts b/packages/core/src/browser/common-frontend-contribution.ts index 11e9d08067bc5..b8e90b7af81d0 100644 --- a/packages/core/src/browser/common-frontend-contribution.ts +++ b/packages/core/src/browser/common-frontend-contribution.ts @@ -1436,30 +1436,14 @@ export class CommonFrontendContribution implements FrontendApplicationContributi hc: 'inputValidation.errorBackground' }, description: 'Background color of error widgets (like alerts or notifications).' }, - { - id: 'warningBackground', - defaults: { - dark: 'inputValidation.warningBackground', - light: 'inputValidation.warningBackground', - hc: 'inputValidation.warningBackground' - }, description: 'Background color of warn widgets (like alerts or notifications).' - }, { id: 'successBackground', defaults: { - dark: 'gitDecoration.untrackedResourceForeground', - light: 'gitDecoration.untrackedResourceForeground', - hc: 'gitDecoration.untrackedResourceForeground' + dark: 'editorGutter.addedBackground', + light: 'editorGutter.addedBackground', + hc: 'editorGutter.addedBackground' }, description: 'Background color of success widgets (like alerts or notifications).' }, - { - id: 'infoBackground', - defaults: { - dark: 'inputValidation.infoBackground', - light: 'inputValidation.infoBackground', - hc: 'inputValidation.infoBackground' - }, description: 'Background color of info widgets (like alerts or notifications).' - }, // Buttons { id: 'secondaryButton.foreground', diff --git a/packages/core/src/browser/style/alert-messages.css b/packages/core/src/browser/style/alert-messages.css index 6b3bbf212b4d6..ee128b5fc82ba 100644 --- a/packages/core/src/browser/style/alert-messages.css +++ b/packages/core/src/browser/style/alert-messages.css @@ -26,28 +26,21 @@ /* information message */ .theia-info-alert { - background-color: var(--theia-infoBackground); - color: #ffffff; - padding: 10px; -} - -/* success message */ -.theia-success-alert { - background-color: var(--theia-successBackground); - color: #ffffff; + background-color: var(--theia-inputValidation-infoBackground); + color: var(--theia-editor-foreground); padding: 10px; } /* warning message */ .theia-warning-alert { - background-color: var(--theia-inputValidation-warningBackground); - color: var(--theia-inputValidation-warningForeground); + background-color: var(--theia-editorWarning-foreground); + color: var(--theia-inputValidation-warningBackground); padding: 10px; } /* error message */ .theia-error-alert { - background-color: var(--theia-errorBackground); - color: #ffffff; + background-color: var(--theia-inputValidation-errorBorder); + color: var(--theia-editor-foreground); padding: 10px; } diff --git a/packages/core/src/browser/style/index.css b/packages/core/src/browser/style/index.css index 8373fc028f7d5..d413d4648e807 100644 --- a/packages/core/src/browser/style/index.css +++ b/packages/core/src/browser/style/index.css @@ -128,10 +128,6 @@ blockquote { font-size: var(--theia-ui-font-size1); } -.p-Widget .error { - color: var(--theia-errorForeground); -} - .p-Widget.p-mod-hidden { display: none !important; } diff --git a/packages/core/src/browser/style/variables-bright.useable.css b/packages/core/src/browser/style/variables-bright.useable.css index 34f8679847c0c..e6c21cc8dccd6 100644 --- a/packages/core/src/browser/style/variables-bright.useable.css +++ b/packages/core/src/browser/style/variables-bright.useable.css @@ -53,19 +53,6 @@ is not optimized for dense, information rich UIs. --theia-terminal-font-family: monospace; --theia-ui-padding: 6px; - /* State colors (warn, error, success, info) - ------------------------------------------ */ - - --theia-success-color0: var(--md-green-500); - --theia-success-color2: var(--md-green-100); - - --theia-success-font-color0: var(--md-grey-300); - - --theia-info-color0: var(--md-cyan-700); - --theia-info-color1: var(--md-cyan-500); - - --theia-info-font-color0: var(--md-grey-300); - /* Icons */ --theia-icon-close: url(../icons/close-bright.svg); --theia-sprite-y-offset: 0px; diff --git a/packages/core/src/browser/style/variables-dark.useable.css b/packages/core/src/browser/style/variables-dark.useable.css index 27f54557893fc..594463094eda5 100644 --- a/packages/core/src/browser/style/variables-dark.useable.css +++ b/packages/core/src/browser/style/variables-dark.useable.css @@ -53,19 +53,6 @@ is not optimized for dense, information rich UIs. --theia-terminal-font-family: monospace; --theia-ui-padding: 6px; - /* State colors (warn, error, success, info) - ------------------------------------------ */ - - --theia-success-color0: var(--md-green-700); - --theia-success-color2: var(--md-green-300); - - --theia-success-font-color0: var(--md-grey-300); - - --theia-info-color0: var(--md-cyan-700); - --theia-info-color1: var(--md-cyan-500); - - --theia-info-font-color0: var(--md-grey-300); - /* Icons */ --theia-icon-close: url(../icons/close-dark.svg); --theia-sprite-y-offset: -20px; diff --git a/packages/markers/src/browser/problem/problem-decorator.ts b/packages/markers/src/browser/problem/problem-decorator.ts index d5fc8b6d7480f..d29fc26ea9747 100644 --- a/packages/markers/src/browser/problem/problem-decorator.ts +++ b/packages/markers/src/browser/problem/problem-decorator.ts @@ -155,10 +155,10 @@ export class ProblemDecorator implements TreeDecorator { protected getOverlayIconColor(marker: Marker): TreeDecoration.Color { const { severity } = marker.data; switch (severity) { - case 1: return 'var(--theia-errorBackground)'; + case 1: return 'var(--theia-editorError-foreground)'; case 2: return 'var(--theia-editorWarning-foreground)'; - case 3: return 'var(--theia-info-color0)'; - default: return 'var(--theia-success-color0)'; + case 3: return 'var(--theia-editorInfo-foreground)'; + default: return 'var(--theia-successBackground)'; } } diff --git a/packages/markers/src/browser/problem/problem-tabbar-decorator.ts b/packages/markers/src/browser/problem/problem-tabbar-decorator.ts index ad857da64af6a..fd9aca7efe26b 100644 --- a/packages/markers/src/browser/problem/problem-tabbar-decorator.ts +++ b/packages/markers/src/browser/problem/problem-tabbar-decorator.ts @@ -139,10 +139,10 @@ export class ProblemTabBarDecorator implements TabBarDecorator { protected getOverlayIconColor(marker: Marker): WidgetDecoration.Color { const { severity } = marker.data; switch (severity) { - case 1: return 'var(--theia-errorBackground)'; + case 1: return 'var(--theia-editorError-foreground)'; case 2: return 'var(--theia-editorWarning-foreground)'; - case 3: return 'var(--theia-info-color0)'; - default: return 'var(--theia-success-color0)'; + case 3: return 'var(--theia-editorInfo-foreground)'; + default: return 'var(--theia-successBackground)'; } } diff --git a/packages/markers/src/browser/style/index.css b/packages/markers/src/browser/style/index.css index f1560f85cb1a5..0e07a50de5814 100644 --- a/packages/markers/src/browser/style/index.css +++ b/packages/markers/src/browser/style/index.css @@ -53,7 +53,7 @@ } .theia-marker-container .error { - color: var(--theia-errorBackground); + color: var(--theia-editorError-foreground); } .theia-marker-container .warning { @@ -61,11 +61,11 @@ } .theia-marker-container .information { - color: var(--theia-info-color0); + color: var(--theia-editorInfo-foreground); } .theia-marker-container .hint { - color: var(--theia-success-color0); + color: var(--theia-successBackground); } .theia-marker-container .markerNode .position, diff --git a/packages/mini-browser/src/browser/style/index.css b/packages/mini-browser/src/browser/style/index.css index aec6047572d5b..d42f508cfee51 100644 --- a/packages/mini-browser/src/browser/style/index.css +++ b/packages/mini-browser/src/browser/style/index.css @@ -143,8 +143,8 @@ .theia-mini-browser-error-bar { height: 19px; padding-left: var(--theia-ui-padding); - background-color: var(--theia-warningBackground); - color: var(--theia-inputValidation-infoForeground); + background-color: var(--theia-inputValidation-errorBorder); + color: var(--theia-editor-foreground); font-size: var(--theia-statusBar-font-size); z-index: 1000; /* Above the transparent overlay (`z-index: 999;`). */ } diff --git a/packages/plugin-ext/src/main/style/status-bar.css b/packages/plugin-ext/src/main/style/status-bar.css index 587d13ff03c7d..43c38e56c6e23 100644 --- a/packages/plugin-ext/src/main/style/status-bar.css +++ b/packages/plugin-ext/src/main/style/status-bar.css @@ -15,7 +15,7 @@ ********************************************************************************/ #theia-statusBar .development-host { - background-color: var(--theia-success-color0); + background-color: var(--theia-successBackground); } #theia-statusBar .development-host-offline { @@ -23,11 +23,11 @@ } #theia-statusBar .hosted-plugin { - background-color: var(--theia-info-color0); + background-color: var(--theia-inputValidation-infoBackground); } #theia-statusBar .hosted-plugin:hover { - background-color: var(--theia-info-color1); + background-color: var(--theia-editorInfo-foreground); } #theia-statusBar .hosted-plugin-failed { diff --git a/packages/scm/src/browser/style/index.css b/packages/scm/src/browser/style/index.css index 5c762e5eca84b..d43421e799219 100644 --- a/packages/scm/src/browser/style/index.css +++ b/packages/scm/src/browser/style/index.css @@ -112,7 +112,7 @@ } .theia-scm-input-message-success { - border-color: var(--theia-success-color0); + border-color: var(--theia-successBackground); } .theia-scm-input-message-warning { @@ -129,19 +129,19 @@ } .theia-scm-validation-message-info { - background-color: var(--theia-info-color0) !important; - color: var(--theia-info-font-color0); + background-color: var(--theia-inputValidation-infoBackground) !important; + color: var(--theia-inputValidation-warningBackground); } .theia-scm-validation-message-success { - background-color: var(--theia-success-color0) !important; - color: var(--theia-success-font-color0); + background-color: var(--theia-successBackground) !important; + color: var(--theia-inputValidation-warningBackground); } .theia-scm-message-warning, .theia-scm-validation-message-warning { - background-color: var(--theia-warningBackground) !important; - color: var(--theia-inputValidation-warningForeground); + background-color: var(--theia-editorWarning-foreground) !important; + color: var(--theia-inputValidation-warningBackground); } .theia-scm-validation-message-error { diff --git a/packages/search-in-workspace/src/browser/styles/index.css b/packages/search-in-workspace/src/browser/styles/index.css index ff33c3b4767bc..4a2829fb6fbe9 100644 --- a/packages/search-in-workspace/src/browser/styles/index.css +++ b/packages/search-in-workspace/src/browser/styles/index.css @@ -127,10 +127,10 @@ } .t-siw-search-container .searchHeader .search-notification div{ - background-color: var(--theia-warningBackground); + background-color: var(--theia-editorWarning-foreground); width: calc(100% + 2px); margin-left: -1px; - color: var(--theia-inputValidation-warningForeground); + color: var(--theia-inputValidation-warningBackground); z-index: 1000; position: absolute; border: 1px solid var(--theia-inputValidation-warningBorder); diff --git a/packages/typehierarchy/src/browser/tree/typehierarchy-tree.ts b/packages/typehierarchy/src/browser/tree/typehierarchy-tree.ts index 6383a47bf5888..de08f2e5a42fb 100644 --- a/packages/typehierarchy/src/browser/tree/typehierarchy-tree.ts +++ b/packages/typehierarchy/src/browser/tree/typehierarchy-tree.ts @@ -174,7 +174,7 @@ export namespace TypeHierarchyTree { }); } const data = `${TypeHierarchyDirection.Children === direction ? 'â–¼' : 'â–²'}`; - const color = `var(${TypeHierarchyDirection.Children === direction ? '--theia-errorForeground' : '--theia-success-color2'})`; + const color = `var(${TypeHierarchyDirection.Children === direction ? '--theia-errorForeground' : '--theia-successBackground'})`; return { captionSuffixes, captionPrefixes: [{ From 54e321f509e4f6ea4c9741f62617c3fe222699bc Mon Sep 17 00:00:00 2001 From: Jan Bicker Date: Mon, 16 Dec 2019 15:33:44 +0000 Subject: [PATCH 49/65] Fixed tab highlighting in right activity bar. Signed-off-by: Jan Bicker --- packages/core/src/browser/style/sidepanel.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/src/browser/style/sidepanel.css b/packages/core/src/browser/style/sidepanel.css index 00864569656c6..9b984d7004edf 100644 --- a/packages/core/src/browser/style/sidepanel.css +++ b/packages/core/src/browser/style/sidepanel.css @@ -90,12 +90,12 @@ } .p-TabBar.theia-app-right .p-TabBar-tab.p-mod-current { - border-right-color: var(--theia-panel-border-width) solid var(--theia-activityBar-activeBorder); + border-right: var(--theia-panel-border-width) solid var(--theia-activityBar-activeBorder); border-top-color: transparent; } .p-TabBar.theia-app-right .p-TabBar-tab.p-mod-current.theia-mod-active { - border-left: var(--theia-panel-border-width) solid var(--theia-focusBorder); + border-right: var(--theia-panel-border-width) solid var(--theia-focusBorder); } .p-TabBar.theia-app-sides .p-TabBar-tabLabel, From 283226b9ab6e76a94e8a10fcc4efea189c4fd759 Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Mon, 16 Dec 2019 15:44:11 +0000 Subject: [PATCH 50/65] (theming) Use css classes to style HTML elements. Instead of styling based on tags. Signed-off-by: Anton Kosyakov --- CHANGELOG.md | 2 ++ packages/core/src/browser/style/index.css | 4 ++-- .../debug/src/browser/console/debug-console-contribution.tsx | 1 + packages/debug/src/browser/editor/debug-breakpoint-widget.tsx | 4 +++- .../debug/src/browser/view/debug-configuration-widget.tsx | 2 +- .../browser/file-dialog/file-dialog-tree-filters-renderer.tsx | 2 +- .../filesystem/src/browser/location/location-renderer.tsx | 2 +- packages/output/src/browser/output-toolbar-contribution.tsx | 1 + 8 files changed, 12 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 116e7f28e1f37..9e86a259b374c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ Breaking changes: - [task] renamed method `getStrigifiedTaskSchema()` has been renamed to `getStringifiedTaskSchema()` [#6780](https://github.com/eclipse-theia/theia/pull/6780) - [task] renamed method `reorgnizeTasks()` has been renamed to `reorganizeTasks()` [#6780](https://github.com/eclipse-theia/theia/pull/6780) +- Support VS Code icon and color theming. [#6475](https://github.com/eclipse-theia/theia/pull/6475) + - Use `theia-input`, `theia-select` and `theia-button` to style input/textarea, select and button elements correspondingly. Before such elements were styled in an ad-hoc manner. ## v0.14.0 diff --git a/packages/core/src/browser/style/index.css b/packages/core/src/browser/style/index.css index d413d4648e807..cd2dd61019380 100644 --- a/packages/core/src/browser/style/index.css +++ b/packages/core/src/browser/style/index.css @@ -198,7 +198,7 @@ button.secondary[disabled], .theia-button.secondary[disabled] { background-color: var(--theia-secondaryButton-disabledBackground); } -select { +.theia-select { color: var(--dropdown-foreground); font-size: var(--theia-ui-font-size1); border-radius: 0; @@ -207,7 +207,7 @@ select { outline: none; } -select option { +.theia-select option { background: var(--theia-dropdown-listBackground); } diff --git a/packages/debug/src/browser/console/debug-console-contribution.tsx b/packages/debug/src/browser/console/debug-console-contribution.tsx index ba9c1ba6da066..8243aef86fdd3 100644 --- a/packages/debug/src/browser/console/debug-console-contribution.tsx +++ b/packages/debug/src/browser/console/debug-console-contribution.tsx @@ -132,6 +132,7 @@ export class DebugConsoleContribution extends AbstractViewContribution + ReactDOM.render( + {...options}; + return ; } protected renderLocation(value: string): React.ReactNode { diff --git a/packages/filesystem/src/browser/location/location-renderer.tsx b/packages/filesystem/src/browser/location/location-renderer.tsx index e95e918d31982..1ae65e21ac259 100644 --- a/packages/filesystem/src/browser/location/location-renderer.tsx +++ b/packages/filesystem/src/browser/location/location-renderer.tsx @@ -43,7 +43,7 @@ export class LocationListRenderer extends ReactRenderer { protected readonly handleLocationChanged = (e: React.ChangeEvent) => this.onLocationChanged(e); protected doRender(): React.ReactNode { const options = this.collectLocations().map(value => this.renderLocation(value)); - return ; + return ; } /** diff --git a/packages/output/src/browser/output-toolbar-contribution.tsx b/packages/output/src/browser/output-toolbar-contribution.tsx index aa90f8aad4a9b..1b03e0a0d9c89 100644 --- a/packages/output/src/browser/output-toolbar-contribution.tsx +++ b/packages/output/src/browser/output-toolbar-contribution.tsx @@ -54,6 +54,7 @@ export class OutputToolbarContribution implements TabBarToolbarContribution { channelOptionElements.push(); } return