diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index 88b441ee2ce..b92238a965c 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -9,7 +9,7 @@ import { MarkedString } from 'vs/base/common/htmlContent'; import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; -import { LanguageId, LanguageIdentifier, ColorMode } from 'vs/editor/common/modes'; +import { LanguageId, LanguageIdentifier } from 'vs/editor/common/modes'; import { LineTokens } from 'vs/editor/common/core/lineTokens'; import { IDisposable } from 'vs/base/common/lifecycle'; import { Position, IPosition } from 'vs/editor/common/core/position'; @@ -62,9 +62,11 @@ export interface IModelDecorationOverviewRulerOptions { position: OverviewRulerLane; } +export type IColorFormat = string | { opaque: string, transparent: string }; export interface IColorInfo { color: Color; - mode: ColorMode; + format: IColorFormat; + availableFormats: IColorFormat[]; } /** * Options for a model decoration. diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index 7d5b5845578..a80816fa47e 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -173,7 +173,8 @@ export interface MarkedStringHover { // TODO@michel documentation export interface ColorHover { color: Color; - mode: ColorMode; + format: IColorFormat; + availableFormats: IColorFormat[]; /** * The range to which this hover applies. When missing, the * editor will use the range at the current position or the @@ -676,16 +677,13 @@ export interface LinkProvider { /** * A color inside the editor. */ +export type IColorFormat = string | { opaque: string, transparent: string }; export interface IColorInfo { color: Color; - mode: ColorMode; + format: IColorFormat; + availableFormats: IColorFormat[]; range: IRange; } -export enum ColorMode { - RGBA = 0, - Hex = 1, - HSLA = 2 -} /** * A provider of colors. */ diff --git a/src/vs/editor/contrib/colorPicker/browser/colorPicker.ts b/src/vs/editor/contrib/colorPicker/browser/colorPicker.ts index 2e20a4d62a5..4f7f44582ae 100644 --- a/src/vs/editor/contrib/colorPicker/browser/colorPicker.ts +++ b/src/vs/editor/contrib/colorPicker/browser/colorPicker.ts @@ -14,6 +14,7 @@ import { editorWidgetBackground, editorWidgetBorder } from "vs/platform/theme/co import { ColorProviderRegistry, IColorInfo } from "vs/editor/common/modes"; import { TPromise } from "vs/base/common/winjs.base"; import { getColors } from "vs/editor/contrib/colorPicker/common/colorPicker"; +import { IRange } from "vs/editor/common/core/range"; @editorContribution export class ColorPicker implements IEditorContribution { @@ -83,8 +84,8 @@ export class ColorPicker implements IEditorContribution { return; } - this.computePromise = getColors(this.editor.getModel()).then(colors => { - this.updateDecorations(colors); + this.computePromise = getColors(this.editor.getModel()).then(colorInfos => { + this.updateDecorations(colorInfos); this.computePromise = null; }); } @@ -100,24 +101,30 @@ export class ColorPicker implements IEditorContribution { } } - private updateDecorations(colors: IColorInfo[]): void { + private updateDecorations(colorInfos: IColorInfo[]): void { this.editor.changeDecorations((changeAccessor: IModelDecorationsChangeAccessor) => { let newDecorations: IModelDeltaDecoration[] = []; - for (let c of colors) { - newDecorations.push({ - range: { - startLineNumber: c.range.startLineNumber, - startColumn: c.range.startColumn, - endLineNumber: c.range.endLineNumber, - endColumn: c.range.endColumn - }, + + for (let c of colorInfos) { + const range: IRange = { + startLineNumber: c.range.startLineNumber, + startColumn: c.range.startColumn, + endLineNumber: c.range.endLineNumber, + endColumn: c.range.endColumn + }; + + const decoration = { + range: range, options: { colorInfo: { color: c.color, - mode: c.mode + format: c.format, + availableFormats: c.availableFormats } } - }); + }; + + newDecorations.push(decoration); } this.currentDecorations = changeAccessor.deltaDecorations(this.currentDecorations, newDecorations); diff --git a/src/vs/editor/contrib/colorPicker/browser/colorPickerModel.ts b/src/vs/editor/contrib/colorPicker/browser/colorPickerModel.ts index 94f2576b9a8..4a97fdff571 100644 --- a/src/vs/editor/contrib/colorPicker/browser/colorPickerModel.ts +++ b/src/vs/editor/contrib/colorPicker/browser/colorPickerModel.ts @@ -5,20 +5,20 @@ import { ColorPickerWidget } from "vs/editor/contrib/colorPicker/browser/colorPickerWidget"; import { Color, RGBA } from "vs/base/common/color"; -import { ColorMode } from "vs/editor/common/modes"; +import { ColorFormatter } from "vs/editor/contrib/colorPicker/common/colorFormatter"; export class ColorPickerModel { + public widget: ColorPickerWidget; public saturationSelection: ISaturationState; public originalColor: string; - public widget: ColorPickerWidget; private _color: Color; private _selectedColor: string; private _opacity: number; private _hue: Color; - private _colorModel: ColorMode; + private _formatter: ColorFormatter; private _colorModelIndex: number; constructor() { @@ -33,13 +33,7 @@ export class ColorPickerModel { this._hue = color; } - if (this._colorModel === ColorMode.RGBA) { - this.selectedColorString = color.toRGBA().toString(); - } else if (this._colorModel === ColorMode.Hex) { - this.selectedColorString = color.toRGBHex(); - } else { - this.selectedColorString = color.toHSLA().toString(); - } + this.selectedColorString = this._formatter.toString(this._color); } public get color(): Color { @@ -74,10 +68,6 @@ export class ColorPickerModel { public set opacity(opacity: number) { this._opacity = opacity; - if (this._colorModel === ColorMode.Hex) { - this.colorModel = ColorMode.RGBA; - } - const rgba = this._color.toRGBA(); this.color = Color.fromRGBA(new RGBA(rgba.r, rgba.g, rgba.b, opacity * 255)); @@ -90,33 +80,20 @@ export class ColorPickerModel { return this._opacity; } - public set colorModel(model: ColorMode) { - this._colorModel = model; - this._colorModelIndex = model; + public set formatter(formatter: ColorFormatter) { + this._formatter = formatter; if (this._selectedColor) { this.color = this._color; // Refresh selected colour string state } } - public get colorModel(): ColorMode { - return this._colorModel; + public get formatter(): ColorFormatter { + return this._formatter; } public nextColorModel() { // should go to the controller perhaps - this._colorModelIndex++; - - if (this._colorModelIndex > 2) { - this._colorModelIndex = 0; - } - - // Skip hex model if opacity is set - if (this._colorModelIndex === ColorMode.Hex && this._opacity !== 1) { - this.nextColorModel(); - return; - } - - this.colorModel = this._colorModelIndex; + throw new Error('not implemented'); } } diff --git a/src/vs/editor/contrib/colorPicker/browser/elements/colorPickerBody.ts b/src/vs/editor/contrib/colorPicker/browser/elements/colorPickerBody.ts index b1bb8b6af95..88d03724085 100644 --- a/src/vs/editor/contrib/colorPicker/browser/elements/colorPickerBody.ts +++ b/src/vs/editor/contrib/colorPicker/browser/elements/colorPickerBody.ts @@ -46,7 +46,7 @@ export class ColorPickerBody extends Disposable { const g = c.g; const b = c.b; - this.opacityOverlay.style.background = `linear-gradient(to bottom, rgba(${r}, ${g}, ${b}, 1) 0%, rgba(${r}, ${g}, ${b}, 0.83) 17%, rgba(${r}, ${g}, ${b}, 0.67) 33%, rgba(${r}, ${g}, ${b}, 0.5) 50%, rgba(${r}, ${g}, ${b}, 0.33) 67%, rgba(${r}, ${g}, ${b}, 0.17) 83%, rgba(${r}, ${g}, ${b}, 0) 100%)`; + this.opacityOverlay.style.background = `linear-gradient(to bottom, rgba(${r}, ${g}, ${b}, 1) 0%, rgba(${r}, ${g}, ${b}, 0) 100%)`; } private registerListeners(): void { @@ -105,7 +105,7 @@ export class ColorPickerBody extends Disposable { } const slider = element === this.hueStrip ? this.hueSlider : this.opacitySlider; const strip = element === this.hueStrip ? this.hueStrip : this.opacityStrip; - const initialColorModel = this.model.colorModel; + const initialColorModel = this.model.formatter; // Update slider position if clicked on a strip itself if (e.target === this.hueStrip || e.target === this.opacityStrip) { @@ -143,8 +143,8 @@ export class ColorPickerBody extends Disposable { updateModel(); // Change back from RGBA to HEX if opacity touched - if (this.model.colorModel !== initialColorModel && this.model.opacity === 1) { - this.model.colorModel = initialColorModel; + if (this.model.formatter !== initialColorModel && this.model.opacity === 1) { + this.model.formatter = initialColorModel; } }, () => { strip.style.cursor = '-webkit-grab'; diff --git a/src/vs/editor/contrib/colorPicker/browser/elements/colorPickerHeader.ts b/src/vs/editor/contrib/colorPicker/browser/elements/colorPickerHeader.ts index 9256e35ba9a..2a5c024f530 100644 --- a/src/vs/editor/contrib/colorPicker/browser/elements/colorPickerHeader.ts +++ b/src/vs/editor/contrib/colorPicker/browser/elements/colorPickerHeader.ts @@ -33,12 +33,12 @@ export class ColorPickerHeader extends Disposable { public updatePickedColor() { this.pickedColorNode.textContent = this.model.selectedColorString; - this.pickedColorNode.style.backgroundColor = this.model.selectedColorString; + this.pickedColorNode.style.backgroundColor = this.model.color.toString(); } private drawPickedColorBox() { this.pickedColorNode = $('.picked-color'); - this.pickedColorNode.style.backgroundColor = this.model.selectedColorString; + this.pickedColorNode.style.backgroundColor = this.model.color.toString(); this.pickedColorNode.textContent = this.model.selectedColorString; dom.append(this.domNode, this.pickedColorNode); } diff --git a/src/vs/editor/contrib/colorPicker/common/colorFormatter.ts b/src/vs/editor/contrib/colorPicker/common/colorFormatter.ts new file mode 100644 index 00000000000..c3a563dfbd4 --- /dev/null +++ b/src/vs/editor/contrib/colorPicker/common/colorFormatter.ts @@ -0,0 +1,193 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Color } from "vs/base/common/color"; + +interface Node { + (color: Color): string; +} + +function createLiteralNode(value: string): Node { + return () => value; +} + +const RGBA_ENDRANGE = 255; +const HSL_HUERANGE = 360; +const HSL_ENDRANGE = 1; + +function normalize(value: number, start?: number, end?: number, currentEndRange?: number): number { + let val = value; + + if (start || end) { + // More safety checks + // if (!start) { + // throw new Error('Color format range defined is not correct. There is no range start.'); + // } + // if (!end) { + // throw new Error('Color format range defined is not correct. There is no range end.'); + // } + if (start > end) { + throw new Error('Color format range defined is not correct. Range start is bigger than end.'); + } + if (start === end) { + throw new Error('Color format range defined is not correct. Range start is the same as end.'); + } + + const ratio = val / currentEndRange; + val = ratio * (end - start) + start; + } + + return val; +}; + +function createPropertyNode(variable: string, fractionDigits: number, type: string, min: number, max: number): Node { + + return color => { + let absoluteValue: number; + + switch (variable) { + case 'red': + absoluteValue = normalize(color.toRGBA().r, min, max, RGBA_ENDRANGE); + break; + case 'blue': + absoluteValue = normalize(color.toRGBA().g, min, max, RGBA_ENDRANGE); + break; + case 'green': + absoluteValue = normalize(color.toRGBA().b, min, max, RGBA_ENDRANGE); + break; + case 'alpha': + absoluteValue = normalize(color.toRGBA().a, min, max, RGBA_ENDRANGE); + break; + case 'hue': + absoluteValue = normalize(color.toHSLA().h, min, max, HSL_HUERANGE); + break; + case 'saturation': + absoluteValue = normalize(color.toHSLA().s, min, max, HSL_ENDRANGE); + break; + case 'luminosity': + absoluteValue = normalize(color.toHSLA().l, min, max, HSL_ENDRANGE); + break; + } + + if (absoluteValue === undefined) { + throw new Error(`${variable} is not supported as a color format.`); + } + + let value: number | string; + if (type === 'f') { + fractionDigits = fractionDigits ? fractionDigits : 2; // 2 is default + value = absoluteValue.toFixed(fractionDigits); + } else if (type === 'x' || type === 'X') { + value = normalize(absoluteValue, min, max, RGBA_ENDRANGE).toString(16); + + if (value.length !== 2) { + value = '0' + value; + } + if (type === 'X') { + value = value.toUpperCase(); + } + } else { // also 'd'-case + value = absoluteValue.toFixed(0); + } + + + return value.toString(); + }; +} + +export class ColorFormatter { + /* + Variables + - red + - green + - blue + - hue + - saturation + - luminosity + - alpha + + Number formats + - decimal - d + - float - f + - hex - x X + + Number ranges + - 0-1 + - 0-255 + - 0-100 + - arbitrary + + Examples + "{red}" - 123 + "{red:d}" - 123 + "{red:x}" - af + "{red:X}" - AF + "{red:d[0-255]}" - AF + "{red:x[0-255]}" - AF + "{red:X[0-1024]}" - FEFE + "{red:2f}" - 123.51 + "{red:1f}" - 123.5 + "{red:2f[0-1]}" - 1.23 + + - default format: decimal + - default range: 0-255 + */ + + 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) { + this.parse(format); + // this.tree.push(createLiteralNode('new Color(')); + // this.tree.push(createPropertyNode('red', 'd', 0, 255)); + // this.tree.push(createLiteralNode(')')); + } + + private parse(format: string): void { + 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`); + } + const decimals = parseInt(match[2]); + const type = match[3]; + const startRange = parseInt(match[4]); + const endRange = 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))); + } + + public toString(color: Color): string { + let colorString = []; + this.tree.forEach(node => { + colorString.push(node(color)); + }); + + return colorString.join(''); + } +} diff --git a/src/vs/editor/contrib/colorPicker/common/colorPicker.ts b/src/vs/editor/contrib/colorPicker/common/colorPicker.ts index 9e6e3dfa788..c162f90e268 100644 --- a/src/vs/editor/contrib/colorPicker/common/colorPicker.ts +++ b/src/vs/editor/contrib/colorPicker/common/colorPicker.ts @@ -4,28 +4,24 @@ *--------------------------------------------------------------------------------------------*/ import { TPromise } from "vs/base/common/winjs.base"; -import { ColorProviderRegistry, IColorInfo, ColorProvider } from "vs/editor/common/modes"; +import { ColorProviderRegistry, IColorInfo } from "vs/editor/common/modes"; import { asWinJsPromise } from "vs/base/common/async"; import { onUnexpectedExternalError } from "vs/base/common/errors"; import { IReadOnlyModel } from "vs/editor/common/editorCommon"; export function getColors(model: IReadOnlyModel): TPromise { - let colors: IColorInfo[] = []; + let colorInfo: IColorInfo[] = []; // ask all providers for colors in parallel const promises = ColorProviderRegistry.ordered(model).reverse().map(provider => { return asWinJsPromise(token => provider.provideColors(model, token)).then(result => { if (Array.isArray(result)) { - colors = colors.concat(result); + colorInfo = colorInfo.concat(result); } }, onUnexpectedExternalError); }); return TPromise.join(promises).then(() => { - return colors; + return colorInfo; }); -} - -export function changeMode(provider: ColorProvider, colorInfo: IColorInfo): TPromise { - throw new Error('not implemented'); } \ No newline at end of file diff --git a/src/vs/editor/contrib/hover/browser/modesContentHover.ts b/src/vs/editor/contrib/hover/browser/modesContentHover.ts index 65cd7a188e2..b9d30b5cb4c 100644 --- a/src/vs/editor/contrib/hover/browser/modesContentHover.ts +++ b/src/vs/editor/contrib/hover/browser/modesContentHover.ts @@ -25,6 +25,7 @@ import { ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDeco import { ColorPickerModel } from "vs/editor/contrib/colorPicker/browser/colorPickerModel"; import { ColorPickerWidget } from "vs/editor/contrib/colorPicker/browser/colorPickerWidget"; import { IColorInfo } from 'vs/editor/common/editorCommon'; +import { ColorFormatter } from "vs/editor/contrib/colorPicker/common/colorFormatter"; class ModesContentComputer implements IHoverComputer { @@ -98,8 +99,9 @@ class ModesContentComputer implements IHoverComputer { if (colorInfo) { return { color: colorInfo.color, - mode: colorInfo.mode, - range: range + format: colorInfo.format, + availableFormats: colorInfo.availableFormats, + range: range, }; } @@ -294,11 +296,16 @@ export class ModesContentHoverWidget extends ContentHoverWidget { const widget = this._register(new ColorPickerWidget(model, this._editor)); model.widget = widget; model.originalColor = msg.color.toRGBA().toString(); - model.colorModel = msg.mode; + if (typeof msg.format !== 'string') { // TODO: take into account opaque and transparent + msg.format = msg.format.opaque; + } + + model.formatter = new ColorFormatter(msg.format); model.color = msg.color; this._colorPicker = widget; fragment.appendChild(widget.getDomNode()); + console.log(this._editor.getModel()); } }); diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 362acb1921c..1d095825901 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -265,12 +265,7 @@ declare module 'vscode' { static fromHex(hex: string): Color; } - export enum ColorMode { - RGBA = 0, - Hex = 1, // should we account for 4-byte hex? - HSLA = 2 - } - + export type IColorFormat = string | { opaque: string, transparent: string }; // TODO@Michel export class ColorInfo { /** @@ -280,14 +275,15 @@ declare module 'vscode' { color: Color; - mode: ColorMode; + format: IColorFormat; - constructor(range: Range, color: Color, mode: ColorMode); + availableFormats: IColorFormat[]; + + constructor(range: Range, color: Color, format: IColorFormat, availableFormats: IColorFormat[]); } export interface DocumentColorProvider { provideDocumentColors(document: TextDocument, token: CancellationToken): ProviderResult; - provideColorFormat(colorInfo: ColorInfo): ProviderResult; } export namespace languages { diff --git a/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts b/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts index 54f47ea150a..0fa8179d4ea 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts @@ -269,15 +269,37 @@ export class MainThreadLanguageFeatures extends MainThreadLanguageFeaturesShape // --- colors $registerDocumentColorProvider(handle: number, selector: vscode.DocumentSelector): TPromise { + const proxy = this._proxy; this._registrations[handle] = modes.ColorProviderRegistry.register(selector, { - provideColors: (model, token) => { - return wireCancellationToken(token, this._proxy.$provideDocumentColors(handle, model.uri)) + provideColors: function (model, token) { + const provider = this; + return wireCancellationToken(token, proxy.$provideDocumentColors(handle, model.uri)) .then((colorInfos) => { return colorInfos.map(c => { + let format: modes.IColorFormat; + if (typeof c.format === 'string') { + format = c.format; + } else { + format = { opaque: c.format[0], transparent: c.format[1] }; + } + let availableFormats: modes.IColorFormat[] = []; + c.availableFormats.forEach(format => { + if (typeof format === 'string') { + availableFormats.push(format); + } else { + availableFormats.push({ + opaque: format[0], + transparent: format[1] + }); + } + }); + return { color: Color.fromRGBA(new RGBA(c.color[0], c.color[1], c.color[2], c.color[3] * 255)), - mode: c.mode, - range: c.range + format: format, + availableFormats: availableFormats, + range: c.range, + provider: provider }; }); }); diff --git a/src/vs/workbench/api/node/extHost.api.impl.ts b/src/vs/workbench/api/node/extHost.api.impl.ts index 42e7a2637dc..b6abda2a9c5 100644 --- a/src/vs/workbench/api/node/extHost.api.impl.ts +++ b/src/vs/workbench/api/node/extHost.api.impl.ts @@ -492,7 +492,6 @@ export function createApiFactory( CodeLens: extHostTypes.CodeLens, Color: extHostTypes.Color, ColorInfo: extHostTypes.ColorInfo, - ColorMode: extHostTypes.ColorMode, EndOfLine: extHostTypes.EndOfLine, CompletionItem: extHostTypes.CompletionItem, CompletionItemKind: extHostTypes.CompletionItemKind, diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index ea2b82fb140..0c69325ef6a 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -35,7 +35,7 @@ import { IConfigurationData } from 'vs/platform/configuration/common/configurati import { IPickOpenEntry, IPickOptions } from 'vs/platform/quickOpen/common/quickOpen'; import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles'; import { TextEditorCursorStyle } from 'vs/editor/common/config/editorOptions'; -import { EndOfLine, TextEditorLineNumbersStyle, ColorMode } from 'vs/workbench/api/node/extHostTypes'; +import { EndOfLine, TextEditorLineNumbersStyle } from 'vs/workbench/api/node/extHostTypes'; import { TaskSet } from 'vs/workbench/parts/tasks/common/tasks'; @@ -453,10 +453,10 @@ export namespace ObjectIdentifier { export abstract class ExtHostHeapServiceShape { $onGarbageCollection(ids: number[]): void { throw ni(); } } - export interface IColorInfo { color: [number, number, number, number | undefined]; - mode: ColorMode; + format: string | [string, string]; + availableFormats: (string | [string, string])[]; range: IRange; } diff --git a/src/vs/workbench/api/node/extHostTypeConverters.ts b/src/vs/workbench/api/node/extHostTypeConverters.ts index dc55f20aac4..182ca0eb016 100644 --- a/src/vs/workbench/api/node/extHostTypeConverters.ts +++ b/src/vs/workbench/api/node/extHostTypeConverters.ts @@ -372,9 +372,26 @@ export namespace DocumentLink { export namespace DocumentColor { export function from(colorInfo: vscode.ColorInfo): IColorInfo { + let format: string | [string, string]; + if (typeof colorInfo.format === 'string') { + format = colorInfo.format; + } else { + format = [colorInfo.format.opaque, colorInfo.format.transparent]; + } + + let availableFormats: (string | [string, string])[] = []; + colorInfo.availableFormats.forEach(format => { + if (typeof format === 'string') { + availableFormats.push(format); + } else { + availableFormats.push([format.opaque, format.transparent]); + } + }); + return { color: [colorInfo.color.red, colorInfo.color.green, colorInfo.color.blue, colorInfo.color.alpha], - mode: colorInfo.mode, + format: format, + availableFormats: availableFormats, range: fromRange(colorInfo.range) }; } diff --git a/src/vs/workbench/api/node/extHostTypes.ts b/src/vs/workbench/api/node/extHostTypes.ts index 8c744866bf3..4c4c99de4b2 100644 --- a/src/vs/workbench/api/node/extHostTypes.ts +++ b/src/vs/workbench/api/node/extHostTypes.ts @@ -1043,32 +1043,34 @@ export class Color { } } -export enum ColorMode { - RGBA = 0, - Hex = 1, - HSLA = 2 -} +export type IColorFormat = string | { opaque: string, transparent: string }; export class ColorInfo { range: Range; color: Color; - mode: ColorMode; + format: IColorFormat; - constructor(range: Range, color: Color, mode: ColorMode) { + availableFormats: IColorFormat[]; + + constructor(range: Range, color: Color, format: IColorFormat, availableFormats: IColorFormat[]) { if (color && !(color instanceof Color)) { throw illegalArgument('color'); } - if (mode && !(mode in ColorMode)) { - throw illegalArgument('mode'); + if (format && (typeof format !== 'string') && !format.opaque && !format.transparent && typeof format.opaque !== 'string' && typeof format.transparent !== 'string') { + throw illegalArgument('format'); + } + if (availableFormats && !Array.isArray(availableFormats)) { + throw illegalArgument('availableFormats'); } if (!Range.isRange(range) || range.isEmpty) { throw illegalArgument('range'); } this.range = range; this.color = color; - this.mode = mode; + this.format = format; + this.availableFormats = availableFormats; } }