mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 13:00:58 +00:00
themes as settings
This commit is contained in:
parent
b7dc5cd88b
commit
255ecfb084
|
@ -9,26 +9,31 @@
|
|||
"contributes": {
|
||||
"themes": [
|
||||
{
|
||||
"id": "Default Dark+",
|
||||
"label": "Dark+ (default dark)",
|
||||
"uiTheme": "vs-dark",
|
||||
"path": "./themes/dark_plus.json"
|
||||
},
|
||||
{
|
||||
"id": "Default Light+",
|
||||
"label": "Light+ (default light)",
|
||||
"uiTheme": "vs",
|
||||
"path": "./themes/light_plus.json"
|
||||
},
|
||||
{
|
||||
"id": "Visual Studio Dark",
|
||||
"label": "Dark (Visual Studio)",
|
||||
"uiTheme": "vs-dark",
|
||||
"path": "./themes/dark_vs.json"
|
||||
},
|
||||
{
|
||||
"id": "Visual Studio Light",
|
||||
"label": "Light (Visual Studio)",
|
||||
"uiTheme": "vs",
|
||||
"path": "./themes/light_vs.json"
|
||||
},
|
||||
{
|
||||
"id": "Default High Contrast",
|
||||
"label": "High Contrast",
|
||||
"uiTheme": "hc-black",
|
||||
"path": "./themes/hc_black.json"
|
||||
|
|
|
@ -9,7 +9,6 @@ import * as path from 'path';
|
|||
import * as platform from 'vs/base/common/platform';
|
||||
import * as objects from 'vs/base/common/objects';
|
||||
import nls = require('vs/nls');
|
||||
import { IStorageService } from 'vs/code/electron-main/storage';
|
||||
import { shell, screen, BrowserWindow, systemPreferences, app } from 'electron';
|
||||
import { TPromise, TValueCallback } from 'vs/base/common/winjs.base';
|
||||
import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment';
|
||||
|
@ -78,6 +77,7 @@ export interface IWindowConfiguration extends ParsedArgs {
|
|||
zoomLevel?: number;
|
||||
fullscreen?: boolean;
|
||||
highContrast?: boolean;
|
||||
baseTheme?: string;
|
||||
accessibilitySupport?: boolean;
|
||||
|
||||
isInitialStartup?: boolean;
|
||||
|
@ -134,8 +134,6 @@ export interface IVSCodeWindow {
|
|||
|
||||
export class VSCodeWindow implements IVSCodeWindow {
|
||||
|
||||
public static colorThemeStorageKey = 'theme';
|
||||
|
||||
private static MIN_WIDTH = 200;
|
||||
private static MIN_HEIGHT = 120;
|
||||
|
||||
|
@ -162,8 +160,7 @@ export class VSCodeWindow implements IVSCodeWindow {
|
|||
config: IWindowCreationOptions,
|
||||
@ILogService private logService: ILogService,
|
||||
@IEnvironmentService private environmentService: IEnvironmentService,
|
||||
@IConfigurationService private configurationService: IConfigurationService,
|
||||
@IStorageService private storageService: IStorageService
|
||||
@IConfigurationService private configurationService: IConfigurationService
|
||||
) {
|
||||
this.options = config;
|
||||
this._lastFocusTime = -1;
|
||||
|
@ -177,9 +174,9 @@ export class VSCodeWindow implements IVSCodeWindow {
|
|||
this.restoreWindowState(config.state);
|
||||
|
||||
// For VS theme we can show directly because background is white
|
||||
const themeId = this.storageService.getItem<string>(VSCodeWindow.colorThemeStorageKey);
|
||||
const usesLightTheme = /vs($| )/.test(themeId);
|
||||
const usesHighContrastTheme = /hc-black($| )/.test(themeId) || (platform.isWindows && systemPreferences.isInvertedColorScheme());
|
||||
const themeId = this.configurationService.lookup<string>('workbench.colorTheme').value;
|
||||
const usesLightTheme = /^l-/.test(themeId);
|
||||
const usesHighContrastTheme = /^hc-/.test(themeId) || (platform.isWindows && systemPreferences.isInvertedColorScheme());
|
||||
|
||||
// in case we are maximized or fullscreen, only show later after the call to maximize/fullscreen (see below)
|
||||
const isFullscreenOrMaximized = (this.currentWindowMode === WindowMode.Maximized || this.currentWindowMode === WindowMode.Fullscreen);
|
||||
|
@ -505,6 +502,16 @@ export class VSCodeWindow implements IVSCodeWindow {
|
|||
windowConfiguration.highContrast = platform.isWindows && systemPreferences.isInvertedColorScheme() && (!windowConfig || windowConfig.autoDetectHighContrast);
|
||||
windowConfiguration.accessibilitySupport = app.isAccessibilitySupportEnabled();
|
||||
|
||||
// background color
|
||||
const themeId = this.configurationService.lookup<string>('workbench.colorTheme').value;
|
||||
if (themeId[0] === 'h') {
|
||||
windowConfiguration.baseTheme = 'hc-black';
|
||||
} else if (themeId[0] === 'l') {
|
||||
windowConfiguration.baseTheme = 'vs';
|
||||
} else {
|
||||
windowConfiguration.baseTheme = 'vs-dark';
|
||||
}
|
||||
|
||||
// Perf Counters
|
||||
windowConfiguration.perfStartTime = global.perfStartTime;
|
||||
windowConfiguration.perfAppReady = global.perfAppReady;
|
||||
|
|
|
@ -289,13 +289,7 @@ export class WindowsManager implements IWindowsMainService {
|
|||
}
|
||||
|
||||
private onBroadcast(event: string, payload: any): void {
|
||||
|
||||
// Theme changes
|
||||
if (event === 'vscode:changeColorTheme' && typeof payload === 'string') {
|
||||
this.storageService.setItem(VSCodeWindow.colorThemeStorageKey, payload);
|
||||
}
|
||||
}
|
||||
|
||||
public reload(win: VSCodeWindow, cli?: ParsedArgs): void {
|
||||
|
||||
// Only reload when the window has not vetoed this
|
||||
|
@ -530,7 +524,7 @@ export class WindowsManager implements IWindowsMainService {
|
|||
|
||||
const mru = this.getRecentPathsList();
|
||||
paths.forEach(p => {
|
||||
const {path, isFile} = p;
|
||||
const { path, isFile } = p;
|
||||
|
||||
if (isFile) {
|
||||
mru.files.unshift(path);
|
||||
|
@ -794,8 +788,7 @@ export class WindowsManager implements IWindowsMainService {
|
|||
},
|
||||
this.logService,
|
||||
this.environmentService,
|
||||
this.configurationService,
|
||||
this.storageService
|
||||
this.configurationService
|
||||
);
|
||||
|
||||
WindowsManager.WINDOWS.push(vscodeWindow);
|
||||
|
|
|
@ -16,13 +16,8 @@
|
|||
<script>
|
||||
(function() {
|
||||
try {
|
||||
var theme = window.localStorage.getItem('storage://global/workbench.theme');
|
||||
if (theme) {
|
||||
var baseTheme = theme.split(' ')[0];
|
||||
if (baseTheme !== 'vs-dark') {
|
||||
window.document.body.className = 'monaco-shell ' + baseTheme;
|
||||
}
|
||||
}
|
||||
let config = JSON.parse(decodeURIComponent(window.location.search.substring(8)));
|
||||
window.document.body.className = 'monaco-shell ' + config.baseTheme;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
|
|
@ -269,7 +269,7 @@ export class ElectronWindow {
|
|||
const windowConfig = this.configurationService.getConfiguration<IWindowSettings>('window');
|
||||
if (windowConfig && windowConfig.autoDetectHighContrast) {
|
||||
this.partService.joinCreation().then(() => {
|
||||
this.themeService.setColorTheme(VS_HC_THEME, false);
|
||||
this.themeService.setColorTheme(VS_HC_THEME, null);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -278,7 +278,7 @@ export class ElectronWindow {
|
|||
const windowConfig = this.configurationService.getConfiguration<IWindowSettings>('window');
|
||||
if (windowConfig && windowConfig.autoDetectHighContrast) {
|
||||
this.partService.joinCreation().then(() => {
|
||||
this.themeService.setColorTheme(VS_DARK_THEME, false);
|
||||
this.themeService.setColorTheme(VS_DARK_THEME, null);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -11,7 +11,6 @@ import { TPromise } from 'vs/base/common/winjs.base';
|
|||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { addDisposableListener, addClass } from 'vs/base/browser/dom';
|
||||
import { isLightTheme, isDarkTheme } from 'vs/platform/theme/common/themes';
|
||||
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { MenuRegistry } from 'vs/platform/actions/common/actions';
|
||||
import { IColorTheme } from 'vs/workbench/services/themes/common/themeService';
|
||||
|
@ -154,7 +153,6 @@ export default class Webview {
|
|||
}
|
||||
|
||||
style(theme: IColorTheme): void {
|
||||
let themeId = theme.id;
|
||||
const {color, backgroundColor, fontFamily, fontWeight, fontSize} = window.getComputedStyle(this._styleElement);
|
||||
|
||||
let value = `
|
||||
|
@ -193,7 +191,7 @@ export default class Webview {
|
|||
|
||||
let activeTheme: ApiThemeClassName;
|
||||
|
||||
if (isLightTheme(themeId)) {
|
||||
if (theme.isLightTheme()) {
|
||||
value += `
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(100, 100, 100, 0.4);
|
||||
|
@ -207,7 +205,7 @@ export default class Webview {
|
|||
|
||||
activeTheme = 'vscode-light';
|
||||
|
||||
} else if (isDarkTheme(themeId)) {
|
||||
} else if (theme.isDarkTheme()) {
|
||||
value += `
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(121, 121, 121, 0.4);
|
||||
|
|
|
@ -31,7 +31,6 @@ import { createActionItem } from 'vs/platform/actions/browser/menuItemActionItem
|
|||
import { SCMMenus } from './scmMenus';
|
||||
import { ActionBar, IActionItemProvider } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IThemeService } from 'vs/workbench/services/themes/common/themeService';
|
||||
import { isDarkTheme } from 'vs/platform/theme/common/themes';
|
||||
import { SCMEditor } from './scmEditor';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
|
||||
|
@ -128,7 +127,7 @@ class ResourceRenderer implements IRenderer<ISCMResource, ResourceTemplate> {
|
|||
toggleClass(template.name, 'strike-through', resource.decorations.strikeThrough);
|
||||
|
||||
const theme = this.themeService.getColorTheme();
|
||||
const icon = isDarkTheme(theme.id) ? resource.decorations.iconDark : resource.decorations.icon;
|
||||
const icon = theme.isDarkTheme() ? resource.decorations.iconDark : resource.decorations.icon;
|
||||
|
||||
if (icon) {
|
||||
template.decorationIcon.style.backgroundImage = `url('${icon}')`;
|
||||
|
|
|
@ -20,7 +20,6 @@ import { KillTerminalAction, CreateNewTerminalAction, SwitchTerminalInstanceActi
|
|||
import { Panel } from 'vs/workbench/browser/panel';
|
||||
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { getBaseThemeId } from 'vs/platform/theme/common/themes';
|
||||
|
||||
export class TerminalPanel extends Panel {
|
||||
|
||||
|
@ -204,8 +203,7 @@ export class TerminalPanel extends Panel {
|
|||
if (!colorTheme) {
|
||||
colorTheme = this._themeService.getColorTheme();
|
||||
}
|
||||
let themeId = colorTheme.id;
|
||||
let baseThemeId = getBaseThemeId(themeId);
|
||||
let baseThemeId = colorTheme.getBaseThemeId();
|
||||
if (baseThemeId === this._currentBaseThemeId) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -15,11 +15,13 @@ import { IMessageService, Severity } from 'vs/platform/message/common/message';
|
|||
import { Registry } from 'vs/platform/platform';
|
||||
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actionRegistry';
|
||||
import { IQuickOpenService, IPickOpenEntry } from 'vs/platform/quickOpen/common/quickOpen';
|
||||
import { IThemeService } from 'vs/workbench/services/themes/common/themeService';
|
||||
import { IThemeService, COLOR_THEME_SETTING, ICON_THEME_SETTING } from 'vs/workbench/services/themes/common/themeService';
|
||||
import { VIEWLET_ID, IExtensionsViewlet } from 'vs/workbench/parts/extensions/common/extensions';
|
||||
import { IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||
import { Delayer } from 'vs/base/common/async';
|
||||
import { ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing';
|
||||
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
|
||||
|
||||
export class SelectColorThemeAction extends Action {
|
||||
|
||||
|
@ -33,7 +35,8 @@ export class SelectColorThemeAction extends Action {
|
|||
@IMessageService private messageService: IMessageService,
|
||||
@IThemeService private themeService: IThemeService,
|
||||
@IExtensionGalleryService private extensionGalleryService: IExtensionGalleryService,
|
||||
@IViewletService private viewletService: IViewletService
|
||||
@IViewletService private viewletService: IViewletService,
|
||||
@IWorkspaceConfigurationService private configurationService: IWorkspaceConfigurationService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
@ -48,12 +51,18 @@ export class SelectColorThemeAction extends Action {
|
|||
.map(theme => ({ id: theme.id, label: theme.label, description: theme.description }))
|
||||
.sort((t1, t2) => t1.label.localeCompare(t2.label));
|
||||
|
||||
const selectTheme = (theme, broadcast) => {
|
||||
const selectTheme = (theme, applyTheme) => {
|
||||
if (theme === pickInMarketPlace) {
|
||||
theme = currentTheme;
|
||||
}
|
||||
this.themeService.setColorTheme(theme.id, broadcast)
|
||||
.done(null, err => this.messageService.show(Severity.Info, localize('problemChangingTheme', "Problem loading theme: {0}", err)));
|
||||
let target = null;
|
||||
if (applyTheme) {
|
||||
let confValue = this.configurationService.lookup(COLOR_THEME_SETTING);
|
||||
target = typeof confValue.workspace !== 'undefined' ? ConfigurationTarget.WORKSPACE : ConfigurationTarget.USER;
|
||||
}
|
||||
|
||||
this.themeService.setColorTheme(theme.id, target)
|
||||
.done(null, err => this.messageService.show(Severity.Info, localize('problemChangingTheme', "Problem setting theme: {0}", err)));
|
||||
};
|
||||
|
||||
const placeHolder = localize('themes.selectTheme', "Select Color Theme");
|
||||
|
@ -86,7 +95,9 @@ class SelectIconThemeAction extends Action {
|
|||
@IMessageService private messageService: IMessageService,
|
||||
@IThemeService private themeService: IThemeService,
|
||||
@IExtensionGalleryService private extensionGalleryService: IExtensionGalleryService,
|
||||
@IViewletService private viewletService: IViewletService
|
||||
@IViewletService private viewletService: IViewletService,
|
||||
@IWorkspaceConfigurationService private configurationService: IWorkspaceConfigurationService
|
||||
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
@ -103,12 +114,17 @@ class SelectIconThemeAction extends Action {
|
|||
|
||||
picks.splice(0, 0, { id: '', label: localize('noIconThemeLabel', 'None'), description: localize('noIconThemeDesc', 'Disable file icons') });
|
||||
|
||||
const selectTheme = (theme, broadcast) => {
|
||||
const selectTheme = (theme, applyTheme) => {
|
||||
if (theme === pickInMarketPlace) {
|
||||
theme = currentTheme;
|
||||
}
|
||||
this.themeService.setFileIconTheme(theme && theme.id, broadcast)
|
||||
.done(null, err => this.messageService.show(Severity.Info, localize('problemChangingIconTheme', "Problem loading icon theme: {0}", err.message)));
|
||||
let target = null;
|
||||
if (applyTheme) {
|
||||
let confValue = this.configurationService.lookup(ICON_THEME_SETTING);
|
||||
target = typeof confValue.workspace !== 'undefined' ? ConfigurationTarget.WORKSPACE : ConfigurationTarget.USER;
|
||||
}
|
||||
this.themeService.setFileIconTheme(theme && theme.id, target)
|
||||
.done(null, err => this.messageService.show(Severity.Info, localize('problemChangingIconTheme', "Problem setting icon theme: {0}", err.message)));
|
||||
};
|
||||
|
||||
const placeHolder = localize('themes.selectIconTheme', "Select File Icon Theme");
|
||||
|
|
|
@ -183,7 +183,7 @@ class Snapper {
|
|||
let defaultThemes = themeDatas.filter(themeData => !!getThemeName(themeData.id));
|
||||
return TPromise.join(defaultThemes.map(defaultTheme => {
|
||||
let themeId = defaultTheme.id;
|
||||
return this.themeService.setColorTheme(themeId, false).then(success => {
|
||||
return this.themeService.setColorTheme(themeId, null).then(success => {
|
||||
if (success) {
|
||||
let themeName = getThemeName(themeId);
|
||||
result[themeName] = {
|
||||
|
@ -194,7 +194,7 @@ class Snapper {
|
|||
});
|
||||
}));
|
||||
}).then(_ => {
|
||||
return this.themeService.setColorTheme(currentTheme.id, false).then(_ => {
|
||||
return this.themeService.setColorTheme(currentTheme.id, null).then(_ => {
|
||||
return result;
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import Event from 'vs/base/common/event';
|
||||
import { ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing';
|
||||
|
||||
export let IThemeService = createDecorator<IThemeService>('themeService');
|
||||
|
||||
|
@ -14,17 +15,27 @@ export const VS_LIGHT_THEME = 'vs';
|
|||
export const VS_DARK_THEME = 'vs-dark';
|
||||
export const VS_HC_THEME = 'hc-black';
|
||||
|
||||
export const COLOR_THEME_SETTING = 'workbench.colorTheme';
|
||||
export const ICON_THEME_SETTING = 'workbench.iconTheme';
|
||||
|
||||
export interface IColorTheme {
|
||||
readonly id: string;
|
||||
readonly label: string;
|
||||
readonly settingsId: string;
|
||||
readonly description?: string;
|
||||
readonly isLoaded: boolean;
|
||||
readonly settings?: IThemeSetting[];
|
||||
|
||||
isLightTheme(): boolean;
|
||||
isDarkTheme(): boolean;
|
||||
getSyntaxThemeId(): string;
|
||||
getBaseThemeId(): string;
|
||||
}
|
||||
|
||||
export interface IFileIconTheme {
|
||||
readonly id: string;
|
||||
readonly label: string;
|
||||
readonly settingsId: string;
|
||||
readonly description?: string;
|
||||
readonly isLoaded: boolean;
|
||||
readonly hasFileIcons?: boolean;
|
||||
|
@ -33,12 +44,12 @@ export interface IFileIconTheme {
|
|||
|
||||
export interface IThemeService {
|
||||
_serviceBrand: any;
|
||||
setColorTheme(themeId: string, broadcastToAllWindows: boolean): TPromise<IColorTheme>;
|
||||
setColorTheme(themeId: string, settingsTarget: ConfigurationTarget): TPromise<IColorTheme>;
|
||||
getColorTheme(): IColorTheme;
|
||||
getColorThemes(): TPromise<IColorTheme[]>;
|
||||
onDidColorThemeChange: Event<IColorTheme>;
|
||||
|
||||
setFileIconTheme(iconThemeId: string, broadcastToAllWindows: boolean): TPromise<IFileIconTheme>;
|
||||
setFileIconTheme(iconThemeId: string, settingsTarget: ConfigurationTarget): TPromise<IFileIconTheme>;
|
||||
getFileIconTheme(): IFileIconTheme;
|
||||
getFileIconThemes(): TPromise<IFileIconTheme[]>;
|
||||
onDidFileIconThemeChange: Event<IFileIconTheme>;
|
||||
|
|
|
@ -8,19 +8,23 @@ import { TPromise, Promise } from 'vs/base/common/winjs.base';
|
|||
import nls = require('vs/nls');
|
||||
import Paths = require('vs/base/common/paths');
|
||||
import Json = require('vs/base/common/json');
|
||||
import * as types from 'vs/base/common/types';
|
||||
import { IThemeExtensionPoint } from 'vs/platform/theme/common/themeExtensionPoint';
|
||||
import { IExtensionService } from 'vs/platform/extensions/common/extensions';
|
||||
import { ExtensionsRegistry, ExtensionMessageCollector } from 'vs/platform/extensions/common/extensionsRegistry';
|
||||
import { IThemeService, IThemeSetting, IColorTheme, IFileIconTheme, VS_LIGHT_THEME, VS_DARK_THEME, VS_HC_THEME } from 'vs/workbench/services/themes/common/themeService';
|
||||
import { IThemeService, IThemeSetting, IColorTheme, IFileIconTheme, VS_LIGHT_THEME, VS_DARK_THEME, VS_HC_THEME, COLOR_THEME_SETTING, ICON_THEME_SETTING } from 'vs/workbench/services/themes/common/themeService';
|
||||
import { EditorStylesContribution, SearchViewStylesContribution, TerminalStylesContribution } from 'vs/workbench/services/themes/electron-browser/stylesContributions';
|
||||
import { getBaseThemeId } from 'vs/platform/theme/common/themes';
|
||||
import { IWindowIPCService } from 'vs/workbench/services/window/electron-browser/windowService';
|
||||
import { getBaseThemeId, getSyntaxThemeId, isDarkTheme, isLightTheme } from 'vs/platform/theme/common/themes';
|
||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { Registry } from 'vs/platform/platform';
|
||||
import { Extensions as JSONExtensions, IJSONContributionRegistry } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
|
||||
import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
import errors = require('vs/base/common/errors');
|
||||
import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
|
||||
|
||||
import { $ } from 'vs/base/browser/builder';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
|
@ -31,13 +35,9 @@ import pfs = require('vs/base/node/pfs');
|
|||
// implementation
|
||||
|
||||
const DEFAULT_THEME_ID = 'vs-dark vscode-theme-defaults-themes-dark_plus-json';
|
||||
const DEFAULT_THEME_NAME = 'd-Dark+ (default dark)';
|
||||
|
||||
const COLOR_THEME_CHANNEL = 'vscode:changeColorTheme';
|
||||
const ICON_THEME_CHANNEL = 'vscode:changeIconTheme';
|
||||
const COLOR_THEME_PREF = 'workbench.theme';
|
||||
const ICON_THEME_PREF = 'workbench.iconTheme';
|
||||
|
||||
let defaultBaseTheme = getBaseThemeId(DEFAULT_THEME_ID);
|
||||
const defaultBaseTheme = getBaseThemeId(DEFAULT_THEME_ID);
|
||||
|
||||
const defaultThemeExtensionId = 'vscode-theme-defaults';
|
||||
const oldDefaultThemeExtensionId = 'vscode-theme-colorful-defaults';
|
||||
|
@ -61,8 +61,12 @@ let themesExtPoint = ExtensionsRegistry.registerExtensionPoint<IThemeExtensionPo
|
|||
type: 'array',
|
||||
items: {
|
||||
type: 'object',
|
||||
defaultSnippets: [{ body: { label: '${1:label}', uiTheme: VS_DARK_THEME, path: './themes/${2:id}.tmTheme.' } }],
|
||||
defaultSnippets: [{ body: { label: '${1:label}', id: '${2:id}', uiTheme: VS_DARK_THEME, path: './themes/${3:id}.tmTheme.' } }],
|
||||
properties: {
|
||||
id: {
|
||||
description: nls.localize('vscode.extension.contributes.themes.id', 'Id of the icon theme as used in the user settings.'),
|
||||
type: 'string'
|
||||
},
|
||||
label: {
|
||||
description: nls.localize('vscode.extension.contributes.themes.label', 'Label of the color theme as shown in the UI.'),
|
||||
type: 'string'
|
||||
|
@ -104,20 +108,38 @@ let iconThemeExtPoint = ExtensionsRegistry.registerExtensionPoint<IThemeExtensio
|
|||
}
|
||||
});
|
||||
|
||||
class IInternalColorThemeData implements IColorTheme {
|
||||
class ColorThemeData implements IColorTheme {
|
||||
id: string;
|
||||
label: string;
|
||||
settingsId: string;
|
||||
description?: string;
|
||||
settings?: IThemeSetting[];
|
||||
isLoaded: boolean;
|
||||
path?: string;
|
||||
styleSheetContent?: string;
|
||||
extensionData: ExtensionData;
|
||||
|
||||
isLightTheme() {
|
||||
return isLightTheme(this.id);
|
||||
}
|
||||
|
||||
isDarkTheme() {
|
||||
return isDarkTheme(this.id);
|
||||
}
|
||||
|
||||
getSyntaxThemeId() {
|
||||
return getSyntaxThemeId(this.id);
|
||||
}
|
||||
|
||||
getBaseThemeId() {
|
||||
return getBaseThemeId(this.id);
|
||||
}
|
||||
}
|
||||
|
||||
class IInternalIconThemeData implements IFileIconTheme {
|
||||
interface IInternalIconThemeData extends IFileIconTheme {
|
||||
id: string;
|
||||
label: string;
|
||||
settingsId: string;
|
||||
description?: string;
|
||||
hasFileIcons?: boolean;
|
||||
hasFolderIcons?: boolean;
|
||||
|
@ -171,6 +193,7 @@ interface ExtensionData {
|
|||
const noFileIconTheme: IFileIconTheme = {
|
||||
id: '',
|
||||
label: '',
|
||||
settingsId: null,
|
||||
hasFileIcons: false,
|
||||
hasFolderIcons: false,
|
||||
isLoaded: true
|
||||
|
@ -197,10 +220,16 @@ let defaultThemeColors: { [baseTheme: string]: IThemeSetting[] } = {
|
|||
],
|
||||
};
|
||||
|
||||
const settingsIdPrefix = {
|
||||
[VS_DARK_THEME]: 'd-',
|
||||
[VS_LIGHT_THEME]: 'l-',
|
||||
[VS_HC_THEME]: 'hc-',
|
||||
};
|
||||
|
||||
export class ThemeService implements IThemeService {
|
||||
_serviceBrand: any;
|
||||
|
||||
private knownColorThemes: IInternalColorThemeData[];
|
||||
private knownColorThemes: ColorThemeData[];
|
||||
private currentColorTheme: IColorTheme;
|
||||
private container: HTMLElement;
|
||||
private onColorThemeChange: Emitter<IColorTheme>;
|
||||
|
@ -212,8 +241,9 @@ export class ThemeService implements IThemeService {
|
|||
constructor(
|
||||
container: HTMLElement,
|
||||
@IExtensionService private extensionService: IExtensionService,
|
||||
@IWindowIPCService private windowService: IWindowIPCService,
|
||||
@IStorageService private storageService: IStorageService,
|
||||
@IConfigurationService private configurationService: IConfigurationService,
|
||||
@IConfigurationEditingService private configurationEditingService: IConfigurationEditingService,
|
||||
@ITelemetryService private telemetryService: ITelemetryService) {
|
||||
|
||||
this.container = container;
|
||||
|
@ -225,23 +255,26 @@ export class ThemeService implements IThemeService {
|
|||
let isLightTheme = (Array.prototype.indexOf.call(document.body.classList, 'vs') >= 0);
|
||||
let foreground = isLightTheme ? '#000000' : '#D4D4D4';
|
||||
let background = isLightTheme ? '#ffffff' : '#1E1E1E';
|
||||
this.currentColorTheme = {
|
||||
id: this.storageService.get(COLOR_THEME_PREF, StorageScope.GLOBAL, DEFAULT_THEME_ID),
|
||||
label: '',
|
||||
isLoaded: false,
|
||||
settings: [{
|
||||
settings: {
|
||||
foreground: foreground,
|
||||
background: background
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
let initialTheme = new ColorThemeData();
|
||||
initialTheme.id = isLightTheme ? VS_LIGHT_THEME : VS_DARK_THEME;
|
||||
initialTheme.label = '';
|
||||
initialTheme.settingsId = null;
|
||||
initialTheme.isLoaded = false;
|
||||
initialTheme.settings = [{
|
||||
settings: {
|
||||
foreground: foreground,
|
||||
background: background
|
||||
}
|
||||
}];
|
||||
this.currentColorTheme = initialTheme;
|
||||
|
||||
this.onColorThemeChange = new Emitter<IColorTheme>();
|
||||
this.knownIconThemes = [];
|
||||
this.currentIconTheme = {
|
||||
id: '',
|
||||
label: '',
|
||||
settingsId: null,
|
||||
isLoaded: false,
|
||||
hasFileIcons: false,
|
||||
hasFolderIcons: false
|
||||
|
@ -260,12 +293,6 @@ export class ThemeService implements IThemeService {
|
|||
}
|
||||
});
|
||||
|
||||
windowService.onBroadcast(e => {
|
||||
if (e.channel === COLOR_THEME_CHANNEL && typeof e.payload === 'string') {
|
||||
this.setColorTheme(e.payload, false);
|
||||
}
|
||||
});
|
||||
|
||||
iconThemeExtPoint.setHandler((extensions) => {
|
||||
for (let ext of extensions) {
|
||||
let extensionData = {
|
||||
|
@ -278,9 +305,21 @@ export class ThemeService implements IThemeService {
|
|||
}
|
||||
});
|
||||
|
||||
windowService.onBroadcast(e => {
|
||||
if (e.channel === ICON_THEME_CHANNEL && typeof e.payload === 'string') {
|
||||
this.setFileIconTheme(e.payload, false);
|
||||
this.configurationService.onDidUpdateConfiguration(e => {
|
||||
let colorThemeSetting = this.configurationService.lookup<string>(COLOR_THEME_SETTING).value;
|
||||
if (colorThemeSetting !== this.currentColorTheme.settingsId) {
|
||||
this.findThemeDataBySettingsId(colorThemeSetting, null).then(theme => {
|
||||
if (theme) {
|
||||
this.setColorTheme(theme.id, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let iconThemeSetting = this.configurationService.lookup<string>(ICON_THEME_SETTING).value || '';
|
||||
if (iconThemeSetting !== this.currentIconTheme.settingsId) {
|
||||
this.findIconThemeBySettingsId(iconThemeSetting).then(theme => {
|
||||
this.setFileIconTheme(theme && theme.id, null);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -296,33 +335,52 @@ export class ThemeService implements IThemeService {
|
|||
}
|
||||
|
||||
private initialize(): TPromise<void> {
|
||||
let themeId = this.storageService.get(COLOR_THEME_PREF, StorageScope.GLOBAL, null);
|
||||
if (!themeId) {
|
||||
themeId = DEFAULT_THEME_ID;
|
||||
this.storageService.store(COLOR_THEME_PREF, themeId, StorageScope.GLOBAL);
|
||||
}
|
||||
let iconThemeId = this.storageService.get(ICON_THEME_PREF, StorageScope.GLOBAL, null);
|
||||
return Promise.join([
|
||||
this.setColorTheme(themeId, false),
|
||||
this.setFileIconTheme(iconThemeId, false)
|
||||
]);
|
||||
|
||||
let legacyColorThemeId = this.storageService.get('workbench.theme', StorageScope.GLOBAL, null);
|
||||
let legacyIconThemeId = this.storageService.get('workbench.iconTheme', StorageScope.GLOBAL, null);
|
||||
|
||||
if (legacyColorThemeId || legacyIconThemeId) {
|
||||
this.storageService.remove('workbench.theme', StorageScope.GLOBAL);
|
||||
this.storageService.remove('workbench.iconTheme', StorageScope.GLOBAL);
|
||||
return Promise.join([
|
||||
this.findThemeData(legacyColorThemeId, DEFAULT_THEME_ID).then(theme => {
|
||||
let themeId = theme ? theme.id : DEFAULT_THEME_ID;
|
||||
let target = themeId !== DEFAULT_THEME_ID ? ConfigurationTarget.USER : null;
|
||||
return this.setColorTheme(themeId, target);
|
||||
}),
|
||||
this._findIconThemeData(legacyIconThemeId).then(theme => {
|
||||
let themeId = theme && theme.id;
|
||||
let target = themeId !== DEFAULT_THEME_ID ? ConfigurationTarget.USER : null;
|
||||
return this.setFileIconTheme(themeId, target);
|
||||
})
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
let colorThemeSetting = this.configurationService.lookup<string>(COLOR_THEME_SETTING).value;
|
||||
let iconThemeSetting = this.configurationService.lookup<string>(ICON_THEME_SETTING).value || '';
|
||||
|
||||
return Promise.join([
|
||||
this.findThemeDataBySettingsId(colorThemeSetting, DEFAULT_THEME_ID).then(theme => {
|
||||
return this.setColorTheme(theme && theme.id, null);
|
||||
}),
|
||||
this.findIconThemeBySettingsId(iconThemeSetting).then(theme => {
|
||||
return this.setFileIconTheme(theme && theme.id, null);
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
public setColorTheme(themeId: string, broadcastToAllWindows: boolean): TPromise<IColorTheme> {
|
||||
public setColorTheme(themeId: string, settingsTarget: ConfigurationTarget): TPromise<IColorTheme> {
|
||||
if (!themeId) {
|
||||
return TPromise.as(null);
|
||||
}
|
||||
if (themeId === this.currentColorTheme.id && this.currentColorTheme.isLoaded) {
|
||||
if (broadcastToAllWindows) {
|
||||
this.windowService.broadcast({ channel: COLOR_THEME_CHANNEL, payload: themeId });
|
||||
}
|
||||
return TPromise.as(this.currentColorTheme);
|
||||
return this.writeColorThemeConfiguration(settingsTarget);
|
||||
}
|
||||
|
||||
themeId = validateThemeId(themeId); // migrate theme ids
|
||||
|
||||
let onApply = (newTheme: IInternalColorThemeData) => {
|
||||
let onApply = (newTheme: ColorThemeData) => {
|
||||
let newThemeId = newTheme.id;
|
||||
if (this.container) {
|
||||
if (this.currentColorTheme) {
|
||||
|
@ -332,45 +390,61 @@ export class ThemeService implements IThemeService {
|
|||
}
|
||||
this.currentColorTheme = newTheme;
|
||||
|
||||
this.storageService.store(COLOR_THEME_PREF, newThemeId, StorageScope.GLOBAL);
|
||||
if (broadcastToAllWindows) {
|
||||
this.windowService.broadcast({ channel: COLOR_THEME_CHANNEL, payload: newThemeId });
|
||||
} else {
|
||||
this.sendTelemetry(newTheme.id, newTheme.extensionData, 'color');
|
||||
}
|
||||
this.sendTelemetry(newTheme.id, newTheme.extensionData, 'color');
|
||||
|
||||
this.onColorThemeChange.fire(this.currentColorTheme);
|
||||
return this.currentColorTheme;
|
||||
|
||||
return this.writeColorThemeConfiguration(settingsTarget);
|
||||
};
|
||||
|
||||
return this.applyThemeCSS(themeId, DEFAULT_THEME_ID, onApply);
|
||||
return this.findThemeData(themeId, DEFAULT_THEME_ID).then(themeData => {
|
||||
if (themeData) {
|
||||
return applyTheme(themeData, onApply);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
private writeColorThemeConfiguration(settingsTarget: ConfigurationTarget) {
|
||||
if (!types.isUndefinedOrNull(settingsTarget)) {
|
||||
return this.configurationEditingService.writeConfiguration(settingsTarget, { key: COLOR_THEME_SETTING, value: this.currentColorTheme.settingsId }).then(_ => {
|
||||
return this.currentColorTheme;
|
||||
});
|
||||
}
|
||||
return TPromise.as(this.currentColorTheme);
|
||||
}
|
||||
|
||||
public getColorTheme() {
|
||||
return this.currentColorTheme;
|
||||
}
|
||||
|
||||
private findThemeData(themeId: string, defaultId?: string): TPromise<IInternalColorThemeData> {
|
||||
private findThemeData(themeId: string, defaultId?: string): TPromise<ColorThemeData> {
|
||||
return this.getColorThemes().then(allThemes => {
|
||||
let themes = allThemes.filter(t => t.id === themeId);
|
||||
if (themes.length > 0) {
|
||||
return <IInternalColorThemeData>themes[0];
|
||||
}
|
||||
if (defaultId) {
|
||||
let themes = allThemes.filter(t => t.id === defaultId);
|
||||
if (themes.length > 0) {
|
||||
return <IInternalColorThemeData>themes[0];
|
||||
let defaultTheme = void 0;
|
||||
for (let t of allThemes) {
|
||||
if (t.id === themeId) {
|
||||
return t;
|
||||
}
|
||||
if (t.id === defaultId) {
|
||||
defaultTheme = t;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return defaultTheme;
|
||||
});
|
||||
}
|
||||
|
||||
private applyThemeCSS(themeId: string, defaultId: string, onApply: (theme: IInternalColorThemeData) => IColorTheme): TPromise<IColorTheme> {
|
||||
return this.findThemeData(themeId, defaultId).then(theme => {
|
||||
if (theme) {
|
||||
return applyTheme(theme, onApply);
|
||||
private findThemeDataBySettingsId(settingsId: string, defaultId: string): TPromise<ColorThemeData> {
|
||||
return this.getColorThemes().then(allThemes => {
|
||||
let defaultTheme = void 0;
|
||||
for (let t of allThemes) {
|
||||
if (t.settingsId === settingsId) {
|
||||
return t;
|
||||
}
|
||||
if (t.id === defaultId) {
|
||||
defaultTheme = t;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return defaultTheme;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -390,7 +464,7 @@ export class ThemeService implements IThemeService {
|
|||
return;
|
||||
}
|
||||
themes.forEach(theme => {
|
||||
if (!theme.path || (typeof theme.path !== 'string')) {
|
||||
if (!theme.path || !types.isString(theme.path)) {
|
||||
collector.error(nls.localize(
|
||||
'reqpath',
|
||||
"Expected string in `contributes.{0}.path`. Provided value: {1}",
|
||||
|
@ -405,15 +479,19 @@ export class ThemeService implements IThemeService {
|
|||
collector.warn(nls.localize('invalid.path.1', "Expected `contributes.{0}.path` ({1}) to be included inside extension's folder ({2}). This might make the extension non-portable.", themesExtPoint.name, normalizedAbsolutePath, extensionFolderPath));
|
||||
}
|
||||
|
||||
let baseTheme = theme.uiTheme || defaultBaseTheme;
|
||||
|
||||
let themeSelector = toCSSSelector(extensionData.extensionId + '-' + Paths.normalize(theme.path));
|
||||
this.knownColorThemes.push({
|
||||
id: `${theme.uiTheme || defaultBaseTheme} ${themeSelector}`,
|
||||
label: theme.label || Paths.basename(theme.path),
|
||||
description: theme.description,
|
||||
path: normalizedAbsolutePath,
|
||||
extensionData: extensionData,
|
||||
isLoaded: false
|
||||
});
|
||||
let themeData = new ColorThemeData();
|
||||
themeData.id = `${baseTheme} ${themeSelector}`;
|
||||
themeData.label = theme.label || Paths.basename(theme.path);
|
||||
themeData.settingsId = settingsIdPrefix[baseTheme] + (theme.id || themeData.label);
|
||||
themeData.description = theme.description;
|
||||
themeData.path = normalizedAbsolutePath;
|
||||
themeData.extensionData = extensionData;
|
||||
themeData.isLoaded = false;
|
||||
|
||||
this.knownColorThemes.push(themeData);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -427,7 +505,7 @@ export class ThemeService implements IThemeService {
|
|||
return;
|
||||
}
|
||||
iconThemes.forEach(iconTheme => {
|
||||
if (!iconTheme.path || (typeof iconTheme.path !== 'string')) {
|
||||
if (!iconTheme.path || !types.isString(iconTheme.path)) {
|
||||
collector.error(nls.localize(
|
||||
'reqpath',
|
||||
"Expected string in `contributes.{0}.path`. Provided value: {1}",
|
||||
|
@ -436,7 +514,7 @@ export class ThemeService implements IThemeService {
|
|||
));
|
||||
return;
|
||||
}
|
||||
if (!iconTheme.id || (typeof iconTheme.id !== 'string')) {
|
||||
if (!iconTheme.id || !types.isString(iconTheme.id)) {
|
||||
collector.error(nls.localize(
|
||||
'reqid',
|
||||
"Expected string in `contributes.{0}.id`. Provided value: {1}",
|
||||
|
@ -454,6 +532,7 @@ export class ThemeService implements IThemeService {
|
|||
this.knownIconThemes.push({
|
||||
id: extensionData.extensionId + '-' + iconTheme.id,
|
||||
label: iconTheme.label || Paths.basename(iconTheme.path),
|
||||
settingsId: iconTheme.id,
|
||||
description: iconTheme.description,
|
||||
path: normalizedAbsolutePath,
|
||||
extensionData: extensionData,
|
||||
|
@ -487,13 +566,10 @@ export class ThemeService implements IThemeService {
|
|||
return this.currentIconTheme;
|
||||
}
|
||||
|
||||
public setFileIconTheme(iconTheme: string, broadcastToAllWindows: boolean): TPromise<IColorTheme> {
|
||||
public setFileIconTheme(iconTheme: string, settingsTarget: ConfigurationTarget): TPromise<IFileIconTheme> {
|
||||
iconTheme = iconTheme || '';
|
||||
if (iconTheme === this.currentIconTheme.id && this.currentIconTheme.isLoaded) {
|
||||
if (broadcastToAllWindows) {
|
||||
this.windowService.broadcast({ channel: ICON_THEME_CHANNEL, payload: iconTheme });
|
||||
}
|
||||
return TPromise.as(this.currentIconTheme);
|
||||
return this.writeFileIconConfiguration(settingsTarget);
|
||||
}
|
||||
let onApply = (newIconTheme: IInternalIconThemeData) => {
|
||||
if (newIconTheme) {
|
||||
|
@ -501,6 +577,7 @@ export class ThemeService implements IThemeService {
|
|||
} else {
|
||||
this.currentIconTheme = noFileIconTheme;
|
||||
}
|
||||
|
||||
if (this.container) {
|
||||
if (newIconTheme) {
|
||||
$(this.container).addClass(fileIconsEnabledClass);
|
||||
|
@ -508,36 +585,51 @@ export class ThemeService implements IThemeService {
|
|||
$(this.container).removeClass(fileIconsEnabledClass);
|
||||
}
|
||||
}
|
||||
|
||||
this.storageService.store(ICON_THEME_PREF, this.currentIconTheme.id, StorageScope.GLOBAL);
|
||||
if (broadcastToAllWindows) {
|
||||
this.windowService.broadcast({ channel: ICON_THEME_CHANNEL, payload: this.currentIconTheme.id });
|
||||
} else if (newIconTheme) {
|
||||
if (newIconTheme) {
|
||||
this.sendTelemetry(newIconTheme.id, newIconTheme.extensionData, 'fileIcon');
|
||||
}
|
||||
this.onFileIconThemeChange.fire(this.currentIconTheme);
|
||||
return this.currentIconTheme;
|
||||
return this.writeFileIconConfiguration(settingsTarget);
|
||||
};
|
||||
|
||||
|
||||
return this._updateIconTheme(iconTheme, onApply);
|
||||
return this._findIconThemeData(iconTheme).then(iconThemeData => {
|
||||
return _applyIconTheme(iconThemeData, onApply);
|
||||
});
|
||||
}
|
||||
|
||||
private _updateIconTheme(iconTheme: string, onApply: (theme: IInternalIconThemeData) => IFileIconTheme): TPromise<IFileIconTheme> {
|
||||
private writeFileIconConfiguration(settingsTarget: ConfigurationTarget): TPromise<IFileIconTheme> {
|
||||
if (!types.isUndefinedOrNull(settingsTarget)) {
|
||||
return this.configurationEditingService.writeConfiguration(settingsTarget, { key: ICON_THEME_SETTING, value: this.currentIconTheme.settingsId }).then(_ => {
|
||||
return this.currentIconTheme;
|
||||
});
|
||||
}
|
||||
return TPromise.as(this.currentIconTheme);
|
||||
}
|
||||
|
||||
private _findIconThemeData(iconTheme: string): TPromise<IInternalIconThemeData> {
|
||||
return this.getFileIconThemes().then(allIconSets => {
|
||||
let iconSetData: IInternalIconThemeData;
|
||||
for (let iconSet of allIconSets) {
|
||||
if (iconSet.id === iconTheme) {
|
||||
iconSetData = <IInternalIconThemeData>iconSet;
|
||||
break;
|
||||
return <IInternalIconThemeData>iconSet;
|
||||
}
|
||||
}
|
||||
return _applyIconTheme(iconSetData, onApply);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
private findIconThemeBySettingsId(settingsId: string): TPromise<IFileIconTheme> {
|
||||
return this.getFileIconThemes().then(allIconSets => {
|
||||
for (let iconSet of allIconSets) {
|
||||
if (iconSet.settingsId === settingsId) {
|
||||
return iconSet;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function _applyIconTheme(data: IInternalIconThemeData, onApply: (theme: IInternalIconThemeData) => IFileIconTheme): TPromise<IFileIconTheme> {
|
||||
function _applyIconTheme(data: IInternalIconThemeData, onApply: (theme: IInternalIconThemeData) => TPromise<IFileIconTheme>): TPromise<IFileIconTheme> {
|
||||
if (!data) {
|
||||
_applyRules('', iconThemeRulesClassName);
|
||||
return TPromise.as(onApply(data));
|
||||
|
@ -728,7 +820,7 @@ function toCSSSelector(str: string) {
|
|||
return str;
|
||||
}
|
||||
|
||||
function applyTheme(theme: IInternalColorThemeData, onApply: (theme: IInternalColorThemeData) => IColorTheme): TPromise<IColorTheme> {
|
||||
function applyTheme(theme: ColorThemeData, onApply: (theme: ColorThemeData) => TPromise<IColorTheme>): TPromise<IColorTheme> {
|
||||
if (theme.styleSheetContent) {
|
||||
_applyRules(theme.styleSheetContent, colorThemeRulesClassName);
|
||||
return TPromise.as(onApply(theme));
|
||||
|
@ -755,7 +847,7 @@ function _loadThemeDocument(baseTheme: string, themePath: string): TPromise<IThe
|
|||
return TPromise.wrapError(new Error(nls.localize('error.cannotparsejson', "Problems parsing JSON theme file: {0}", errors.map(e => Json.getParseErrorMessage(e.error)).join(', '))));
|
||||
}
|
||||
if (!Array.isArray(contentValue.settings)) {
|
||||
return TPromise.wrapError(new Error(nls.localize('error.invalidformat', "Problem parsing JSON theme file: {0}. 'settings' is not array.")));
|
||||
return TPromise.wrapError(new Error(nls.localize({ key: 'error.invalidformat', comment: ['{0} will be replaced by a path. "settings" must not be translated.'] }, "Problem parsing JSON theme file: {0}. 'settings' is not array.")));
|
||||
}
|
||||
allSettings = allSettings.concat(contentValue.settings); // will clone
|
||||
if (contentValue.include) {
|
||||
|
@ -1013,4 +1105,24 @@ const schema: IJSONSchema = {
|
|||
};
|
||||
|
||||
let schemaRegistry = <IJSONContributionRegistry>Registry.as(JSONExtensions.JSONContribution);
|
||||
schemaRegistry.registerSchema(schemaId, schema);
|
||||
schemaRegistry.registerSchema(schemaId, schema);
|
||||
|
||||
// Configuration: Workbench
|
||||
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
|
||||
configurationRegistry.registerConfiguration({
|
||||
'id': 'workbench',
|
||||
'order': 7.1,
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
[COLOR_THEME_SETTING]: {
|
||||
'type': 'string',
|
||||
'description': nls.localize('colorTheme', "Specifies the color theme used in the workbench."),
|
||||
'default': DEFAULT_THEME_NAME
|
||||
},
|
||||
[ICON_THEME_SETTING]: {
|
||||
'type': ['string', 'null'],
|
||||
'default': null,
|
||||
'description': nls.localize('iconTheme', "Specifies the icon theme used in the workbench.")
|
||||
}
|
||||
}
|
||||
});
|
Loading…
Reference in a new issue