提交 35204a12 编写于 作者: S Sandeep Somavarapu

extract editor styles and settings

上级 ed7ba30c
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export interface RGBA { r: number; g: number; b: number; a: number; }
export class Color {
private parsed: RGBA;
private str: string;
constructor(arg: string | RGBA) {
if (typeof arg === 'string') {
this.parsed = Color.parse(<string>arg);
} else {
this.parsed = <RGBA>arg;
}
this.str = null;
}
private static parse(color: string): RGBA {
function parseHex(str: string) {
return parseInt('0x' + str);
}
if (color.charAt(0) === '#' && color.length >= 7) {
let r = parseHex(color.substr(1, 2));
let g = parseHex(color.substr(3, 2));
let b = parseHex(color.substr(5, 2));
let a = color.length === 9 ? parseHex(color.substr(7, 2)) / 0xff : 1;
return { r, g, b, a };
}
return { r: 255, g: 0, b: 0, a: 1 };
}
public toString(): string {
if (!this.str) {
let p = this.parsed;
this.str = `rgba(${p.r}, ${p.g}, ${p.b}, ${+p.a.toFixed(2)})`;
}
return this.str;
}
public transparent(factor: number): Color {
let p = this.parsed;
return new Color({ r: p.r, g: p.g, b: p.b, a: p.a * factor });
}
public opposite(): Color {
return new Color({
r: 255 - this.parsed.r,
g: 255 - this.parsed.g,
b: 255 - this.parsed.b,
a : this.parsed.a
});
}
}
\ No newline at end of file
......@@ -27,4 +27,19 @@ export interface IThemeData {
label: string;
description?: string;
path: string;
}
export interface IThemeDocument {
name: string;
include: string;
settings: IThemeSetting[];
}
export interface IThemeSetting {
name?: string;
scope?: string[];
settings: IThemeSettingStyle[];
}
export interface IThemeSettingStyle {
}
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import {IThemeDocument, IThemeSetting, IThemeSettingStyle} from 'vs/workbench/services/themes/common/themeService';
import {Color} from 'vs/workbench/services/themes/common/color';
import {getBaseThemeId, getSyntaxThemeId} from 'vs/platform/theme/common/themes';
export class TokenStylesContribution {
public contributeStyles(themeId: string, themeDocument: IThemeDocument): string[] {
let cssRules = [];
let editorStyles = new EditorStyles(themeId, themeDocument);
themeDocument.settings.forEach((s: IThemeSetting, index, arr) => {
let scope: string | string[] = s.scope;
let settings = s.settings;
if (scope && settings) {
let rules = Array.isArray(scope) ? <string[]>scope : scope.split(',');
let statements = this._settingsToStatements(settings);
rules.forEach(rule => {
rule = rule.trim().replace(/ /g, '.'); // until we have scope hierarchy in the editor dom: replace spaces with .
cssRules.push(`.monaco-editor.${editorStyles.themeSelector} .token.${rule} { ${statements} }`);
});
}
});
return cssRules;
}
private _settingsToStatements(settings: IThemeSettingStyle): string {
let statements: string[] = [];
for (let settingName in settings) {
const value = settings[settingName];
switch (settingName) {
case 'foreground':
let foreground = new Color(value);
statements.push(`color: ${foreground};`);
break;
case 'background':
// do not support background color for now, see bug 18924
//let background = new Color(value);
//statements.push(`background-color: ${background};`);
break;
case 'fontStyle':
let segments = value.split(' ');
segments.forEach(s => {
switch (s) {
case 'italic':
statements.push(`font-style: italic;`);
break;
case 'bold':
statements.push(`font-weight: bold;`);
break;
case 'underline':
statements.push(`text-decoration: underline;`);
break;
}
});
}
}
return statements.join(' ');
}
}
export class EditorStylesContribution {
public contributeStyles(themeId: string, themeDocument: IThemeDocument): string[] {
let cssRules = [];
let editorStyles = new EditorStyles(themeId, themeDocument);
if (editorStyles.editorStyleSettings) {
let themeSelector = editorStyles.themeSelector;
if (editorStyles.editorStyleSettings.background) {
let background = new Color(editorStyles.editorStyleSettings.background);
cssRules.push(`.monaco-editor.${themeSelector} .monaco-editor-background { background-color: ${background}; }`);
cssRules.push(`.monaco-editor.${themeSelector} .glyph-margin { background-color: ${background}; }`);
cssRules.push(`.${themeSelector} .monaco-workbench .monaco-editor-background { background-color: ${background}; }`);
}
if (editorStyles.editorStyleSettings.foreground) {
let foreground = new Color(editorStyles.editorStyleSettings.foreground);
cssRules.push(`.monaco-editor.${themeSelector} .token { color: ${foreground}; }`);
}
if (editorStyles.editorStyleSettings.selection) {
let selection = new Color(editorStyles.editorStyleSettings.selection);
cssRules.push(`.monaco-editor.${themeSelector} .focused .selected-text { background-color: ${selection}; }`);
cssRules.push(`.monaco-editor.${themeSelector} .selected-text { background-color: ${selection.transparent(0.5)}; }`);
}
if (editorStyles.editorStyleSettings.selectionHighlight) {
let selection = new Color(editorStyles.editorStyleSettings.selectionHighlight);
cssRules.push(`.monaco-editor.${themeSelector} .selectionHighlight { background-color: ${selection}; }`);
}
if (editorStyles.editorStyleSettings.wordHighlight) {
let selection = new Color(editorStyles.editorStyleSettings.wordHighlight);
cssRules.push(`.monaco-editor.${themeSelector} .wordHighlight { background-color: ${selection}; }`);
}
if (editorStyles.editorStyleSettings.wordHighlightStrong) {
let selection = new Color(editorStyles.editorStyleSettings.wordHighlightStrong);
cssRules.push(`.monaco-editor.${themeSelector} .wordHighlightStrong { background-color: ${selection}; }`);
}
if (editorStyles.editorStyleSettings.findLineHighlight) {
let selection = new Color(editorStyles.editorStyleSettings.findLineHighlight);
cssRules.push(`.monaco-editor.${themeSelector} .findLineHighlight { background-color: ${selection}; }`);
}
if (editorStyles.editorStyleSettings.lineHighlight) {
let lineHighlight = new Color(editorStyles.editorStyleSettings.lineHighlight);
cssRules.push(`.monaco-editor.${themeSelector} .current-line { background-color: ${lineHighlight}; border:0; }`);
}
if (editorStyles.editorStyleSettings.caret) {
let caret = new Color(editorStyles.editorStyleSettings.caret);
let oppositeCaret = caret.opposite();
cssRules.push(`.monaco-editor.${themeSelector} .cursor { background-color: ${caret}; border-color: ${caret}; color: ${oppositeCaret}; }`);
}
if (editorStyles.editorStyleSettings.invisibles) {
let invisibles = new Color(editorStyles.editorStyleSettings.invisibles);
cssRules.push(`.monaco-editor.${themeSelector} .token.whitespace { color: ${invisibles} !important; }`);
}
if (editorStyles.editorStyleSettings.guide) {
let guide = new Color(editorStyles.editorStyleSettings.guide);
cssRules.push(`.monaco-editor.${themeSelector} .lines-content .cigr { background: ${guide}; }`);
} else if (editorStyles.editorStyleSettings.invisibles) {
let invisibles = new Color(editorStyles.editorStyleSettings.invisibles);
cssRules.push(`.monaco-editor.${themeSelector} .lines-content .cigr { background: ${invisibles}; }`);
}
}
return cssRules;
}
}
interface EditorStyleSettings {
background?: string;
foreground?: string;
fontStyle?: string;
caret?: string;
invisibles?: string;
guide?: string;
lineHighlight?: string;
selection?: string;
selectionHighlight?: string;
findLineHighlight?: string;
wordHighlight?: string;
wordHighlightStrong?: string;
}
class EditorStyles {
public themeSelector: string;
public editorStyleSettings: EditorStyleSettings = null;
constructor(themeId: string, themeDocument: IThemeDocument) {
this.themeSelector = `${getBaseThemeId(themeId)}.${getSyntaxThemeId(themeId)}`;
let settings = themeDocument.settings[0];
if (!settings.scope) {
this.editorStyleSettings = settings.settings;
}
}
}
\ No newline at end of file
......@@ -11,8 +11,9 @@ import Json = require('vs/base/common/json');
import {IThemeExtensionPoint} from 'vs/platform/theme/common/themeExtensionPoint';
import {IExtensionService} from 'vs/platform/extensions/common/extensions';
import {ExtensionsRegistry, IExtensionMessageCollector} from 'vs/platform/extensions/common/extensionsRegistry';
import {IThemeService, IThemeData} from 'vs/workbench/services/themes/common/themeService';
import {getBaseThemeId, getSyntaxThemeId} from 'vs/platform/theme/common/themes';
import {IThemeService, IThemeData, IThemeSetting, IThemeDocument} from 'vs/workbench/services/themes/common/themeService';
import {TokenStylesContribution, EditorStylesContribution} from 'vs/workbench/services/themes/electron-browser/editorStyles';
import {getBaseThemeId} from 'vs/platform/theme/common/themes';
import {IWindowService} from 'vs/workbench/services/window/electron-browser/windowService';
import {IStorageService, StorageScope} from 'vs/platform/storage/common/storage';
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
......@@ -100,29 +101,6 @@ let iconThemeExtPoint = ExtensionsRegistry.registerExtensionPoint<IThemeExtensio
}
});
interface ThemeSettingStyle {
background?: string;
foreground?: string;
fontStyle?: string;
caret?: string;
invisibles?: string;
guide?: string;
lineHighlight?: string;
selection?: string;
}
interface ThemeSetting {
name?: string;
scope?: string | string[];
settings: ThemeSettingStyle[];
}
interface ThemeDocument {
name: string;
include: string;
settings: ThemeSetting[];
}
interface IInternalThemeData extends IThemeData {
styleSheetContent?: string;
extensionId: string;
......@@ -469,7 +447,7 @@ function _applyIconTheme(data: IInternalThemeData, onApply: (theme:IInternalThem
function _loadIconThemeDocument(fileSetPath: string) : TPromise<IconThemeDocument> {
return pfs.readFile(fileSetPath).then(content => {
let errors: Json.ParseError[] = [];
let contentValue = <ThemeDocument> Json.parse(content.toString(), errors);
let contentValue = <IThemeDocument> Json.parse(content.toString(), errors);
if (errors.length > 0) {
return TPromise.wrapError(new Error(nls.localize('error.cannotparseicontheme', "Problems parsing file icons file: {0}", errors.map(e => Json.getParseErrorMessage(e.error)).join(', '))));
}
......@@ -621,11 +599,11 @@ function applyTheme(theme: IInternalThemeData, onApply: (theme:IInternalThemeDat
});
}
function _loadThemeDocument(themePath: string) : TPromise<ThemeDocument> {
function _loadThemeDocument(themePath: string) : TPromise<IThemeDocument> {
return pfs.readFile(themePath).then(content => {
if (Paths.extname(themePath) === '.json') {
let errors: Json.ParseError[] = [];
let contentValue = <ThemeDocument> Json.parse(content.toString(), errors);
let contentValue = <IThemeDocument> Json.parse(content.toString(), errors);
if (errors.length > 0) {
return TPromise.wrapError(new Error(nls.localize('error.cannotparsejson', "Problems parsing JSON theme file: {0}", errors.map(e => Json.getParseErrorMessage(e.error)).join(', '))));
}
......@@ -645,116 +623,18 @@ function _loadThemeDocument(themePath: string) : TPromise<ThemeDocument> {
});
}
function _processThemeObject(themeId: string, themeDocument: ThemeDocument): string {
function _processThemeObject(themeId: string, themeDocument: IThemeDocument): string {
let cssRules: string[] = [];
let themeSettings : ThemeSetting[] = themeDocument.settings;
let editorSettings : ThemeSettingStyle = {
background: void 0,
foreground: void 0,
caret: void 0,
invisibles: void 0,
guide: void 0,
lineHighlight: void 0,
selection: void 0
};
let themeSelector = `${getBaseThemeId(themeId)}.${getSyntaxThemeId(themeId)}`;
let themeSettings : IThemeSetting[] = themeDocument.settings;
if (Array.isArray(themeSettings)) {
themeSettings.forEach((s : ThemeSetting, index, arr) => {
if (index === 0 && !s.scope) {
editorSettings = s.settings;
} else {
let scope: string | string[] = s.scope;
let settings = s.settings;
if (scope && settings) {
let rules = Array.isArray(scope) ? <string[]> scope : scope.split(',');
let statements = _settingsToStatements(settings);
rules.forEach(rule => {
rule = rule.trim().replace(/ /g, '.'); // until we have scope hierarchy in the editor dom: replace spaces with .
cssRules.push(`.monaco-editor.${themeSelector} .token.${rule} { ${statements} }`);
});
}
}
});
}
if (editorSettings.background) {
let background = new Color(editorSettings.background);
cssRules.push(`.monaco-editor.${themeSelector} .monaco-editor-background { background-color: ${background}; }`);
cssRules.push(`.monaco-editor.${themeSelector} .glyph-margin { background-color: ${background}; }`);
cssRules.push(`.${themeSelector} .monaco-workbench .monaco-editor-background { background-color: ${background}; }`);
}
if (editorSettings.foreground) {
let foreground = new Color(editorSettings.foreground);
cssRules.push(`.monaco-editor.${themeSelector} .token { color: ${foreground}; }`);
}
if (editorSettings.selection) {
let selection = new Color(editorSettings.selection);
cssRules.push(`.monaco-editor.${themeSelector} .focused .selected-text { background-color: ${selection}; }`);
cssRules.push(`.monaco-editor.${themeSelector} .selected-text { background-color: ${selection.transparent(0.5)}; }`);
}
if (editorSettings.lineHighlight) {
let lineHighlight = new Color(editorSettings.lineHighlight);
cssRules.push(`.monaco-editor.${themeSelector} .current-line { background-color: ${lineHighlight}; border:0; }`);
}
if (editorSettings.caret) {
let caret = new Color(editorSettings.caret);
let oppositeCaret = caret.opposite();
cssRules.push(`.monaco-editor.${themeSelector} .cursor { background-color: ${caret}; border-color: ${caret}; color: ${oppositeCaret}; }`);
}
if (editorSettings.invisibles) {
let invisibles = new Color(editorSettings.invisibles);
cssRules.push(`.monaco-editor.${themeSelector} .token.whitespace { color: ${invisibles} !important; }`);
}
if (editorSettings.guide) {
let guide = new Color(editorSettings.guide);
cssRules.push(`.monaco-editor.${themeSelector} .lines-content .cigr { background: ${guide}; }`);
} else if (editorSettings.invisibles) {
let invisibles = new Color(editorSettings.invisibles);
cssRules.push(`.monaco-editor.${themeSelector} .lines-content .cigr { background: ${invisibles}; }`);
cssRules= cssRules.concat(new TokenStylesContribution().contributeStyles(themeId, themeDocument));
cssRules= cssRules.concat(new EditorStylesContribution().contributeStyles(themeId, themeDocument));
}
return cssRules.join('\n');
}
function _settingsToStatements(settings: ThemeSettingStyle): string {
let statements: string[] = [];
for (let settingName in settings) {
const value = settings[settingName];
switch (settingName) {
case 'foreground':
let foreground = new Color(value);
statements.push(`color: ${foreground};`);
break;
case 'background':
// do not support background color for now, see bug 18924
//let background = new Color(value);
//statements.push(`background-color: ${background};`);
break;
case 'fontStyle':
let segments = value.split(' ');
segments.forEach(s => {
switch (s) {
case 'italic':
statements.push(`font-style: italic;`);
break;
case 'bold':
statements.push(`font-weight: bold;`);
break;
case 'underline':
statements.push(`text-decoration: underline;`);
break;
}
});
}
}
return statements.join(' ');
}
let colorThemeRulesClassName = 'contributedColorTheme';
let iconThemeRulesClassName = 'contributedIconTheme';
......@@ -771,60 +651,6 @@ function _applyRules(styleSheetContent: string, rulesClassName: string) {
}
}
interface RGBA { r: number; g: number; b: number; a: number; }
class Color {
private parsed: RGBA;
private str: string;
constructor(arg: string | RGBA) {
if (typeof arg === 'string') {
this.parsed = Color.parse(<string>arg);
} else {
this.parsed = <RGBA>arg;
}
this.str = null;
}
private static parse(color: string): RGBA {
function parseHex(str: string) {
return parseInt('0x' + str);
}
if (color.charAt(0) === '#' && color.length >= 7) {
let r = parseHex(color.substr(1, 2));
let g = parseHex(color.substr(3, 2));
let b = parseHex(color.substr(5, 2));
let a = color.length === 9 ? parseHex(color.substr(7, 2)) / 0xff : 1;
return { r, g, b, a };
}
return { r: 255, g: 0, b: 0, a: 1 };
}
public toString(): string {
if (!this.str) {
let p = this.parsed;
this.str = `rgba(${p.r}, ${p.g}, ${p.b}, ${+p.a.toFixed(2)})`;
}
return this.str;
}
public transparent(factor: number): Color {
let p = this.parsed;
return new Color({ r: p.r, g: p.g, b: p.b, a: p.a * factor });
}
public opposite(): Color {
return new Color({
r: 255 - this.parsed.r,
g: 255 - this.parsed.g,
b: 255 - this.parsed.b,
a : this.parsed.a
});
}
}
const schemaId = 'vscode://schemas/icon-theme';
const schema: IJSONSchema = {
type: 'object',
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册