提交 572c7ba2 编写于 作者: J Johannes Rieken

deco - expose decorations as proposed api

上级 b0a7b57d
......@@ -168,4 +168,26 @@ declare module 'vscode' {
*/
export function registerDiffInformationCommand(command: string, callback: (diff: LineChange[], ...args: any[]) => any, thisArg?: any): Disposable;
}
//#region decorations
//todo@joh -> make class
export interface DecorationData {
priority?: number;
title?: string;
abbreviation?: string;
color?: ThemeColor;
opacity?: number;
}
export interface DecorationProvider {
onDidChangeDecorations: Event<Uri | Uri[]>;
provideDecoration(uri: Uri, token: CancellationToken): ProviderResult<DecorationData>;
}
export namespace window {
export function registerDecorationProvider(provider: DecorationProvider, label: string): Disposable;
}
//#endregion
}
......@@ -19,6 +19,7 @@ import './mainThreadCommands';
import './mainThreadConfiguration';
import './mainThreadCredentials';
import './mainThreadDebugService';
import './mainThreadDecorations';
import './mainThreadDiagnostics';
import './mainThreadDialogs';
import './mainThreadDocumentContentProviders';
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import URI from 'vs/base/common/uri';
import { Emitter } from 'vs/base/common/event';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { ExtHostContext, MainContext, IExtHostContext, MainThreadDecorationsShape, ExtHostDecorationsShape } from '../node/extHost.protocol';
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
import { IDecorationsService } from 'vs/workbench/services/decorations/browser/decorations';
@extHostNamedCustomer(MainContext.MainThreadDecorations)
export class MainThreadDecorations implements MainThreadDecorationsShape {
private readonly _provider = new Map<number, [Emitter<URI[]>, IDisposable]>();
private readonly _proxy: ExtHostDecorationsShape;
constructor(
context: IExtHostContext,
@IDecorationsService private readonly _decorationsService: IDecorationsService
) {
this._proxy = context.get(ExtHostContext.ExtHostDecorations);
}
dispose() {
this._provider.forEach(value => dispose(value));
this._provider.clear();
}
$registerDecorationProvider(handle: number, label: string): void {
let emitter = new Emitter<URI[]>();
let registration = this._decorationsService.registerDecorationsProvider({
label,
onDidChange: emitter.event,
provideDecorations: (uri) => {
return this._proxy.$providerDecorations(handle, uri).then(data => {
const [weight, title, letter, opacity, themeColor] = data;
return {
weight: weight || 0,
title,
letter,
opacity,
color: themeColor && themeColor.id
};
});
}
});
this._provider.set(handle, [emitter, registration]);
}
$onDidChange(handle: number, resources: URI[]): void {
const [emitter] = this._provider.get(handle);
emitter.fire(resources);
}
$unregisterDecorationProvider(handle: number): void {
if (this._provider.has(handle)) {
dispose(this._provider.get(handle));
this._provider.delete(handle);
}
}
}
......@@ -55,6 +55,7 @@ import { ProxyIdentifier } from 'vs/workbench/services/thread/common/threadServi
import { ExtHostDialogs } from 'vs/workbench/api/node/extHostDialogs';
import { ExtHostFileSystem } from 'vs/workbench/api/node/extHostFileSystem';
import { FileChangeType, FileType } from 'vs/platform/files/common/files';
import { ExtHostDecorations } from 'vs/workbench/api/node/extHostDecorations';
export interface IExtensionApiFactory {
(extension: IExtensionDescription): typeof vscode;
......@@ -83,6 +84,7 @@ export function createApiFactory(
// Addressable instances
const extHostHeapService = threadService.set(ExtHostContext.ExtHostHeapService, new ExtHostHeapService());
const extHostDecorations = threadService.set(ExtHostContext.ExtHostDecorations, new ExtHostDecorations(threadService));
const extHostDocumentsAndEditors = threadService.set(ExtHostContext.ExtHostDocumentsAndEditors, new ExtHostDocumentsAndEditors(threadService));
const extHostDocuments = threadService.set(ExtHostContext.ExtHostDocuments, new ExtHostDocuments(threadService, extHostDocumentsAndEditors));
const extHostDocumentContentProviders = threadService.set(ExtHostContext.ExtHostDocumentContentProviders, new ExtHostDocumentContentProvider(threadService, extHostDocumentsAndEditors));
......@@ -376,6 +378,9 @@ export function createApiFactory(
sampleFunction: proposedApiFunction(extension, () => {
return extHostMessageService.showMessage(extension, Severity.Info, 'Hello Proposed Api!', {}, []);
}),
registerDecorationProvider: proposedApiFunction(extension, (provider: vscode.DecorationProvider, label: string) => {
return extHostDecorations.registerDecorationProvider(provider, label);
})
};
// namespace: workspace
......
......@@ -135,6 +135,12 @@ export interface MainThreadDiaglogsShape extends IDisposable {
$showSaveDialog(options: MainThreadDialogSaveOptions): TPromise<string>;
}
export interface MainThreadDecorationsShape extends IDisposable {
$registerDecorationProvider(handle: number, label: string): void;
$unregisterDecorationProvider(handle: number): void;
$onDidChange(handle: number, resources: URI[]): void;
}
export interface MainThreadDocumentContentProvidersShape extends IDisposable {
$registerTextContentProvider(handle: number, scheme: string): void;
$unregisterTextContentProvider(handle: number): void;
......@@ -596,6 +602,13 @@ export interface ExtHostDebugServiceShape {
$acceptDebugSessionCustomEvent(id: DebugSessionUUID, type: string, name: string, event: any): void;
}
export type DecorationData = [number, string, string, number, ThemeColor];
export interface ExtHostDecorationsShape {
$providerDecorations(handle: number, uri: URI): TPromise<DecorationData>;
}
export interface ExtHostCredentialsShape {
}
......@@ -609,6 +622,7 @@ export const MainContext = {
MainThreadCommands: createMainId<MainThreadCommandsShape>('MainThreadCommands'),
MainThreadConfiguration: createMainId<MainThreadConfigurationShape>('MainThreadConfiguration'),
MainThreadDebugService: createMainId<MainThreadDebugServiceShape>('MainThreadDebugService'),
MainThreadDecorations: createMainId<MainThreadDecorationsShape>('MainThreadDecorations'),
MainThreadDiagnostics: createMainId<MainThreadDiagnosticsShape>('MainThreadDiagnostics'),
MainThreadDialogs: createMainId<MainThreadDiaglogsShape>('MainThreadDiaglogs'),
MainThreadDocuments: createMainId<MainThreadDocumentsShape>('MainThreadDocuments'),
......@@ -640,6 +654,7 @@ export const ExtHostContext = {
ExtHostConfiguration: createExtId<ExtHostConfigurationShape>('ExtHostConfiguration'),
ExtHostDiagnostics: createExtId<ExtHostDiagnosticsShape>('ExtHostDiagnostics'),
ExtHostDebugService: createExtId<ExtHostDebugServiceShape>('ExtHostDebugService'),
ExtHostDecorations: createExtId<ExtHostDecorationsShape>('ExtHostDecorations'),
ExtHostDocumentsAndEditors: createExtId<ExtHostDocumentsAndEditorsShape>('ExtHostDocumentsAndEditors'),
ExtHostDocuments: createExtId<ExtHostDocumentsShape>('ExtHostDocuments'),
ExtHostDocumentContentProviders: createExtId<ExtHostDocumentContentProvidersShape>('ExtHostDocumentContentProviders'),
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as vscode from 'vscode';
import URI from 'vs/base/common/uri';
import { MainContext, IMainContext, ExtHostDecorationsShape, MainThreadDecorationsShape, DecorationData } from 'vs/workbench/api/node/extHost.protocol';
import { TPromise } from 'vs/base/common/winjs.base';
import { Disposable } from 'vs/workbench/api/node/extHostTypes';
import { asWinJsPromise } from 'vs/base/common/async';
export class ExtHostDecorations implements ExtHostDecorationsShape {
private static _handlePool = 0;
private readonly _provider = new Map<number, vscode.DecorationProvider>();
private readonly _proxy: MainThreadDecorationsShape;
constructor(mainContext: IMainContext) {
this._proxy = mainContext.get(MainContext.MainThreadDecorations);
}
registerDecorationProvider(provider: vscode.DecorationProvider, label: string): vscode.Disposable {
const handle = ExtHostDecorations._handlePool++;
this._provider.set(handle, provider);
this._proxy.$registerDecorationProvider(handle, label);
const listener = provider.onDidChangeDecorations(e => {
this._proxy.$onDidChange(handle, Array.isArray(e) ? e : [e]);
});
return new Disposable(() => {
listener.dispose();
this._proxy.$unregisterDecorationProvider(handle);
this._provider.delete(handle);
});
}
$providerDecorations(handle: number, uri: URI): TPromise<DecorationData> {
const provider = this._provider.get(handle);
return asWinJsPromise(token => provider.provideDecoration(uri, token)).then(data => {
return <DecorationData>[data.priority, data.title, data.abbreviation, data.opacity, data.color];
});
}
}
......@@ -44,6 +44,7 @@ class MarkersDecorationsProvider implements IDecorationsProvider {
return {
weight: 100 * first.severity,
bubble: true,
title: markers.length === 1 ? localize('tooltip.1', "1 problem in this file") : localize('tooltip.N', "{0} problems in this file", markers.length),
letter: markers.length.toString(),
color: first.severity === Severity.Error ? editorErrorForeground : editorWarningForeground,
......
......@@ -65,7 +65,8 @@ class SCMDecorationsProvider implements IDecorationsProvider {
return undefined;
}
return {
weight: 100 - resource.decorations.tooltip.charAt(0).toLowerCase().charCodeAt(0),
bubble: true,
weight: 255 - resource.decorations.tooltip.charAt(0).toLowerCase().charCodeAt(0),
title: localize('tooltip', "{0}, {1}", resource.decorations.tooltip, this._provider.label),
color: resource.decorations.color,
letter: resource.decorations.tooltip.charAt(0)
......
......@@ -18,6 +18,7 @@ export interface IDecorationData {
readonly opacity?: number;
readonly letter?: string;
readonly title?: string;
readonly bubble?: boolean;
}
export interface IDecoration {
......
......@@ -347,6 +347,12 @@ export class FileDecorationsService implements IDecorationsService {
this._onDidChangeDecorationsDelayed
);
const remove = this._data.push(wrapper);
this._onDidChangeDecorations.fire({
// everything might have changed
affectsResource() { return true; }
});
return {
dispose: () => {
// fire event that says 'yes' for any resource
......@@ -363,9 +369,10 @@ export class FileDecorationsService implements IDecorationsService {
let onlyChildren = true;
for (let iter = this._data.iterator(), next = iter.next(); !next.done; next = iter.next()) {
next.value.getOrRetrieve(uri, includeChildren, (deco, isChild) => {
// top = FileDecorationsService._pickBest(top, candidate);
data.push(deco);
onlyChildren = onlyChildren && isChild;
if (!isChild || deco.bubble) {
data.push(deco);
onlyChildren = onlyChildren && isChild;
}
});
}
......
......@@ -103,4 +103,43 @@ suite('DecorationsService', function () {
reg.dispose();
assert.equal(didSeeEvent, true);
});
test('No default bubbling', function () {
let reg = service.registerDecorationsProvider({
label: 'Test',
onDidChange: Event.None,
provideDecorations(uri: URI) {
return uri.path.match(/\.txt/)
? { title: '.txt' }
: undefined;
}
});
let childUri = URI.parse('file:///some/path/some/file.txt');
let deco = service.getDecoration(childUri, false);
assert.equal(deco.title, '.txt');
deco = service.getDecoration(childUri.with({ path: 'some/path/' }), true);
assert.equal(deco, undefined);
reg.dispose();
// bubble
reg = service.registerDecorationsProvider({
label: 'Test',
onDidChange: Event.None,
provideDecorations(uri: URI) {
return uri.path.match(/\.txt/)
? { title: '.txt.bubble', bubble: true }
: undefined;
}
});
deco = service.getDecoration(childUri, false);
assert.equal(deco.title, '.txt.bubble');
deco = service.getDecoration(childUri.with({ path: 'some/path/' }), true);
assert.equal(deco.title, '.txt.bubble');
});
});
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册