diff --git a/src/vs/workbench/api/electron-browser/mainThreadTreeViews.ts b/src/vs/workbench/api/electron-browser/mainThreadTreeViews.ts index a43537e66b0..d8760b4d574 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadTreeViews.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadTreeViews.ts @@ -8,7 +8,7 @@ import { Event, Emitter } from 'vs/base/common/event'; import { TPromise } from 'vs/base/common/winjs.base'; import { Disposable } from 'vs/base/common/lifecycle'; import { ExtHostContext, MainThreadTreeViewsShape, ExtHostTreeViewsShape, MainContext, IExtHostContext } from '../node/extHost.protocol'; -import { ITreeViewDataProvider, ITreeItem, IViewsService } from 'vs/workbench/common/views'; +import { ITreeViewDataProvider, ITreeItem, IViewsService, ITreeViewer } from 'vs/workbench/common/views'; import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; import { distinct } from 'vs/base/common/arrays'; import { INotificationService } from 'vs/platform/notification/common/notification'; @@ -34,6 +34,7 @@ export class MainThreadTreeViews extends Disposable implements MainThreadTreeVie const treeViewer = this.viewsService.getTreeViewer(treeViewId); if (treeViewer) { treeViewer.dataProvider = dataProvider; + this.registerListeners(treeViewId, treeViewer); } else { this.notificationService.error('No view is registered with id: ' + treeViewId); } @@ -54,6 +55,11 @@ export class MainThreadTreeViews extends Disposable implements MainThreadTreeVie } } + private registerListeners(treeViewId: string, treeViewer: ITreeViewer): void { + this._register(treeViewer.onDidExpandItem(item => this._proxy.$setExpanded(treeViewId, item.handle, true))); + this._register(treeViewer.onDidCollapseItem(item => this._proxy.$setExpanded(treeViewId, item.handle, false))); + } + dispose(): void { this._dataProviders.clear(); super.dispose(); diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 55bc964bcf0..57f0d2fde24 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -575,6 +575,7 @@ export interface ExtHostDocumentsAndEditorsShape { export interface ExtHostTreeViewsShape { $getChildren(treeViewId: string, treeItemHandle?: string): TPromise; + $setExpanded(treeViewId: string, treeItemHandle: string, expanded: boolean): void; } export interface ExtHostWorkspaceShape { diff --git a/src/vs/workbench/api/node/extHostTreeViews.ts b/src/vs/workbench/api/node/extHostTreeViews.ts index 9cadef91101..f42af8e8de5 100644 --- a/src/vs/workbench/api/node/extHostTreeViews.ts +++ b/src/vs/workbench/api/node/extHostTreeViews.ts @@ -8,7 +8,7 @@ import { localize } from 'vs/nls'; import * as vscode from 'vscode'; import { basename } from 'vs/base/common/paths'; import URI from 'vs/base/common/uri'; -import { debounceEvent } from 'vs/base/common/event'; +import { debounceEvent, Emitter, Event } from 'vs/base/common/event'; import { TPromise } from 'vs/base/common/winjs.base'; import { Disposable } from 'vs/base/common/lifecycle'; import { ExtHostTreeViewsShape, MainThreadTreeViewsShape } from './extHost.protocol'; @@ -67,6 +67,14 @@ export class ExtHostTreeViews implements ExtHostTreeViewsShape { return treeView.getChildren(treeItemHandle); } + $setExpanded(treeViewId: string, treeItemHandle: string, expanded: boolean): void { + const treeView = this.treeViews.get(treeViewId); + if (treeView) { + treeView.setExpanded(treeItemHandle, expanded); + } + TPromise.wrapError(new Error(localize('treeView.notRegistered', 'No tree view with id \'{0}\' registered.', treeViewId))); + } + private createExtHostTreeViewer(id: string, dataProvider: vscode.TreeDataProvider): ExtHostTreeView { const treeView = new ExtHostTreeView(id, dataProvider, this._proxy, this.commands.converter); this.treeViews.set(id, treeView); @@ -94,6 +102,12 @@ class ExtHostTreeView extends Disposable { private elements: Map = new Map(); private nodes: Map = new Map(); + private _onDidExpandElement: Emitter = this._register(new Emitter()); + readonly onDidExpandElement: Event = this._onDidExpandElement.event; + + private _onDidCollapseElement: Emitter = this._register(new Emitter()); + readonly onDidCollapseElement: Event = this._onDidCollapseElement.event; + constructor(private viewId: string, private dataProvider: vscode.TreeDataProvider, private proxy: MainThreadTreeViewsShape, private commands: CommandsConverter) { super(); this.proxy.$registerTreeViewDataProvider(viewId); @@ -127,6 +141,17 @@ class ExtHostTreeView extends Disposable { .then(treeNode => this.proxy.$reveal(this.viewId, treeNode.item, parentChain.map(p => p.item), options))); } + setExpanded(treeItemHandle: TreeItemHandle, expanded: boolean): void { + const element = this.getExtensionElement(treeItemHandle); + if (element) { + if (expanded) { + this._onDidExpandElement.fire(element); + } else { + this._onDidCollapseElement.fire(element); + } + } + } + private resolveUnknownParentChain(element: T): TPromise { return this.resolveParent(element) .then((parent) => { diff --git a/src/vs/workbench/browser/parts/views/customView.ts b/src/vs/workbench/browser/parts/views/customView.ts index 80f4e237f9b..cfddcdd221a 100644 --- a/src/vs/workbench/browser/parts/views/customView.ts +++ b/src/vs/workbench/browser/parts/views/customView.ts @@ -32,6 +32,7 @@ import { ICommandService } from 'vs/platform/commands/common/commands'; import { FileIconThemableWorkbenchTree } from 'vs/workbench/browser/parts/views/viewsViewlet'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { isUndefinedOrNull } from 'vs/base/common/types'; +import { Emitter, Event } from 'vs/base/common/event'; export class CustomViewsService extends Disposable implements IViewsService { @@ -112,6 +113,12 @@ class CustomTreeViewer extends Disposable implements ITreeViewer { private _dataProvider: ITreeViewDataProvider; private dataProviderDisposables: IDisposable[] = []; + private _onDidExpandItem: Emitter = this._register(new Emitter()); + readonly onDidExpandItem: Event = this._onDidExpandItem.event; + + private _onDidCollapseItem: Emitter = this._register(new Emitter()); + readonly onDidCollapseItem: Event = this._onDidCollapseItem.event; + constructor( private id: string, private location: ViewLocation, @@ -224,6 +231,8 @@ class CustomTreeViewer extends Disposable implements ITreeViewer { this.tree.contextKeyService.createKey(this.id, true); this._register(this.tree); this._register(this.tree.onDidChangeSelection(e => this.onSelection(e))); + this._register(this.tree.onDidExpandItem(e => this._onDidExpandItem.fire(e.item.getElement()))); + this._register(this.tree.onDidCollapseItem(e => this._onDidCollapseItem.fire(e.item.getElement()))); this.tree.setInput(this.root); } diff --git a/src/vs/workbench/common/views.ts b/src/vs/workbench/common/views.ts index 8fb99569d83..f9bb7fdfe45 100644 --- a/src/vs/workbench/common/views.ts +++ b/src/vs/workbench/common/views.ts @@ -161,6 +161,10 @@ export interface ITreeViewer extends IDisposable { dataProvider: ITreeViewDataProvider; + readonly onDidExpandItem: Event; + + readonly onDidCollapseItem: Event; + refresh(treeItems?: ITreeItem[]): TPromise; setVisibility(visible: boolean): void;