提交 06c30736 编写于 作者: M Michel Kaporin

Added color provider to proposed API.

上级 e3d86e19
......@@ -677,7 +677,7 @@ export interface LinkProvider {
/**
* A color inside the editor.
*/
export interface IColor {
export interface IColorInfo {
range: IRange;
color: Color;
}
......@@ -685,7 +685,7 @@ export interface IColor {
* A provider of links.
*/
export interface ColorProvider {
provideColors(model: editorCommon.IReadOnlyModel, token: CancellationToken): IColor[] | Thenable<IColor[]>;
provideColors(model: editorCommon.IReadOnlyModel, token: CancellationToken): IColorInfo[] | Thenable<IColorInfo[]>;
}
export interface IResourceEdit {
......
......@@ -3,96 +3,135 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { editorAction, EditorAction, CommonEditorRegistry } from "vs/editor/common/editorCommonExtensions";
import { KeyCode, KeyMod } from "vs/base/common/keyCodes";
import { ServicesAccessor } from "vs/platform/instantiation/common/instantiation";
import { EditorContextKeys } from "vs/editor/common/editorContextKeys";
import * as nls from 'vs/nls';
import { ICommonCodeEditor, IEditorContribution, IModelDeltaDecoration } from "vs/editor/common/editorCommon";
import { ICommonCodeEditor, IEditorContribution } from "vs/editor/common/editorCommon";
import { editorContribution } from "vs/editor/browser/editorBrowserExtensions";
import { ICodeEditor } from "vs/editor/browser/editorBrowser";
import { ColorPickerWidget } from "vs/editor/contrib/colorPicker/browser/colorPickerWidget";
import { Disposable, empty as EmptyDisposable } from "vs/base/common/lifecycle";
import { IDisposable } from "vs/base/common/lifecycle";
import { registerThemingParticipant } from "vs/platform/theme/common/themeService";
import { editorWidgetBackground, editorWidgetBorder } from "vs/platform/theme/common/colorRegistry";
import { Color } from "vs/base/common/color";
import { ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDecorations';
// import { Color } from "vs/base/common/color";
// import { ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDecorations';
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 * as editorCommon from 'vs/editor/common/editorCommon';
@editorContribution
export class ColorPickerController extends Disposable implements IEditorContribution {
export class ColorPicker implements IEditorContribution {
private static ID: string = 'editor.contrib.colorPicker';
private widget: ColorPickerWidget;
// private model: ColorPickerModel;
private listenersToRemove: IDisposable[];
private computePromise: TPromise<void>;
private currentDecorations: string[];
constructor(private editor: ICodeEditor) {
super();
this.listenersToRemove = [];
this.listenersToRemove.push(editor.onDidChangeModel((e) => this.onModelChanged()));
}
public getId(): string {
return ColorPickerController.ID;
return ColorPicker.ID;
}
public static get(editor: ICommonCodeEditor): ColorPickerController {
return editor.getContribution<ColorPickerController>(this.ID);
public static get(editor: ICommonCodeEditor): ColorPicker {
return editor.getContribution<ColorPicker>(this.ID);
}
public dispose(): void {
if (this.widget.visible) {
this.widget.dispose();
}
}
}
@editorContribution
export class FakeColorDecorations extends Disposable implements IEditorContribution {
private static ID: string = 'editor.contrib.fakeColorDecorations';
private onModelChanged(): void {
this.beginCompute();
}
private decorationsDisposable = EmptyDisposable;
private beginCompute(): void {
if (!this.editor.getModel()) {
return;
}
private static decorationOptions = ModelDecorationOptions.register({
inlineClassName: 'detected-color',
color: Color.green
// hoverMessage: Color.green.toString()
});
if (!ColorProviderRegistry.has(this.editor.getModel())) {
return;
}
constructor(private editor: ICodeEditor) {
super();
this._register(editor.onDidChangeModel(e => {
this.decorationsDisposable.dispose();
const model = editor.getModel();
const decoration: IModelDeltaDecoration = {
range: {
startLineNumber: 4,
startColumn: 1,
endLineNumber: 4,
endColumn: 10
},
options: FakeColorDecorations.decorationOptions
};
const old = model.deltaDecorations([], [decoration]);
this.decorationsDisposable = {
dispose: () => {
model.deltaDecorations(old, []);
}
};
}));
this.computePromise = getColors(this.editor.getModel()).then(colors => {
this.updateDecorations(colors);
this.computePromise = null;
});
}
public getId(): string {
return FakeColorDecorations.ID;
}
private updateDecorations(colors: IColorInfo[]): void {
this.editor.changeDecorations((changeAccessor: editorCommon.IModelDecorationsChangeAccessor) => {
let newDecorations: editorCommon.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
},
options: {
color: c.color
}
});
}
dispose(): void {
super.dispose();
this.currentDecorations = changeAccessor.deltaDecorations(this.currentDecorations, newDecorations);
});
}
}
// @editorContribution
// export class FakeColorDecorations extends Disposable implements IEditorContribution {
// private static ID: string = 'editor.contrib.fakeColorDecorations';
// private decorationsDisposable = EmptyDisposable;
// private static decorationOptions = ModelDecorationOptions.register({
// inlineClassName: 'detected-color',
// color: Color.green
// // hoverMessage: Color.green.toString()
// });
// constructor(private editor: ICodeEditor) {
// super();
// this._register(editor.onDidChangeModel(e => {
// this.decorationsDisposable.dispose();
// const model = editor.getModel();
// const decoration: IModelDeltaDecoration = {
// range: {
// startLineNumber: 4,
// startColumn: 1,
// endLineNumber: 4,
// endColumn: 10
// },
// options: FakeColorDecorations.decorationOptions
// };
// const old = model.deltaDecorations([], [decoration]);
// this.decorationsDisposable = {
// dispose: () => {
// model.deltaDecorations(old, []);
// }
// };
// }));
// }
// public getId(): string {
// return FakeColorDecorations.ID;
// }
// dispose(): void {
// super.dispose();
// }
// }
registerThemingParticipant((theme, collector) => {
const widgetBackground = theme.getColor(editorWidgetBackground);
collector.addRule(`.monaco-editor .colorpicker-widget { background-color: ${widgetBackground}; }`);
......@@ -102,29 +141,29 @@ registerThemingParticipant((theme, collector) => {
collector.addRule(`.monaco-editor .colorpicker-header { border-bottom: 1px solid ${widgetBorder}; }`);
});
@editorAction
class ColorPickerCommand extends EditorAction {
constructor() {
super({
id: 'editor.action.colorPicker',
label: nls.localize('editor.action.colorPicker', "Pick Color"),
alias: 'Pick Color',
precondition: null,
kbOpts: {
kbExpr: EditorContextKeys.textFocus,
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_C
}
});
}
public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void {
let controller = ColorPickerController.get(editor);
if (!controller) {
return;
}
controller.pickColor();
}
}
CommonEditorRegistry.registerEditorAction(new ColorPickerCommand());
\ No newline at end of file
// @editorAction
// class ColorPickerCommand extends EditorAction {
// constructor() {
// super({
// id: 'editor.action.colorPicker',
// label: nls.localize('editor.action.colorPicker', "Pick Color"),
// alias: 'Pick Color',
// precondition: null,
// kbOpts: {
// kbExpr: EditorContextKeys.textFocus,
// primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_C
// }
// });
// }
// public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void {
// let controller = ColorPickerController.get(editor);
// if (!controller) {
// return;
// }
// controller.pickColor();
// }
// }
// CommonEditorRegistry.registerEditorAction(new ColorPickerCommand());
\ No newline at end of file
......@@ -176,7 +176,7 @@ export class ColorPickerBody extends Disposable {
private calculateHueRGB(slider: Slider): Color {
const hueNormalizedHeight = this.hueStrip.offsetHeight - slider.domNode.offsetHeight;
const proportion = (hueNormalizedHeight - slider.top) / hueNormalizedHeight;
const proportion = 1 - ((hueNormalizedHeight - slider.top) / hueNormalizedHeight);
const hue = proportion * 360;
const hh = hue / 60;
......@@ -203,9 +203,9 @@ export class ColorPickerBody extends Disposable {
b = X;
}
r = Math.round(r * 255.0);
g = Math.round(g * 255.0);
b = Math.round(b * 255.0);
r = Math.round(r * 255);
g = Math.round(g * 255);
b = Math.round(b * 255);
return Color.fromRGBA(new RGBA(r, g, b));
}
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { TPromise } from "vs/base/common/winjs.base";
import { Color } from "vs/base/common/color";
import { ColorProviderRegistry, IColorInfo, ColorProvider } 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";
import { IRange } from 'vs/editor/common/core/range';
export class ColorInfo implements IColorInfo {
private _colorInfo: IColorInfo;
private _provider: ColorProvider;
constructor(colorInfo: IColorInfo, provider: ColorProvider) {
this._colorInfo = colorInfo;
this._provider = provider;
}
get range(): IRange {
return this._colorInfo.range;
}
get color(): Color {
return this._colorInfo.color;
}
}
export function getColors(model: IReadOnlyModel): TPromise<IColorInfo[]> {
let colors: 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.concat(result);
}
}, onUnexpectedExternalError);
});
return TPromise.join(promises).then(() => {
return colors;
});
}
\ No newline at end of file
......@@ -252,4 +252,41 @@ declare module 'vscode' {
*/
customRequest(command: string, args?: any): Thenable<any>;
}
export enum ColorType {
RGBA = 0,
HSL = 1,
Hex = 2,
Custom = 3
}
export class Color {
r: number;
g: number;
b: number;
a: number;
}
// TODO@Michel
export class ColorInfo {
/**
* The range this link applies to.
*/
range: Range;
color: Color;
type: ColorType;
constructor(range: Range, color: Color);
}
export interface DocumentColorProvider {
provideDocumentColors(document: TextDocument, token: CancellationToken): ProviderResult<ColorInfo[]>;
}
export namespace languages {
export function registerColorProvider(selector: DocumentSelector, provider: DocumentColorProvider): Disposable;
}
}
......@@ -265,6 +265,17 @@ export class MainThreadLanguageFeatures extends MainThreadLanguageFeaturesShape
return undefined;
}
// --- colors
$registerDocumentColorProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
this._registrations[handle] = modes.ColorProviderRegistry.register(selector, <modes.ColorProvider>{
provideColors: (model, token) => {
return wireCancellationToken(token, this._proxy.$provideDocumentColors(handle, model.uri));
}
});
return undefined;
}
// --- configuration
$setLanguageConfiguration(handle: number, languageId: string, _configuration: vscode.LanguageConfiguration): TPromise<any> {
......
......@@ -261,6 +261,9 @@ export function createApiFactory(
registerDocumentLinkProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentLinkProvider): vscode.Disposable {
return languageFeatures.registerDocumentLinkProvider(selector, provider);
},
registerColorProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentColorProvider): vscode.Disposable {
return languageFeatures.registerColorProvider(selector, provider);
},
setLanguageConfiguration: (language: string, configuration: vscode.LanguageConfiguration): vscode.Disposable => {
return languageFeatures.setLanguageConfiguration(language, configuration);
}
......@@ -486,6 +489,10 @@ export function createApiFactory(
// types
CancellationTokenSource: CancellationTokenSource,
CodeLens: extHostTypes.CodeLens,
Color: extHostTypes.Color,
ColorInfo: extHostTypes.ColorInfo,
ColorType: extHostTypes.ColorType,
EndOfLine: extHostTypes.EndOfLine,
CompletionItem: extHostTypes.CompletionItem,
CompletionItemKind: extHostTypes.CompletionItemKind,
CompletionList: extHostTypes.CompletionList,
......@@ -495,7 +502,6 @@ export function createApiFactory(
DocumentHighlight: extHostTypes.DocumentHighlight,
DocumentHighlightKind: extHostTypes.DocumentHighlightKind,
DocumentLink: extHostTypes.DocumentLink,
EndOfLine: extHostTypes.EndOfLine,
EventEmitter: Emitter,
Hover: extHostTypes.Hover,
IndentAction: languageConfiguration.IndentAction,
......
......@@ -229,6 +229,7 @@ export abstract class MainThreadLanguageFeaturesShape {
$registerSuggestSupport(handle: number, selector: vscode.DocumentSelector, triggerCharacters: string[]): TPromise<any> { throw ni(); }
$registerSignatureHelpProvider(handle: number, selector: vscode.DocumentSelector, triggerCharacter: string[]): TPromise<any> { throw ni(); }
$registerDocumentLinkProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any> { throw ni(); }
$registerDocumentColorProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any> { throw ni(); }
$setLanguageConfiguration(handle: number, languageId: string, configuration: vscode.LanguageConfiguration): TPromise<any> { throw ni(); }
}
......@@ -474,6 +475,7 @@ export abstract class ExtHostLanguageFeaturesShape {
$resolveCompletionItem(handle: number, resource: URI, position: IPosition, suggestion: modes.ISuggestion): TPromise<modes.ISuggestion> { throw ni(); }
$provideSignatureHelp(handle: number, resource: URI, position: IPosition): TPromise<modes.SignatureHelp> { throw ni(); }
$provideDocumentLinks(handle: number, resource: URI): TPromise<modes.ILink[]> { throw ni(); }
$provideDocumentColors(handle: number, resource: URI): TPromise<modes.IColorInfo[]> { throw ni(); }
$resolveDocumentLink(handle: number, link: modes.ILink): TPromise<modes.ILink> { throw ni(); }
}
......
......@@ -671,10 +671,32 @@ class LinkProviderAdapter {
}
}
class ColorProviderAdapter {
private _documents: ExtHostDocuments;
private _provider: vscode.DocumentColorProvider;
constructor(documents: ExtHostDocuments, provider: vscode.DocumentColorProvider) {
this._documents = documents;
this._provider = provider;
}
provideColors(resource: URI): TPromise<modes.IColorInfo[]> {
const doc = this._documents.getDocumentData(resource).document;
return asWinJsPromise(token => this._provider.provideDocumentColors(doc, token)).then(colors => {
if (Array.isArray(colors)) {
return colors.map(TypeConverters.DocumentColor.from);
}
return undefined;
});
}
}
type Adapter = OutlineAdapter | CodeLensAdapter | DefinitionAdapter | HoverAdapter
| DocumentHighlightAdapter | ReferenceAdapter | QuickFixAdapter | DocumentFormattingAdapter
| RangeFormattingAdapter | OnTypeFormattingAdapter | NavigateTypeAdapter | RenameAdapter
| SuggestAdapter | SignatureHelpAdapter | LinkProviderAdapter | ImplementationAdapter | TypeDefinitionAdapter;
| SuggestAdapter | SignatureHelpAdapter | LinkProviderAdapter | ImplementationAdapter | TypeDefinitionAdapter | ColorProviderAdapter;
export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
......@@ -959,6 +981,17 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
return this._withAdapter(handle, LinkProviderAdapter, adapter => adapter.resolveLink(link));
}
registerColorProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentColorProvider): vscode.Disposable {
const handle = this._nextHandle();
this._adapter.set(handle, new ColorProviderAdapter(this._documents, provider));
this._proxy.$registerDocumentColorProvider(handle, selector);
return this._createDisposable(handle);
}
$provideDocumentColors(handle: number, resource: URI): TPromise<modes.IColorInfo[]> {
return this._withAdapter(handle, ColorProviderAdapter, adapter => adapter.provideColors(resource));
}
// --- configuration
setLanguageConfiguration(languageId: string, configuration: vscode.LanguageConfiguration): vscode.Disposable {
......
......@@ -16,6 +16,7 @@ import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
import { IPosition } from 'vs/editor/common/core/position';
import { IRange } from 'vs/editor/common/core/range';
import { ISelection } from 'vs/editor/common/core/selection';
import { RGBA, Color } from "vs/base/common/color";
export interface PositionLike {
line: number;
......@@ -369,6 +370,15 @@ export namespace DocumentLink {
}
}
export namespace DocumentColor {
export function from(colorInfo: vscode.ColorInfo): modes.IColorInfo {
return {
range: fromRange(colorInfo.range),
color: Color.fromRGBA(new RGBA(colorInfo.color.r, colorInfo.color.g, colorInfo.color.b, colorInfo.color.a * 255))
};
}
}
export namespace TextDocumentSaveReason {
export function to(reason: SaveReason): vscode.TextDocumentSaveReason {
......
......@@ -1015,6 +1015,39 @@ export class DocumentLink {
}
}
export enum ColorType {
RGBA = 0,
HSL = 1,
Hex = 2,
Custom = 3
}
export class Color {
r: number;
g: number;
b: number;
a: number;
}
export class ColorInfo {
range: Range;
color: Color;
type: ColorType;
constructor(range: Range, color: Color) {
if (color && !(color instanceof Color)) {
throw illegalArgument('target');
}
if (!Range.isRange(range) || range.isEmpty) {
throw illegalArgument('range');
}
this.range = range;
this.color = color;
}
}
export enum TaskRevealKind {
Always = 1,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册