Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into hide-activity-bar
Browse files Browse the repository at this point in the history
  • Loading branch information
bpasero committed Nov 10, 2016
2 parents b994f2e + 2d75d95 commit 86a4be1
Show file tree
Hide file tree
Showing 29 changed files with 1,214 additions and 37 deletions.
7 changes: 7 additions & 0 deletions src/vs/base/browser/ui/actionbar/actionbar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,13 @@ export class ActionBar extends EventEmitter implements IActionRunner {
});
}

public pull(index: number): void {
if (index >= 0 && index < this.items.length) {
this.items.splice(index, 1);
this.actionsList.removeChild(this.actionsList.childNodes[index]);
}
}

public clear(): void {
// Do not dispose action items if they were provided from outside
this.items = this.options.actionItemProvider ? [] : lifecycle.dispose(this.items);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@ export interface ITheme {
label: string;
}

export interface ITreeExplorer {
treeExplorerNodeProviderId: string;
treeLabel: string;
icon: string;
}

export interface IExtensionContributions {
commands?: ICommand[];
configuration?: IConfiguration;
Expand All @@ -86,6 +92,7 @@ export interface IExtensionContributions {
menus?: { [context: string]: IMenu[] };
snippets?: ISnippet[];
themes?: ITheme[];
explorer?: ITreeExplorer;
}

export interface IExtensionManifest {
Expand Down
76 changes: 75 additions & 1 deletion src/vs/vscode.proposed.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,78 @@ declare module 'vscode' {

export function sampleFunction(): Thenable<any>;
}
}

export namespace workspace {

/**
* Register a [TreeExplorerNodeProvider](#TreeExplorerNodeProvider).
*
* @param providerId A unique id that identifies the provider.
* @param provider A [TreeExplorerNodeProvider](#TreeExplorerNodeProvider).
* @return A [disposable](#Disposable) that unregisters this provider when being disposed.
*/
export function registerTreeExplorerNodeProvider(providerId: string, provider: TreeExplorerNodeProvider<any>): Disposable;
}

/**
* A node provider for a tree explorer contribution.
*
* Providers are registered through (#workspace.registerTreeExplorerNodeProvider) with a
* `providerId` that corresponds to the `treeExplorerNodeProviderId` in the extension's
* `contributes.explorer` section.
*
* The contributed tree explorer will ask the corresponding provider to provide the root
* node and resolve children for each node. In addition, the provider could **optionally**
* provide the following information for each node:
* - label: A human-readable label used for rendering the node.
* - hasChildren: Whether the node has children and is expandable.
* - clickCommand: A command to execute when the node is clicked.
*/
export interface TreeExplorerNodeProvider<T> {

/**
* Provide the root node. This function will be called when the tree explorer is activated
* for the first time. The root node is hidden and its direct children will be displayed on the first level of
* the tree explorer.
*
* @return The root node.
*/
provideRootNode(): T | Thenable<T>;

/**
* Resolve the children of `node`.
*
* @param node The node from which the provider resolves children.
* @return Children of `node`.
*/
resolveChildren(node: T): T[] | Thenable<T[]>;

/**
* Provide a human-readable string that will be used for rendering the node. Default to use
* `node.toString()` if not provided.
*
* @param node The node from which the provider computes label.
* @return A human-readable label.
*/
getLabel?(node: T): string;

/**
* Determine if `node` has children and is expandable. Default to `true` if not provided.
*
* @param node The node to determine if it has children and is expandable.
* @return A boolean that determines if `node` has children and is expandable.
*/
getHasChildren?(node: T): boolean;

/**
* Get the command to execute when `node` is clicked.
*
* Commands can be registered through [registerCommand](#commands.registerCommand). `node` will be provided
* as the first argument to the command's callback function.
*
* @param node The node that the command is associated with.
* @return The command to execute when `node` is clicked.
*/
getClickCommand?(node: T): string;
}
}
5 changes: 5 additions & 0 deletions src/vs/workbench/api/node/extHost.api.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
import { ExtHostDocumentSaveParticipant } from 'vs/workbench/api/node/extHostDocumentSaveParticipant';
import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration';
import { ExtHostDiagnostics } from 'vs/workbench/api/node/extHostDiagnostics';
import { ExtHostTreeExplorers } from 'vs/workbench/api/node/extHostTreeExplorers';
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import { ExtHostQuickOpen } from 'vs/workbench/api/node/extHostQuickOpen';
import { ExtHostHeapService } from 'vs/workbench/api/node/extHostHeapService';
Expand Down Expand Up @@ -73,6 +74,7 @@ export function createApiFactory(initDataConfiguration: WorkspaceConfigurationNo
const extHostDocumentSaveParticipant = col.define(ExtHostContext.ExtHostDocumentSaveParticipant).set<ExtHostDocumentSaveParticipant>(new ExtHostDocumentSaveParticipant(extHostDocuments, threadService.get(MainContext.MainThreadWorkspace)));
const extHostEditors = col.define(ExtHostContext.ExtHostEditors).set<ExtHostEditors>(new ExtHostEditors(threadService, extHostDocuments));
const extHostCommands = col.define(ExtHostContext.ExtHostCommands).set<ExtHostCommands>(new ExtHostCommands(threadService, extHostEditors, extHostHeapService));
const extHostExplorers = col.define(ExtHostContext.ExtHostExplorers).set<ExtHostTreeExplorers>(new ExtHostTreeExplorers(threadService, extHostCommands));
const extHostConfiguration = col.define(ExtHostContext.ExtHostConfiguration).set<ExtHostConfiguration>(new ExtHostConfiguration(threadService.get(MainContext.MainThreadConfiguration), initDataConfiguration));
const extHostDiagnostics = col.define(ExtHostContext.ExtHostDiagnostics).set<ExtHostDiagnostics>(new ExtHostDiagnostics(threadService));
const languageFeatures = col.define(ExtHostContext.ExtHostLanguageFeatures).set<ExtHostLanguageFeatures>(new ExtHostLanguageFeatures(threadService, extHostDocuments, extHostCommands, extHostHeapService, extHostDiagnostics));
Expand Down Expand Up @@ -341,6 +343,9 @@ export function createApiFactory(initDataConfiguration: WorkspaceConfigurationNo
onWillSaveTextDocument: (listener, thisArgs?, disposables?) => {
return extHostDocumentSaveParticipant.onWillSaveTextDocumentEvent(listener, thisArgs, disposables);
},
registerTreeExplorerNodeProvider: proposedApiFunction(extension, (providerId: string, provider: vscode.TreeExplorerNodeProvider<any>) => {
return extHostExplorers.registerTreeExplorerNodeProvider(providerId, provider);
}),
onDidChangeConfiguration: (listener: () => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) => {
return extHostConfiguration.onDidChangeConfiguration(listener, thisArgs, disposables);
},
Expand Down
2 changes: 2 additions & 0 deletions src/vs/workbench/api/node/extHost.contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { MainThreadDiagnostics } from './mainThreadDiagnostics';
import { MainThreadDocuments } from './mainThreadDocuments';
import { MainThreadEditors } from './mainThreadEditors';
import { MainThreadErrors } from './mainThreadErrors';
import { MainThreadTreeExplorers } from './mainThreadTreeExplorers';
import { MainThreadLanguageFeatures } from './mainThreadLanguageFeatures';
import { MainThreadLanguages } from './mainThreadLanguages';
import { MainThreadMessageService } from './mainThreadMessageService';
Expand Down Expand Up @@ -70,6 +71,7 @@ export class ExtHostContribution implements IWorkbenchContribution {
col.define(MainContext.MainThreadDocuments).set(create(MainThreadDocuments));
col.define(MainContext.MainThreadEditors).set(create(MainThreadEditors));
col.define(MainContext.MainThreadErrors).set(create(MainThreadErrors));
col.define(MainContext.MainThreadExplorers).set(create(MainThreadTreeExplorers));
col.define(MainContext.MainThreadLanguageFeatures).set(create(MainThreadLanguageFeatures));
col.define(MainContext.MainThreadLanguages).set(create(MainThreadLanguages));
col.define(MainContext.MainThreadMessageService).set(create(MainThreadMessageService));
Expand Down
14 changes: 14 additions & 0 deletions src/vs/workbench/api/node/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
import { IWorkspaceSymbol } from 'vs/workbench/parts/search/common/search';
import { IApplyEditsOptions, TextEditorRevealType, ITextEditorConfigurationUpdate, IResolvedTextEditorConfiguration, ISelectionChangeEvent } from './mainThreadEditorsTracker';

import { InternalTreeExplorerNodeContent } from 'vs/workbench/parts/explorers/common/treeExplorerViewModel';

export interface IEnvironment {
appSettingsHome: string;
disableExtensions: boolean;
Expand Down Expand Up @@ -136,6 +138,10 @@ export abstract class MainThreadEditorsShape {
$tryApplyEdits(id: string, modelVersionId: number, edits: editorCommon.ISingleEditOperation[], opts: IApplyEditsOptions): TPromise<boolean> { throw ni(); }
}

export abstract class MainThreadTreeExplorersShape {
$registerTreeExplorerNodeProvider(providerId: string): void { throw ni(); }
}

export abstract class MainThreadErrorsShape {
onUnexpectedExtHostError(err: any): void { throw ni(); }
}
Expand Down Expand Up @@ -277,6 +283,12 @@ export abstract class ExtHostEditorsShape {
$acceptTextEditorRemove(id: string): void { throw ni(); }
}

export abstract class ExtHostTreeExplorersShape {
$provideRootNode(providerId: string): TPromise<InternalTreeExplorerNodeContent> { throw ni(); };
$resolveChildren(providerId: string, node: InternalTreeExplorerNodeContent): TPromise<InternalTreeExplorerNodeContent[]> { throw ni(); }
$getInternalCommand(providerId: string, node: InternalTreeExplorerNodeContent): TPromise<modes.Command> { throw ni(); }
}

export abstract class ExtHostExtensionServiceShape {
$localShowMessage(severity: Severity, msg: string): void { throw ni(); }
$activateExtension(extensionDescription: IExtensionDescription): TPromise<void> { throw ni(); }
Expand Down Expand Up @@ -351,6 +363,7 @@ export const MainContext = {
MainThreadDocuments: createMainId<MainThreadDocumentsShape>('MainThreadDocuments', MainThreadDocumentsShape),
MainThreadEditors: createMainId<MainThreadEditorsShape>('MainThreadEditors', MainThreadEditorsShape),
MainThreadErrors: createMainId<MainThreadErrorsShape>('MainThreadErrors', MainThreadErrorsShape),
MainThreadExplorers: createMainId<MainThreadTreeExplorersShape>('MainThreadExplorers', MainThreadTreeExplorersShape),
MainThreadLanguageFeatures: createMainId<MainThreadLanguageFeaturesShape>('MainThreadLanguageFeatures', MainThreadLanguageFeaturesShape),
MainThreadLanguages: createMainId<MainThreadLanguagesShape>('MainThreadLanguages', MainThreadLanguagesShape),
MainThreadMessageService: createMainId<MainThreadMessageServiceShape>('MainThreadMessageService', MainThreadMessageServiceShape),
Expand All @@ -371,6 +384,7 @@ export const ExtHostContext = {
ExtHostDocuments: createExtId<ExtHostDocumentsShape>('ExtHostDocuments', ExtHostDocumentsShape),
ExtHostDocumentSaveParticipant: createExtId<ExtHostDocumentSaveParticipantShape>('ExtHostDocumentSaveParticipant', ExtHostDocumentSaveParticipantShape),
ExtHostEditors: createExtId<ExtHostEditorsShape>('ExtHostEditors', ExtHostEditorsShape),
ExtHostExplorers: createExtId<ExtHostTreeExplorersShape>('ExtHostExplorers', ExtHostTreeExplorersShape),
ExtHostFileSystemEventService: createExtId<ExtHostFileSystemEventServiceShape>('ExtHostFileSystemEventService', ExtHostFileSystemEventServiceShape),
ExtHostHeapService: createExtId<ExtHostHeapServiceShape>('ExtHostHeapMonitor', ExtHostHeapServiceShape),
ExtHostLanguageFeatures: createExtId<ExtHostLanguageFeaturesShape>('ExtHostLanguageFeatures', ExtHostLanguageFeaturesShape),
Expand Down
107 changes: 107 additions & 0 deletions src/vs/workbench/api/node/extHostTreeExplorers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*---------------------------------------------------------------------------------------------
* 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 { localize } from 'vs/nls';
import { TreeExplorerNodeProvider } from 'vscode';
import { TPromise } from 'vs/base/common/winjs.base';
import { Disposable } from 'vs/workbench/api/node/extHostTypes';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { MainContext, ExtHostTreeExplorersShape, MainThreadTreeExplorersShape } from './extHost.protocol';
import { InternalTreeExplorerNode } from 'vs/workbench/parts/explorers/common/treeExplorerViewModel';
import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
import { asWinJsPromise } from 'vs/base/common/async';
import * as modes from 'vs/editor/common/modes';

export class ExtHostTreeExplorers extends ExtHostTreeExplorersShape {
private _proxy: MainThreadTreeExplorersShape;

private _extNodeProviders: { [providerId: string]: TreeExplorerNodeProvider<any> };
private _extNodeMaps: { [providerId: string]: { [id: number]: any } };

constructor(
threadService: IThreadService,
private commands: ExtHostCommands
) {
super();

this._proxy = threadService.get(MainContext.MainThreadExplorers);

this._extNodeProviders = Object.create(null);
this._extNodeMaps = Object.create(null);
}

registerTreeExplorerNodeProvider(providerId: string, provider: TreeExplorerNodeProvider<any>): Disposable {
this._proxy.$registerTreeExplorerNodeProvider(providerId);
this._extNodeProviders[providerId] = provider;

return new Disposable(() => {
delete this._extNodeProviders[providerId];
delete this._extNodeProviders[providerId];
});
}

$provideRootNode(providerId: string): TPromise<InternalTreeExplorerNode> {
const provider = this._extNodeProviders[providerId];
if (!provider) {
const errMessage = localize('treeExplorer.notRegistered', 'No TreeExplorerNodeProvider with id \'{0}\' registered.', providerId);
return TPromise.wrapError(errMessage);
}

return asWinJsPromise(() => provider.provideRootNode()).then(extRootNode => {
const extNodeMap = Object.create(null);
const internalRootNode = new InternalTreeExplorerNode(extRootNode, provider);

extNodeMap[internalRootNode.id] = extRootNode;
this._extNodeMaps[providerId] = extNodeMap;

return internalRootNode;
}, err => {
const errMessage = localize('treeExplorer.failedToProvideRootNode', 'TreeExplorerNodeProvider \'{0}\' failed to provide root node.', providerId);
return TPromise.wrapError(errMessage);
});
}

$resolveChildren(providerId: string, mainThreadNode: InternalTreeExplorerNode): TPromise<InternalTreeExplorerNode[]> {
const provider = this._extNodeProviders[providerId];
if (!provider) {
const errMessage = localize('treeExplorer.notRegistered', 'No TreeExplorerNodeProvider with id \'{0}\' registered.', providerId);
return TPromise.wrapError(errMessage);
}

const extNodeMap = this._extNodeMaps[providerId];
const extNode = extNodeMap[mainThreadNode.id];

return asWinJsPromise(() => provider.resolveChildren(extNode)).then(children => {
return children.map(extChild => {
const internalChild = new InternalTreeExplorerNode(extChild, provider);
extNodeMap[internalChild.id] = extChild;
return internalChild;
});
}, err => {
const errMessage = localize('treeExplorer.failedToResolveChildren', 'TreeExplorerNodeProvider \'{0}\' failed to resolveChildren.', providerId);
return TPromise.wrapError(errMessage);
});
}

// Convert the command on the ExtHost side so we can pass the original externalNode to the registered handler
$getInternalCommand(providerId: string, mainThreadNode: InternalTreeExplorerNode): TPromise<modes.Command> {
const commandConverter = this.commands.converter;

if (mainThreadNode.clickCommand) {
const extNode = this._extNodeMaps[providerId][mainThreadNode.id];

const internalCommand = commandConverter.toInternal({
title: '',
command: mainThreadNode.clickCommand,
arguments: [extNode]
});

return TPromise.wrap(internalCommand);
}

return TPromise.as(null);
}
}
46 changes: 46 additions & 0 deletions src/vs/workbench/api/node/mainThreadTreeExplorers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*---------------------------------------------------------------------------------------------
* 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 { TPromise } from 'vs/base/common/winjs.base';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { ExtHostContext, MainThreadTreeExplorersShape, ExtHostTreeExplorersShape } from './extHost.protocol';
import { ICustomTreeExplorerService } from 'vs/workbench/parts/explorers/browser/customTreeExplorerService';
import { InternalTreeExplorerNodeContent } from 'vs/workbench/parts/explorers/common/treeExplorerViewModel';
import { IMessageService, Severity } from 'vs/platform/message/common/message';
import { ICommandService } from 'vs/platform/commands/common/commands';

export class MainThreadTreeExplorers extends MainThreadTreeExplorersShape {
private _proxy: ExtHostTreeExplorersShape;

constructor(
@IThreadService private threadService: IThreadService,
@ICustomTreeExplorerService private treeExplorerService: ICustomTreeExplorerService,
@IMessageService private messageService: IMessageService,
@ICommandService private commandService: ICommandService
) {
super();

this._proxy = threadService.get(ExtHostContext.ExtHostExplorers);
}

$registerTreeExplorerNodeProvider(providerId: string): void {
const onError = err => { this.messageService.show(Severity.Error, err); };

this.treeExplorerService.registerTreeExplorerNodeProvider(providerId, {
provideRootNode: (): TPromise<InternalTreeExplorerNodeContent> => {
return this._proxy.$provideRootNode(providerId).then(rootNode => rootNode, onError);
},
resolveChildren: (node: InternalTreeExplorerNodeContent): TPromise<InternalTreeExplorerNodeContent[]> => {
return this._proxy.$resolveChildren(providerId, node).then(children => children, onError);
},
executeCommand: (node: InternalTreeExplorerNodeContent): TPromise<any> => {
return this._proxy.$getInternalCommand(providerId, node).then(command => {
return this.commandService.executeCommand(command.id, ...command.arguments);
});
}
});
}
}
Loading

0 comments on commit 86a4be1

Please sign in to comment.