mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-28 12:33:35 +01:00
Fix #32235. Functional style formatter. Color range is all float number and remove fromHex, fromHSL methods.
This commit is contained in:
@@ -679,12 +679,23 @@ export interface IColor {
|
||||
readonly alpha: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a color format
|
||||
*/
|
||||
export enum ColorFormat {
|
||||
RGB = 0,
|
||||
HEX = 1,
|
||||
HSL = 2
|
||||
}
|
||||
|
||||
/**
|
||||
* A color formatter.
|
||||
* @internal
|
||||
*/
|
||||
export interface IColorFormatter {
|
||||
readonly supportsTransparency: boolean;
|
||||
format(color: IColor): string;
|
||||
readonly colorFormat: ColorFormat;
|
||||
format(color: Color): string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -701,11 +712,6 @@ export interface IColorRange {
|
||||
* The color represented in this range.
|
||||
*/
|
||||
color: IColor;
|
||||
|
||||
/**
|
||||
* The available formats for this specific color.
|
||||
*/
|
||||
formatters: IColorFormatter[];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -716,6 +722,10 @@ export interface DocumentColorProvider {
|
||||
* Provides the color ranges for a specific model.
|
||||
*/
|
||||
provideColorRanges(model: editorCommon.IReadOnlyModel, token: CancellationToken): IColorRange[] | Thenable<IColorRange[]>;
|
||||
/**
|
||||
* Provide the string representation for a color.
|
||||
*/
|
||||
resolveColor(color: IColor, colorFormat: ColorFormat, token: CancellationToken): string | Thenable<string>;
|
||||
}
|
||||
|
||||
export interface IResourceEdit {
|
||||
|
||||
@@ -12,9 +12,9 @@ import { editorContribution } from 'vs/editor/browser/editorBrowserExtensions';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { ColorProviderRegistry, IColorRange } from 'vs/editor/common/modes';
|
||||
import { ColorProviderRegistry } from 'vs/editor/common/modes';
|
||||
import { ICodeEditorService } from 'vs/editor/common/services/codeEditorService';
|
||||
import { getColors } from 'vs/editor/contrib/colorPicker/common/color';
|
||||
import { getColors, IColorData } from 'vs/editor/contrib/colorPicker/common/color';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
|
||||
const MAX_DECORATORS = 500;
|
||||
@@ -32,7 +32,7 @@ export class ColorDetector implements IEditorContribution {
|
||||
private _timeoutPromise: TPromise<void>;
|
||||
|
||||
private _decorationsIds: string[] = [];
|
||||
private _colorRanges = new Map<string, IColorRange>();
|
||||
private _colorDatas = new Map<string, IColorData>();
|
||||
|
||||
private _colorDecoratorIds: string[] = [];
|
||||
private _decorationsTypes: { [key: string]: boolean } = {};
|
||||
@@ -146,35 +146,29 @@ export class ColorDetector implements IEditorContribution {
|
||||
this._localToDispose = dispose(this._localToDispose);
|
||||
}
|
||||
|
||||
private updateDecorations(colorInfos: IColorRange[]): void {
|
||||
const decorations = colorInfos.map(c => ({
|
||||
private updateDecorations(colorDatas: IColorData[]): void {
|
||||
const decorations = colorDatas.map(c => ({
|
||||
range: {
|
||||
startLineNumber: c.range.startLineNumber,
|
||||
startColumn: c.range.startColumn,
|
||||
endLineNumber: c.range.endLineNumber,
|
||||
endColumn: c.range.endColumn
|
||||
startLineNumber: c.colorRange.range.startLineNumber,
|
||||
startColumn: c.colorRange.range.startColumn,
|
||||
endLineNumber: c.colorRange.range.endLineNumber,
|
||||
endColumn: c.colorRange.range.endColumn
|
||||
},
|
||||
options: {}
|
||||
}));
|
||||
|
||||
const colorRanges = colorInfos.map(c => ({
|
||||
range: c.range,
|
||||
color: c.color,
|
||||
formatters: c.formatters
|
||||
}));
|
||||
|
||||
this._decorationsIds = this._editor.deltaDecorations(this._decorationsIds, decorations);
|
||||
|
||||
this._colorRanges = new Map<string, IColorRange>();
|
||||
this._decorationsIds.forEach((id, i) => this._colorRanges.set(id, colorRanges[i]));
|
||||
this._colorDatas = new Map<string, IColorData>();
|
||||
this._decorationsIds.forEach((id, i) => this._colorDatas.set(id, colorDatas[i]));
|
||||
}
|
||||
|
||||
private updateColorDecorators(colorInfos: IColorRange[]): void {
|
||||
private updateColorDecorators(colorInfos: IColorData[]): void {
|
||||
let decorations = [];
|
||||
let newDecorationsTypes: { [key: string]: boolean } = {};
|
||||
|
||||
for (let i = 0; i < colorInfos.length && decorations.length < MAX_DECORATORS; i++) {
|
||||
const { red, green, blue, alpha } = colorInfos[i].color;
|
||||
const { red, green, blue, alpha } = colorInfos[i].colorRange.color;
|
||||
const rgba = new RGBA(Math.round(red * 255), Math.round(green * 255), Math.round(blue * 255), alpha);
|
||||
let subKey = hash(rgba).toString(16);
|
||||
let color = `rgba(${rgba.r}, ${rgba.g}, ${rgba.b}, ${rgba.a})`;
|
||||
@@ -201,10 +195,10 @@ export class ColorDetector implements IEditorContribution {
|
||||
newDecorationsTypes[key] = true;
|
||||
decorations.push({
|
||||
range: {
|
||||
startLineNumber: colorInfos[i].range.startLineNumber,
|
||||
startColumn: colorInfos[i].range.startColumn,
|
||||
endLineNumber: colorInfos[i].range.endLineNumber,
|
||||
endColumn: colorInfos[i].range.endColumn
|
||||
startLineNumber: colorInfos[i].colorRange.range.startLineNumber,
|
||||
startColumn: colorInfos[i].colorRange.range.startColumn,
|
||||
endLineNumber: colorInfos[i].colorRange.range.endLineNumber,
|
||||
endColumn: colorInfos[i].colorRange.range.endColumn
|
||||
},
|
||||
options: this._codeEditorService.resolveDecorationOptions(key, true)
|
||||
});
|
||||
@@ -228,15 +222,15 @@ export class ColorDetector implements IEditorContribution {
|
||||
}
|
||||
}
|
||||
|
||||
getColorRange(position: Position): IColorRange | null {
|
||||
getColorData(position: Position): IColorData | null {
|
||||
const decorations = this._editor.getModel()
|
||||
.getDecorationsInRange(Range.fromPositions(position, position))
|
||||
.filter(d => this._colorRanges.has(d.id));
|
||||
.filter(d => this._colorDatas.has(d.id));
|
||||
|
||||
if (decorations.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this._colorRanges.get(decorations[0].id);
|
||||
return this._colorDatas.get(decorations[0].id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { IColorFormatter } from 'vs/editor/common/modes';
|
||||
|
||||
function canFormat(formatter: IColorFormatter, color: Color): boolean {
|
||||
return color.isOpaque() || formatter.supportsTransparency;
|
||||
}
|
||||
import { HexFormatter, HSLFormatter, RGBFormatter } from '../common/colorFormatter';
|
||||
|
||||
export class ColorPickerModel {
|
||||
|
||||
@@ -26,7 +23,6 @@ export class ColorPickerModel {
|
||||
}
|
||||
|
||||
this._color = color;
|
||||
this._checkFormat();
|
||||
this._onDidChangeColor.fire(color);
|
||||
}
|
||||
|
||||
@@ -43,46 +39,23 @@ export class ColorPickerModel {
|
||||
private _onDidChangeFormatter = new Emitter<IColorFormatter>();
|
||||
readonly onDidChangeFormatter: Event<IColorFormatter> = this._onDidChangeFormatter.event;
|
||||
|
||||
constructor(color: Color, availableFormatters: IColorFormatter[], private formatterIndex: number) {
|
||||
if (availableFormatters.length === 0) {
|
||||
throw new Error('Color picker needs formats');
|
||||
}
|
||||
|
||||
if (formatterIndex < 0 || formatterIndex >= availableFormatters.length) {
|
||||
throw new Error('Formatter index out of bounds');
|
||||
}
|
||||
|
||||
constructor(color: Color, private formatterIndex: number) {
|
||||
this.originalColor = color;
|
||||
this.formatters = availableFormatters;
|
||||
this._color = color;
|
||||
this.formatters = [
|
||||
new RGBFormatter(),
|
||||
new HexFormatter(),
|
||||
new HSLFormatter()
|
||||
];
|
||||
}
|
||||
|
||||
selectNextColorFormat(): void {
|
||||
const oldFomatterIndex = this.formatterIndex;
|
||||
this._checkFormat((this.formatterIndex + 1) % this.formatters.length);
|
||||
if (oldFomatterIndex !== this.formatterIndex) {
|
||||
this.flushColor();
|
||||
}
|
||||
this.formatterIndex = (this.formatterIndex + 1) % this.formatters.length;
|
||||
this.flushColor();
|
||||
this._onDidChangeFormatter.fire(this.formatter);
|
||||
}
|
||||
|
||||
flushColor(): void {
|
||||
this._onColorFlushed.fire(this._color);
|
||||
}
|
||||
|
||||
private _checkFormat(start = this.formatterIndex): void {
|
||||
let isNewFormat = this.formatterIndex !== start;
|
||||
this.formatterIndex = start;
|
||||
|
||||
while (!canFormat(this.formatter, this._color)) {
|
||||
this.formatterIndex = (this.formatterIndex + 1) % this.formatters.length;
|
||||
|
||||
if (this.formatterIndex === start) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (isNewFormat) {
|
||||
this._onDidChangeFormatter.fire(this.formatter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,12 +55,7 @@ export class ColorPickerHeader extends Disposable {
|
||||
}
|
||||
|
||||
private onDidChangeFormatter(): void {
|
||||
this.pickedColorNode.textContent = this.model.formatter.format({
|
||||
red: this.model.color.rgba.r / 255,
|
||||
green: this.model.color.rgba.g / 255,
|
||||
blue: this.model.color.rgba.b / 255,
|
||||
alpha: this.model.color.rgba.a
|
||||
});
|
||||
this.pickedColorNode.textContent = this.model.formatter.format(this.model.color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,15 +4,29 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { ColorProviderRegistry, IColorRange } from 'vs/editor/common/modes';
|
||||
import { ColorProviderRegistry, DocumentColorProvider, IColorRange, IColor, ColorFormat } from 'vs/editor/common/modes';
|
||||
import { asWinJsPromise } from 'vs/base/common/async';
|
||||
import { IReadOnlyModel } from 'vs/editor/common/editorCommon';
|
||||
import { flatten } from 'vs/base/common/arrays';
|
||||
|
||||
export function getColors(model: IReadOnlyModel): TPromise<IColorRange[]> {
|
||||
const providers = ColorProviderRegistry.ordered(model).reverse();
|
||||
const promises = providers.map(p => asWinJsPromise(token => p.provideColorRanges(model, token)));
|
||||
|
||||
return TPromise.join(promises)
|
||||
.then(ranges => flatten(ranges.filter(r => Array.isArray(r))));
|
||||
export interface IColorData {
|
||||
colorRange: IColorRange;
|
||||
provider: DocumentColorProvider;
|
||||
}
|
||||
|
||||
export function getColors(model: IReadOnlyModel): TPromise<IColorData[]> {
|
||||
const colors: IColorData[] = [];
|
||||
const providers = ColorProviderRegistry.ordered(model).reverse();
|
||||
const promises = providers.map(provider => asWinJsPromise(token => provider.provideColorRanges(model, token)).then(result => {
|
||||
if (Array.isArray(result)) {
|
||||
for (let colorRange of result) {
|
||||
colors.push({ colorRange, provider });
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
return TPromise.join(promises).then(() => colors);
|
||||
}
|
||||
|
||||
export function resolveColor(color: IColor, colorFormat: ColorFormat, provider: DocumentColorProvider): TPromise<string> {
|
||||
return asWinJsPromise(token => provider.resolveColor(color, colorFormat, token));
|
||||
}
|
||||
|
||||
@@ -3,142 +3,56 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IColorFormatter, IColor } from 'vs/editor/common/modes';
|
||||
import { Color, RGBA } from 'vs/base/common/color';
|
||||
|
||||
function roundFloat(number: number, decimalPoints: number): number {
|
||||
const decimal = Math.pow(10, decimalPoints);
|
||||
return Math.round(number * decimal) / decimal;
|
||||
}
|
||||
|
||||
interface Node {
|
||||
(color: Color): string;
|
||||
}
|
||||
|
||||
function createLiteralNode(value: string): Node {
|
||||
return () => value;
|
||||
}
|
||||
import { IColorFormatter, ColorFormat } from 'vs/editor/common/modes';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
|
||||
function normalize(value: number, min: number, max: number): number {
|
||||
return value * (max - min) + min;
|
||||
}
|
||||
|
||||
function getPropertyValue(color: Color, variable: string): number | undefined {
|
||||
switch (variable) {
|
||||
case 'red':
|
||||
return color.rgba.r / 255;
|
||||
case 'green':
|
||||
return color.rgba.g / 255;
|
||||
case 'blue':
|
||||
return color.rgba.b / 255;
|
||||
case 'alpha':
|
||||
return color.rgba.a;
|
||||
case 'hue':
|
||||
return color.hsla.h / 360;
|
||||
case 'saturation':
|
||||
return color.hsla.s;
|
||||
case 'luminance':
|
||||
return color.hsla.l;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function createPropertyNode(variable: string, fractionDigits: number, type: string, min: number | undefined, max: number | undefined): Node {
|
||||
return color => {
|
||||
let value = getPropertyValue(color, variable);
|
||||
|
||||
if (value === undefined) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (type === 'd') {
|
||||
min = typeof min === 'number' ? min : 0;
|
||||
max = typeof max === 'number' ? max : 255;
|
||||
|
||||
return (normalize(value, min, max).toFixed(0)).toString();
|
||||
} else if (type === 'x' || type === 'X') {
|
||||
min = typeof min === 'number' ? min : 0;
|
||||
max = typeof max === 'number' ? max : 255;
|
||||
|
||||
let result = normalize(value, min, max).toString(16);
|
||||
|
||||
if (type === 'X') {
|
||||
result = result.toUpperCase();
|
||||
}
|
||||
|
||||
return result.length < 2 ? `0${result}` : result;
|
||||
}
|
||||
|
||||
min = typeof min === 'number' ? min : 0;
|
||||
max = typeof max === 'number' ? max : 1;
|
||||
return roundFloat(normalize(value, min, max), 2).toString();
|
||||
};
|
||||
}
|
||||
|
||||
export class ColorFormatter implements IColorFormatter {
|
||||
|
||||
readonly supportsTransparency: boolean = false;
|
||||
private tree: Node[] = [];
|
||||
|
||||
// Group 0: variable
|
||||
// Group 1: decimal digits
|
||||
// Group 2: floating/integer/hex
|
||||
// Group 3: range begin
|
||||
// Group 4: range end
|
||||
private static PATTERN = /{(\w+)(?::(\d*)(\w)+(?:\[(\d+)-(\d+)\])?)?}/g;
|
||||
|
||||
constructor(format: string) {
|
||||
let match = ColorFormatter.PATTERN.exec(format);
|
||||
let startIndex = 0;
|
||||
|
||||
// if no match -> erroor throw new Error(`${format} is not consistent with color format syntax.`);
|
||||
while (match !== null) {
|
||||
const index = match.index;
|
||||
|
||||
if (startIndex < index) {
|
||||
this.tree.push(createLiteralNode(format.substring(startIndex, index)));
|
||||
}
|
||||
|
||||
// add more parser catches
|
||||
const variable = match[1];
|
||||
if (!variable) {
|
||||
throw new Error(`${variable} is not defined.`);
|
||||
}
|
||||
|
||||
this.supportsTransparency = this.supportsTransparency || (variable === 'alpha');
|
||||
|
||||
const decimals = match[2] && parseInt(match[2]);
|
||||
const type = match[3];
|
||||
const startRange = match[4] && parseInt(match[4]);
|
||||
const endRange = match[5] && parseInt(match[5]);
|
||||
|
||||
this.tree.push(createPropertyNode(variable, decimals, type, startRange, endRange));
|
||||
|
||||
startIndex = index + match[0].length;
|
||||
match = ColorFormatter.PATTERN.exec(format);
|
||||
}
|
||||
|
||||
this.tree.push(createLiteralNode(format.substring(startIndex, format.length)));
|
||||
}
|
||||
|
||||
format(color: IColor): string {
|
||||
const richColor = new Color(new RGBA(Math.round(color.red * 255), Math.round(color.green * 255), Math.round(color.blue * 255), color.alpha));
|
||||
return this.tree.map(node => node(richColor)).join('');
|
||||
}
|
||||
}
|
||||
|
||||
export class CombinedColorFormatter implements IColorFormatter {
|
||||
|
||||
export class RGBFormatter implements IColorFormatter {
|
||||
readonly supportsTransparency: boolean = true;
|
||||
readonly colorFormat: ColorFormat = ColorFormat.RGB;
|
||||
|
||||
constructor(private opaqueFormatter: IColorFormatter, private transparentFormatter: IColorFormatter) {
|
||||
if (!transparentFormatter.supportsTransparency) {
|
||||
throw new Error('Invalid transparent formatter');
|
||||
format(color: Color): string {
|
||||
const rgb = color.rgba;
|
||||
if (rgb.a === 1) {
|
||||
return `rgb(${rgb.r}, ${rgb.g}, ${rgb.b})`;
|
||||
} else {
|
||||
return `rgb(${rgb.r}, ${rgb.g}, ${rgb.b}, ${rgb.a})`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
format(color: IColor): string {
|
||||
return color.alpha === 1 ? this.opaqueFormatter.format(color) : this.transparentFormatter.format(color);
|
||||
export class HexFormatter implements IColorFormatter {
|
||||
readonly supportsTransparency: boolean = false;
|
||||
readonly colorFormat: ColorFormat = ColorFormat.HEX;
|
||||
|
||||
_toTwoDigitHex(n: number): string {
|
||||
const r = n.toString(16);
|
||||
return r.length !== 2 ? '0' + r : r;
|
||||
}
|
||||
|
||||
format(color: Color): string {
|
||||
const rgb = color.rgba;
|
||||
if (rgb.a === 1) {
|
||||
return `#${this._toTwoDigitHex(rgb.r).toUpperCase()}${this._toTwoDigitHex(rgb.g).toUpperCase()}${this._toTwoDigitHex(rgb.b).toUpperCase()}`;
|
||||
} else {
|
||||
return `#${this._toTwoDigitHex(rgb.r).toUpperCase()}${this._toTwoDigitHex(rgb.g).toUpperCase()}${this._toTwoDigitHex(rgb.b).toUpperCase()}${this._toTwoDigitHex(Math.round(rgb.a * 255)).toUpperCase()}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class HSLFormatter implements IColorFormatter {
|
||||
readonly supportsTransparency: boolean = true;
|
||||
readonly colorFormat: ColorFormat = ColorFormat.HSL;
|
||||
|
||||
format(color: Color): string {
|
||||
const hsla = color.hsla;
|
||||
if (hsla.a === 1) {
|
||||
return `hsl(${hsla.h}, ${normalize(hsla.s, 0, 100).toFixed(0)}%, ${normalize(hsla.l, 0, 100).toFixed(0)}%)`;
|
||||
} else {
|
||||
return `hsla(${hsla.h}, ${normalize(hsla.s, 0, 100).toFixed(0)}%, ${normalize(hsla.l, 0, 100).toFixed(0)}%, ${hsla.a})`;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,78 +6,27 @@
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { Color, RGBA, HSLA } from 'vs/base/common/color';
|
||||
import { IColor } from 'vs/editor/common/modes';
|
||||
import { ColorFormatter } from 'vs/editor/contrib/colorPicker/common/colorFormatter';
|
||||
import { RGBFormatter, HexFormatter, HSLFormatter } from 'vs/editor/contrib/colorPicker/common/colorFormatter';
|
||||
|
||||
function convert2IColor(color: Color): IColor {
|
||||
return {
|
||||
red: color.rgba.r / 255,
|
||||
green: color.rgba.g / 255,
|
||||
blue: color.rgba.b / 255,
|
||||
alpha: color.rgba.a
|
||||
};
|
||||
}
|
||||
suite('ColorFormatter', () => {
|
||||
test('empty formatter', () => {
|
||||
const formatter = new ColorFormatter('');
|
||||
assert.equal(formatter.supportsTransparency, false);
|
||||
|
||||
assert.equal(formatter.format(convert2IColor(Color.white)), '');
|
||||
assert.equal(formatter.format(convert2IColor(Color.transparent)), '');
|
||||
});
|
||||
|
||||
test('no placeholder', () => {
|
||||
const formatter = new ColorFormatter('hello');
|
||||
assert.equal(formatter.supportsTransparency, false);
|
||||
|
||||
assert.equal(formatter.format(convert2IColor(Color.white)), 'hello');
|
||||
assert.equal(formatter.format(convert2IColor(Color.transparent)), 'hello');
|
||||
});
|
||||
|
||||
test('supportsTransparency', () => {
|
||||
const formatter = new ColorFormatter('hello');
|
||||
assert.equal(formatter.supportsTransparency, false);
|
||||
|
||||
const transparentFormatter = new ColorFormatter('{alpha}');
|
||||
assert.equal(transparentFormatter.supportsTransparency, true);
|
||||
});
|
||||
|
||||
test('default number format is float', () => {
|
||||
const formatter = new ColorFormatter('{red}');
|
||||
assert.equal(formatter.format(convert2IColor(Color.red)), '1');
|
||||
});
|
||||
|
||||
test('default decimal range is [0-255]', () => {
|
||||
const formatter = new ColorFormatter('{red:d}');
|
||||
assert.equal(formatter.format(convert2IColor(Color.red)), '255');
|
||||
});
|
||||
|
||||
test('default hex range is [0-FF]', () => {
|
||||
const formatter = new ColorFormatter('{red:X}');
|
||||
assert.equal(formatter.format(convert2IColor(Color.red)), 'FF');
|
||||
});
|
||||
|
||||
test('documentation', () => {
|
||||
const color = new Color(new RGBA(255, 127, 0));
|
||||
|
||||
const rgb = new ColorFormatter('rgb({red:d[0-255]}, {green:d[0-255]}, {blue:d[0-255]})');
|
||||
assert.equal(rgb.format(convert2IColor(color)), 'rgb(255, 127, 0)');
|
||||
const rgb = new RGBFormatter();
|
||||
assert.equal(rgb.format(color), 'rgb(255, 127, 0)');
|
||||
|
||||
const rgba = new ColorFormatter('rgba({red:d[0-255]}, {green:d[0-255]}, {blue:d[0-255]}, {alpha})');
|
||||
assert.equal(rgba.format(convert2IColor(color)), 'rgba(255, 127, 0, 1)');
|
||||
const hex = new HexFormatter();
|
||||
assert.equal(hex.format(color), '#FF7F00');
|
||||
|
||||
const hex = new ColorFormatter('#{red:X}{green:X}{blue:X}');
|
||||
assert.equal(hex.format(convert2IColor(color)), '#FF7F00');
|
||||
|
||||
const hsla = new ColorFormatter('hsla({hue:d[0-360]}, {saturation:d[0-100]}%, {luminance:d[0-100]}%, {alpha})');
|
||||
assert.equal(hsla.format(convert2IColor(color)), 'hsla(30, 100%, 50%, 1)');
|
||||
const hsl = new HSLFormatter();
|
||||
assert.equal(hsl.format(color), 'hsl(30, 100%, 50%)');
|
||||
});
|
||||
|
||||
test('bug#32323', () => {
|
||||
const color = new Color(new HSLA(121, 0.45, 0.29, 0.61));
|
||||
const rgba = color.rgba;
|
||||
const color2 = new Color(new RGBA(rgba.r, rgba.g, rgba.b, rgba.a));
|
||||
const hsla = new ColorFormatter('hsla({hue:d[0-360]}, {saturation:d[0-100]}%, {luminance:d[0-100]}%, {alpha})');
|
||||
assert.equal(hsla.format(convert2IColor(color2)), 'hsla(121, 45%, 29%, 0.61)');
|
||||
const hsla = new HSLFormatter();
|
||||
assert.equal(hsla.format(color2), 'hsla(121, 45%, 29%, 0.61)');
|
||||
});
|
||||
});
|
||||
@@ -9,7 +9,7 @@ import * as dom from 'vs/base/browser/dom';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { IRange, Range } from 'vs/editor/common/core/range';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { HoverProviderRegistry, Hover, IColor, IColorFormatter } from 'vs/editor/common/modes';
|
||||
import { HoverProviderRegistry, Hover, IColor, DocumentColorProvider } from 'vs/editor/common/modes';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { getHover } from '../common/hover';
|
||||
import { HoverOperation, IHoverComputer } from './hoverOperation';
|
||||
@@ -22,6 +22,7 @@ import { ColorPickerWidget } from 'vs/editor/contrib/colorPicker/browser/colorPi
|
||||
import { ColorDetector } from 'vs/editor/contrib/colorPicker/browser/colorDetector';
|
||||
import { Color, RGBA } from 'vs/base/common/color';
|
||||
import { IDisposable, empty as EmptyDisposable, dispose, combinedDisposable } from 'vs/base/common/lifecycle';
|
||||
import { resolveColor } from 'vs/editor/contrib/colorPicker/common/color';
|
||||
const $ = dom.$;
|
||||
|
||||
class ColorHover {
|
||||
@@ -29,7 +30,7 @@ class ColorHover {
|
||||
constructor(
|
||||
public readonly range: IRange,
|
||||
public readonly color: IColor,
|
||||
public readonly formatters: IColorFormatter[]
|
||||
public readonly provider: DocumentColorProvider
|
||||
) { }
|
||||
}
|
||||
|
||||
@@ -90,13 +91,13 @@ class ModesContentComputer implements IHoverComputer<HoverPart[]> {
|
||||
}
|
||||
|
||||
const range = new Range(this._range.startLineNumber, startColumn, this._range.startLineNumber, endColumn);
|
||||
const colorRange = colorDetector.getColorRange(d.range.getStartPosition());
|
||||
const colorData = colorDetector.getColorData(d.range.getStartPosition());
|
||||
|
||||
if (!didFindColor && colorRange) {
|
||||
if (!didFindColor && colorData) {
|
||||
didFindColor = true;
|
||||
|
||||
const { color, formatters } = colorRange;
|
||||
return new ColorHover(d.range, color, formatters);
|
||||
const { color } = colorData.colorRange;
|
||||
return new ColorHover(d.range, color, colorData.provider);
|
||||
} else {
|
||||
if (isEmptyMarkdownString(d.options.hoverMessage)) {
|
||||
return null;
|
||||
@@ -313,34 +314,24 @@ export class ModesContentHoverWidget extends ContentHoverWidget {
|
||||
const rgba = new RGBA(red * 255, green * 255, blue * 255, alpha);
|
||||
const color = new Color(rgba);
|
||||
|
||||
const formatters = [...msg.formatters];
|
||||
const text = this._editor.getModel().getValueInRange(msg.range);
|
||||
|
||||
let formatterIndex = 0;
|
||||
|
||||
for (let i = 0; i < formatters.length; i++) {
|
||||
if (text === formatters[i].format(msg.color)) {
|
||||
formatterIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const model = new ColorPickerModel(color, formatters, formatterIndex);
|
||||
const model = new ColorPickerModel(color, 0);
|
||||
const widget = new ColorPickerWidget(fragment, model, this._editor.getConfiguration().pixelRatio);
|
||||
|
||||
const editorModel = this._editor.getModel();
|
||||
let range = new Range(msg.range.startLineNumber, msg.range.startColumn, msg.range.endLineNumber, msg.range.endColumn);
|
||||
|
||||
const updateEditorModel = () => {
|
||||
const text = model.formatter.format({
|
||||
const color = {
|
||||
red: model.color.rgba.r / 255,
|
||||
green: model.color.rgba.g / 255,
|
||||
blue: model.color.rgba.b / 255,
|
||||
alpha: model.color.rgba.a
|
||||
};
|
||||
resolveColor(color, model.formatter.colorFormat, msg.provider).then(text => {
|
||||
editorModel.pushEditOperations([], [{ identifier: null, range, text, forceMoveMarkers: false }], () => []);
|
||||
this._editor.pushUndoStop();
|
||||
range = range.setEndPosition(range.endLineNumber, range.startColumn + text.length);
|
||||
});
|
||||
editorModel.pushEditOperations([], [{ identifier: null, range, text, forceMoveMarkers: false }], () => []);
|
||||
this._editor.pushUndoStop();
|
||||
range = range.setEndPosition(range.endLineNumber, range.startColumn + text.length);
|
||||
};
|
||||
|
||||
const colorListener = model.onColorFlushed(updateEditorModel);
|
||||
|
||||
@@ -739,5 +739,6 @@ export function createMonacoLanguagesAPI(): typeof monaco.languages {
|
||||
CompletionItemKind: CompletionItemKind,
|
||||
SymbolKind: modes.SymbolKind,
|
||||
IndentAction: IndentAction,
|
||||
ColorFormat: modes.ColorFormat
|
||||
};
|
||||
}
|
||||
|
||||
17
src/vs/monaco.d.ts
vendored
17
src/vs/monaco.d.ts
vendored
@@ -4807,11 +4807,12 @@ declare module monaco.languages {
|
||||
}
|
||||
|
||||
/**
|
||||
* A color formatter.
|
||||
* Represents a color format
|
||||
*/
|
||||
export interface IColorFormatter {
|
||||
readonly supportsTransparency: boolean;
|
||||
format(color: IColor): string;
|
||||
export enum ColorFormat {
|
||||
RGB = 0,
|
||||
HEX = 1,
|
||||
HSL = 2,
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4826,10 +4827,6 @@ declare module monaco.languages {
|
||||
* The color represented in this range.
|
||||
*/
|
||||
color: IColor;
|
||||
/**
|
||||
* The available formats for this specific color.
|
||||
*/
|
||||
formatters: IColorFormatter[];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4840,6 +4837,10 @@ declare module monaco.languages {
|
||||
* Provides the color ranges for a specific model.
|
||||
*/
|
||||
provideColorRanges(model: editor.IReadOnlyModel, token: CancellationToken): IColorRange[] | Thenable<IColorRange[]>;
|
||||
/**
|
||||
* Provide the string representation for a color.
|
||||
*/
|
||||
resolveColor(color: IColor, colorFormat: ColorFormat, token: CancellationToken): string | Thenable<string>;
|
||||
}
|
||||
|
||||
export interface IResourceEdit {
|
||||
|
||||
78
src/vs/vscode.proposed.d.ts
vendored
78
src/vs/vscode.proposed.d.ts
vendored
@@ -102,71 +102,16 @@ declare module 'vscode' {
|
||||
readonly alpha: number;
|
||||
|
||||
constructor(red: number, green: number, blue: number, alpha: number);
|
||||
|
||||
/**
|
||||
* Creates a color from the HSLA space.
|
||||
*
|
||||
* @param hue The hue component in the range [0-1].
|
||||
* @param saturation The saturation component in the range [0-1].
|
||||
* @param luminance The luminance component in the range [0-1].
|
||||
* @param alpha The alpha component in the range [0-1].
|
||||
*/
|
||||
static fromHSLA(hue: number, saturation: number, luminance: number, alpha: number): Color;
|
||||
|
||||
/**
|
||||
* Creates a color by from a hex string. Supported formats are: #RRGGBB, #RRGGBBAA, #RGB, #RGBA.
|
||||
* <code>null</code> is returned if the string does not match one of the supported formats.
|
||||
* @param hex a string to parse
|
||||
*/
|
||||
static fromHex(hex: string): Color | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A color format is either a single format or a combination of two
|
||||
* formats: an opaque one and a transparent one. The format itself
|
||||
* is a string representation of how the color can be formatted. It
|
||||
* supports the use of placeholders, similar to how snippets work.
|
||||
* Each placeholder, surrounded by curly braces `{}`, requires a
|
||||
* variable name and can optionally specify a number format and range
|
||||
* for that variable's value.
|
||||
*
|
||||
* Supported variables:
|
||||
* - `red`
|
||||
* - `green`
|
||||
* - `blue`
|
||||
* - `hue`
|
||||
* - `saturation`
|
||||
* - `luminance`
|
||||
* - `alpha`
|
||||
*
|
||||
* Supported number formats:
|
||||
* - `f`, float with 2 decimal points. This is the default format. Default range is `[0-1]`.
|
||||
* - `Xf`, float with `X` decimal points. Default range is `[0-1]`.
|
||||
* - `d`, decimal. Default range is `[0-255]`.
|
||||
* - `x`, `X`, hexadecimal. Default range is `[00-FF]`.
|
||||
*
|
||||
* The default number format is float. The default number range is `[0-1]`.
|
||||
*
|
||||
* As an example, take the color `Color(1, 0.5, 0, 1)`. Here's how
|
||||
* different formats would format it:
|
||||
*
|
||||
* - CSS RGB
|
||||
* - Format: `rgb({red:d[0-255]}, {green:d[0-255]}, {blue:d[0-255]})`
|
||||
* - Output: `rgb(255, 127, 0)`
|
||||
*
|
||||
* - CSS RGBA
|
||||
* - Format: `rgba({red:d[0-255]}, {green:d[0-255]}, {blue:d[0-255]}, {alpha})`
|
||||
* - Output: `rgba(255, 127, 0, 1)`
|
||||
*
|
||||
* - CSS Hexadecimal
|
||||
* - Format: `#{red:X}{green:X}{blue:X}`
|
||||
* - Output: `#FF7F00`
|
||||
*
|
||||
* - CSS HSLA
|
||||
* - Format: `hsla({hue:d[0-360]}, {saturation:d[0-100]}%, {luminance:d[0-100]}%, {alpha})`
|
||||
* - Output: `hsla(30, 100%, 50%, 1)`
|
||||
* Represents a color format
|
||||
*/
|
||||
export type ColorFormat = string | { opaque: string, transparent: string };
|
||||
export enum ColorFormat {
|
||||
RGB = 0,
|
||||
HEX = 1,
|
||||
HSL = 2
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a color range from a document.
|
||||
@@ -183,11 +128,6 @@ declare module 'vscode' {
|
||||
*/
|
||||
color: Color;
|
||||
|
||||
/**
|
||||
* The other formats this color range supports the color to be formatted in.
|
||||
*/
|
||||
availableFormats: ColorFormat[];
|
||||
|
||||
/**
|
||||
* Creates a new color range.
|
||||
*
|
||||
@@ -195,7 +135,7 @@ declare module 'vscode' {
|
||||
* @param color The value of the color.
|
||||
* @param format The format in which this color is currently formatted.
|
||||
*/
|
||||
constructor(range: Range, color: Color, availableFormats: ColorFormat[]);
|
||||
constructor(range: Range, color: Color);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -212,6 +152,10 @@ declare module 'vscode' {
|
||||
* can be signaled by returning `undefined`, `null`, or an empty array.
|
||||
*/
|
||||
provideDocumentColors(document: TextDocument, token: CancellationToken): ProviderResult<ColorRange[]>;
|
||||
/**
|
||||
* Provide the string representation for a color.
|
||||
*/
|
||||
resolveColor(color: Color, colorFormat: ColorFormat): ProviderResult<string>;
|
||||
}
|
||||
|
||||
export namespace languages {
|
||||
|
||||
@@ -15,12 +15,11 @@ import { wireCancellationToken } from 'vs/base/common/async';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { Position as EditorPosition } from 'vs/editor/common/core/position';
|
||||
import { Range as EditorRange } from 'vs/editor/common/core/range';
|
||||
import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, IRawColorFormatMap, MainContext, IExtHostContext } from '../node/extHost.protocol';
|
||||
import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext } from '../node/extHost.protocol';
|
||||
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
|
||||
import { LanguageConfiguration } from 'vs/editor/common/modes/languageConfiguration';
|
||||
import { IHeapService } from './mainThreadHeapService';
|
||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||
import { ColorFormatter, CombinedColorFormatter } from 'vs/editor/contrib/colorPicker/common/colorFormatter';
|
||||
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadLanguageFeatures)
|
||||
@@ -30,7 +29,6 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
private _heapService: IHeapService;
|
||||
private _modeService: IModeService;
|
||||
private _registrations: { [handle: number]: IDisposable; } = Object.create(null);
|
||||
private _formatters: Map<number, ColorFormatter>;
|
||||
|
||||
constructor(
|
||||
extHostContext: IExtHostContext,
|
||||
@@ -40,7 +38,6 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
this._proxy = extHostContext.get(ExtHostContext.ExtHostLanguageFeatures);
|
||||
this._heapService = heapService;
|
||||
this._modeService = modeService;
|
||||
this._formatters = new Map<number, ColorFormatter>();
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
@@ -293,14 +290,6 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
return wireCancellationToken(token, proxy.$provideDocumentColors(handle, model.uri))
|
||||
.then(documentColors => {
|
||||
return documentColors.map(documentColor => {
|
||||
const formatters = documentColor.availableFormats.map(f => {
|
||||
if (typeof f === 'number') {
|
||||
return this._formatters.get(f);
|
||||
} else {
|
||||
return new CombinedColorFormatter(this._formatters.get(f[0]), this._formatters.get(f[1]));
|
||||
}
|
||||
});
|
||||
|
||||
const [red, green, blue, alpha] = documentColor.color;
|
||||
const color = {
|
||||
red: red / 255.0,
|
||||
@@ -311,22 +300,19 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
|
||||
return {
|
||||
color,
|
||||
formatters,
|
||||
range: documentColor.range
|
||||
};
|
||||
});
|
||||
});
|
||||
},
|
||||
resolveColor: (color, format, token) => {
|
||||
return wireCancellationToken(token, proxy.$resolveColor(handle, color, format));
|
||||
}
|
||||
});
|
||||
|
||||
return TPromise.as(null);
|
||||
}
|
||||
|
||||
$registerColorFormats(formats: IRawColorFormatMap): TPromise<any> {
|
||||
formats.forEach(f => this._formatters.set(f[0], new ColorFormatter(f[1])));
|
||||
return TPromise.as(null);
|
||||
}
|
||||
|
||||
// --- configuration
|
||||
|
||||
$setLanguageConfiguration(handle: number, languageId: string, _configuration: vscode.LanguageConfiguration): TPromise<any> {
|
||||
|
||||
@@ -551,6 +551,7 @@ export function createApiFactory(
|
||||
CancellationTokenSource: CancellationTokenSource,
|
||||
CodeLens: extHostTypes.CodeLens,
|
||||
Color: extHostTypes.Color,
|
||||
ColorFormat: extHostTypes.ColorFormat,
|
||||
ColorRange: extHostTypes.ColorRange,
|
||||
EndOfLine: extHostTypes.EndOfLine,
|
||||
CompletionItem: extHostTypes.CompletionItem,
|
||||
|
||||
@@ -232,7 +232,6 @@ export interface MainThreadLanguageFeaturesShape extends IDisposable {
|
||||
$registerSuggestSupport(handle: number, selector: vscode.DocumentSelector, triggerCharacters: string[], supportsResolveDetails: boolean): TPromise<any>;
|
||||
$registerSignatureHelpProvider(handle: number, selector: vscode.DocumentSelector, triggerCharacter: string[]): TPromise<any>;
|
||||
$registerDocumentLinkProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any>;
|
||||
$registerColorFormats(formats: IRawColorFormatMap): TPromise<any>;
|
||||
$registerDocumentColorProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any>;
|
||||
$setLanguageConfiguration(handle: number, languageId: string, configuration: vscode.LanguageConfiguration): TPromise<any>;
|
||||
}
|
||||
@@ -501,13 +500,9 @@ export interface ExtHostHeapServiceShape {
|
||||
}
|
||||
export interface IRawColorInfo {
|
||||
color: [number, number, number, number];
|
||||
availableFormats: (number | [number, number])[];
|
||||
range: IRange;
|
||||
}
|
||||
|
||||
export type IRawColorFormatMap = [number, string][];
|
||||
|
||||
|
||||
export interface IExtHostSuggestion extends modes.ISuggestion {
|
||||
_id: number;
|
||||
_parentId: number;
|
||||
@@ -541,8 +536,9 @@ export interface ExtHostLanguageFeaturesShape {
|
||||
$releaseCompletionItems(handle: number, id: number): void;
|
||||
$provideSignatureHelp(handle: number, resource: URI, position: IPosition): TPromise<modes.SignatureHelp>;
|
||||
$provideDocumentLinks(handle: number, resource: URI): TPromise<modes.ILink[]>;
|
||||
$provideDocumentColors(handle: number, resource: URI): TPromise<IRawColorInfo[]>;
|
||||
$resolveDocumentLink(handle: number, link: modes.ILink): TPromise<modes.ILink>;
|
||||
$provideDocumentColors(handle: number, resource: URI): TPromise<IRawColorInfo[]>;
|
||||
$resolveColor(handle: number, color: modes.IColor, colorFormat: modes.ColorFormat): TPromise<string>;
|
||||
}
|
||||
|
||||
export interface ExtHostQuickOpenShape {
|
||||
|
||||
@@ -18,7 +18,7 @@ import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/node/extHos
|
||||
import { ExtHostDiagnostics } from 'vs/workbench/api/node/extHostDiagnostics';
|
||||
import { IWorkspaceSymbolProvider } from 'vs/workbench/parts/search/common/search';
|
||||
import { asWinJsPromise } from 'vs/base/common/async';
|
||||
import { MainContext, MainThreadTelemetryShape, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IRawColorFormatMap, IMainContext, IExtHostSuggestResult, IExtHostSuggestion } from './extHost.protocol';
|
||||
import { MainContext, MainThreadTelemetryShape, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IExtHostSuggestResult, IExtHostSuggestion } from './extHost.protocol';
|
||||
import { regExpLeadsToEndlessLoop } from 'vs/base/common/strings';
|
||||
import { IPosition } from 'vs/editor/common/core/position';
|
||||
import { IRange } from 'vs/editor/common/core/range';
|
||||
@@ -704,8 +704,6 @@ class LinkProviderAdapter {
|
||||
|
||||
class ColorProviderAdapter {
|
||||
|
||||
private static _colorFormatHandlePool: number = 0;
|
||||
|
||||
constructor(
|
||||
private _proxy: MainThreadLanguageFeaturesShape,
|
||||
private _documents: ExtHostDocuments,
|
||||
@@ -720,39 +718,20 @@ class ColorProviderAdapter {
|
||||
return [];
|
||||
}
|
||||
|
||||
const newRawColorFormats: IRawColorFormatMap = [];
|
||||
const getFormatId = (format: string) => {
|
||||
let id = this._colorFormatCache.get(format);
|
||||
|
||||
if (typeof id !== 'number') {
|
||||
id = ColorProviderAdapter._colorFormatHandlePool++;
|
||||
this._colorFormatCache.set(format, id);
|
||||
newRawColorFormats.push([id, format]);
|
||||
}
|
||||
|
||||
return id;
|
||||
};
|
||||
|
||||
const colorInfos: IRawColorInfo[] = colors.map(ci => {
|
||||
const availableFormats = ci.availableFormats.map(format => {
|
||||
if (typeof format === 'string') {
|
||||
return getFormatId(format);
|
||||
} else {
|
||||
return [getFormatId(format.opaque), getFormatId(format.transparent)] as [number, number];
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
color: [ci.color.red, ci.color.green, ci.color.blue, ci.color.alpha] as [number, number, number, number],
|
||||
availableFormats: availableFormats,
|
||||
range: TypeConverters.fromRange(ci.range)
|
||||
};
|
||||
});
|
||||
|
||||
this._proxy.$registerColorFormats(newRawColorFormats);
|
||||
return colorInfos;
|
||||
});
|
||||
}
|
||||
|
||||
resolveColor(color: modes.IColor, colorFormat: modes.ColorFormat): TPromise<string> {
|
||||
return asWinJsPromise(token => this._provider.resolveColor(color, colorFormat));
|
||||
}
|
||||
}
|
||||
|
||||
type Adapter = OutlineAdapter | CodeLensAdapter | DefinitionAdapter | HoverAdapter
|
||||
@@ -1063,6 +1042,10 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
return this._withAdapter(handle, ColorProviderAdapter, adapter => adapter.provideColors(resource));
|
||||
}
|
||||
|
||||
$resolveColor(handle: number, color: modes.IColor, colorFormat: modes.ColorFormat): TPromise<string> {
|
||||
return this._withAdapter(handle, ColorProviderAdapter, adapter => adapter.resolveColor(color, colorFormat));
|
||||
}
|
||||
|
||||
// --- configuration
|
||||
|
||||
setLanguageConfiguration(languageId: string, configuration: vscode.LanguageConfiguration): vscode.Disposable {
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
import * as crypto from 'crypto';
|
||||
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { Color as BaseColor, HSLA } from 'vs/base/common/color';
|
||||
import { illegalArgument } from 'vs/base/common/errors';
|
||||
import * as vscode from 'vscode';
|
||||
import { isMarkdownString } from 'vs/base/common/htmlContent';
|
||||
@@ -1052,20 +1051,6 @@ export class Color {
|
||||
this.blue = blue;
|
||||
this.alpha = alpha;
|
||||
}
|
||||
|
||||
static fromHSLA(hue: number, saturation: number, luminance: number, alpha: number): Color {
|
||||
const color = new BaseColor(new HSLA(hue, saturation, luminance, alpha)).rgba;
|
||||
return new Color(color.r, color.g, color.b, color.a);
|
||||
}
|
||||
|
||||
static fromHex(hex: string): Color | null {
|
||||
let baseColor = BaseColor.Format.CSS.parseHex(hex);
|
||||
if (baseColor) {
|
||||
const rgba = baseColor.rgba;
|
||||
return new Color(rgba.r, rgba.g, rgba.b, rgba.a);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export type IColorFormat = string | { opaque: string, transparent: string };
|
||||
@@ -1075,24 +1060,24 @@ export class ColorRange {
|
||||
|
||||
color: Color;
|
||||
|
||||
availableFormats: IColorFormat[];
|
||||
|
||||
constructor(range: Range, color: Color, availableFormats: IColorFormat[]) {
|
||||
constructor(range: Range, color: Color) {
|
||||
if (color && !(color instanceof Color)) {
|
||||
throw illegalArgument('color');
|
||||
}
|
||||
if (availableFormats && !Array.isArray(availableFormats)) {
|
||||
throw illegalArgument('availableFormats');
|
||||
}
|
||||
if (!Range.isRange(range) || range.isEmpty) {
|
||||
throw illegalArgument('range');
|
||||
}
|
||||
this.range = range;
|
||||
this.color = color;
|
||||
this.availableFormats = availableFormats;
|
||||
}
|
||||
}
|
||||
|
||||
export enum ColorFormat {
|
||||
RGB = 0,
|
||||
HEX = 1,
|
||||
HSL = 2
|
||||
}
|
||||
|
||||
export enum TaskRevealKind {
|
||||
Always = 1,
|
||||
|
||||
|
||||
Reference in New Issue
Block a user