diff --git a/samples/sqlservices/package.json b/samples/sqlservices/package.json index fc4e7b377c..4e8011c41f 100644 --- a/samples/sqlservices/package.json +++ b/samples/sqlservices/package.json @@ -100,7 +100,7 @@ "sqlops": "github:anthonydresser/sqlops-extension-sqlops", "tslint": "^3.14.0", "typescript": "^2.6.1", - "vscode": "^1.1.14", + "vscode": "^1.1.18", "@types/handlebars": "^4.0.11", "vsce": "1.36.2" }, diff --git a/samples/sqlservices/src/controllers/mainController.ts b/samples/sqlservices/src/controllers/mainController.ts index 1460d0abf2..def3ae1039 100644 --- a/samples/sqlservices/src/controllers/mainController.ts +++ b/samples/sqlservices/src/controllers/mainController.ts @@ -114,7 +114,17 @@ export default class MainController implements vscode.Disposable { let tree: sqlops.TreeComponent = view.modelBuilder.tree().withProperties({ 'withCheckbox': true }).component(); - tree.registerDataProvider(treeDataProvider); + let treeView = tree.registerDataProvider(treeDataProvider); + treeView.onNodeCheckedChanged(item => { + if (item && item.element) { + item.element.changeNodeCheckedState(item.checked); + } + }); + treeView.onDidChangeSelection(selectedNodes => { + selectedNodes.forEach(node => { + console.info('tree node selected: ' + node.label); + }); + }); let formModel = view.modelBuilder.formContainer() .withFormItems([{ component: tree, @@ -150,7 +160,7 @@ export default class MainController implements vscode.Disposable { }) .component(); checkbox.onChanged(e => { - console.info("inputBox.enabled " + inputBox.enabled); + console.info('inputBox.enabled ' + inputBox.enabled); inputBox.enabled = !inputBox.enabled; }); let button = view.modelBuilder.button() diff --git a/samples/sqlservices/src/controllers/treeDataProvider.ts b/samples/sqlservices/src/controllers/treeDataProvider.ts index cf84d4608d..253d85dd55 100644 --- a/samples/sqlservices/src/controllers/treeDataProvider.ts +++ b/samples/sqlservices/src/controllers/treeDataProvider.ts @@ -291,9 +291,4 @@ export class TreeDataProvider implements sqlops.TreeComponentDataProvider { + this._dataProvider.onNodeSelected(e.selection); + })); this._tree.refresh(); this.layout(); } diff --git a/src/sql/parts/modelComponents/tree/treeComponentRenderer.ts b/src/sql/parts/modelComponents/tree/treeComponentRenderer.ts index 067e82435f..854bcba356 100644 --- a/src/sql/parts/modelComponents/tree/treeComponentRenderer.ts +++ b/src/sql/parts/modelComponents/tree/treeComponentRenderer.ts @@ -15,6 +15,7 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { Event, Emitter } from 'vs/base/common/event'; import { ITreeComponentItem } from 'sql/workbench/common/views'; import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService'; +import { TreeViewDataProvider } from './treeViewDataProvider'; export enum TreeCheckboxState { Intermediate = 0, @@ -90,6 +91,7 @@ export class TreeComponentRenderer extends Disposable implements IRenderer { constructor( + private _dataProvider: TreeViewDataProvider, private themeService: IWorkbenchThemeService, public options?: { withCheckbox: boolean } ) { @@ -137,7 +139,10 @@ export class TreeComponentRenderer extends Disposable implements IRenderer { const icon = this.themeService.getTheme().type === LIGHT ? element.icon : element.iconDark; templateData.icon.style.backgroundImage = icon ? `url('${icon}')` : ''; dom.toggleClass(templateData.icon, 'model-view-tree-node-item-icon', !!icon); - if (element && !templateData.model) { + if (element) { + element.onCheckedChanged = (checked: boolean) => { + this._dataProvider.onNodeCheckedChanged(element.handle, checked); + } templateData.model = element; } if (templateId === TreeComponentRenderer.DEFAULT_TEMPLATE) { diff --git a/src/sql/parts/modelComponents/tree/treeViewDataProvider.ts b/src/sql/parts/modelComponents/tree/treeViewDataProvider.ts index fd14e2ef61..9c19345d68 100644 --- a/src/sql/parts/modelComponents/tree/treeViewDataProvider.ts +++ b/src/sql/parts/modelComponents/tree/treeViewDataProvider.ts @@ -19,21 +19,13 @@ export class TreeViewDataProvider extends vsTreeView.TreeViewDataProvider implem super(`${handle}-${treeViewId}`, context.getProxy(SqlExtHostContext.ExtHostModelViewTreeViews), notificationService); } - onNodeCheckedChanged(treeViewId: string, treeItemHandle?: string, checked?: boolean) { - (this._proxy).$onNodeCheckedChanged(treeViewId, treeItemHandle, checked); + onNodeCheckedChanged(treeItemHandle?: string, checked?: boolean) { + (this._proxy).$onNodeCheckedChanged(this.treeViewId, treeItemHandle, checked); } - protected postGetChildren(elements: ITreeComponentItem[]): ITreeComponentItem[] { - const result = []; - if (elements) { - for (const element of elements) { - element.onCheckedChanged = (checked: boolean) => { - this.onNodeCheckedChanged(this.treeViewId, element.handle, checked); - }; - this.itemsMap.set(element.handle, element); - result.push(element); - } + onNodeSelected(items: ITreeComponentItem[]) { + if (items) { + (this._proxy).$onNodeSelected(this.treeViewId, items.map(i => i.handle)); } - return result; } } diff --git a/src/sql/sqlops.proposed.d.ts b/src/sql/sqlops.proposed.d.ts index 17c29d1fb6..2c7ef1df48 100644 --- a/src/sql/sqlops.proposed.d.ts +++ b/src/sql/sqlops.proposed.d.ts @@ -42,10 +42,17 @@ declare module 'sqlops' { export interface TreeComponentDataProvider extends vscode.TreeDataProvider { getTreeItem(element: T): TreeComponentItem | Thenable; - - onNodeCheckedChanged?(element: T, checked: boolean): void; } + export interface NodeCheckedEventParameters { + element: T, + checked: boolean + } + + export interface TreeComponentView extends vscode.Disposable { + onNodeCheckedChanged: vscode.Event>; + onDidChangeSelection: vscode.Event; + } export class TreeComponentItem extends vscode.TreeItem { checked?: boolean; @@ -531,7 +538,7 @@ declare module 'sqlops' { } export interface TreeComponent extends Component, TreeProperties { - registerDataProvider(dataProvider: TreeComponentDataProvider): any; + registerDataProvider(dataProvider: TreeComponentDataProvider): TreeComponentView; } export interface WebViewComponent extends Component { diff --git a/src/sql/workbench/api/node/extHostModelView.ts b/src/sql/workbench/api/node/extHostModelView.ts index f082211bf3..5a61ab7520 100644 --- a/src/sql/workbench/api/node/extHostModelView.ts +++ b/src/sql/workbench/api/node/extHostModelView.ts @@ -1063,7 +1063,7 @@ class TreeComponentWrapper extends ComponentWrapper implements sqlops.TreeCom this.properties = {}; } - public registerDataProvider(dataProvider: sqlops.TreeComponentDataProvider): vscode.TreeView { + public registerDataProvider(dataProvider: sqlops.TreeComponentDataProvider): sqlops.TreeComponentView { this.setDataProvider(); return this._extHostModelViewTree.$createTreeView(this._handle, this.id, { treeDataProvider: dataProvider }); } diff --git a/src/sql/workbench/api/node/extHostModelViewTree.ts b/src/sql/workbench/api/node/extHostModelViewTree.ts index f1820f2be1..e62db04b5a 100644 --- a/src/sql/workbench/api/node/extHostModelViewTree.ts +++ b/src/sql/workbench/api/node/extHostModelViewTree.ts @@ -14,33 +14,32 @@ import { asWinJsPromise } from 'vs/base/common/async'; import { IMainContext } from 'vs/workbench/api/node/extHost.protocol'; import * as sqlops from 'sqlops'; import * as vsTreeExt from 'vs/workbench/api/node/extHostTreeViews'; +import { Emitter } from 'vs/base/common/event'; export class ExtHostModelViewTreeViews implements ExtHostModelViewTreeViewsShape { private _proxy: MainThreadModelViewShape; private treeViews: Map> = new Map>(); - constructor( private _mainContext: IMainContext ) { this._proxy = this._mainContext.getProxy(SqlMainContext.MainThreadModelView); } - $createTreeView(handle: number, componentId: string, options: { treeDataProvider: sqlops.TreeComponentDataProvider }): vscode.TreeView { + $createTreeView(handle: number, componentId: string, options: { treeDataProvider: sqlops.TreeComponentDataProvider }): sqlops.TreeComponentView { if (!options || !options.treeDataProvider) { throw new Error('Options with treeDataProvider is mandatory'); } const treeView = this.createExtHostTreeViewer(handle, componentId, options.treeDataProvider); return { - reveal: (element: T, options?: { select?: boolean }): Thenable => { - return treeView.reveal(element, options); - }, dispose: () => { this.treeViews.delete(componentId); treeView.dispose(); - } + }, + onNodeCheckedChanged: treeView.NodeCheckedChanged, + onDidChangeSelection: treeView.ChangeSelection }; } @@ -60,6 +59,13 @@ export class ExtHostModelViewTreeViews implements ExtHostModelViewTreeViewsShape } } + $onNodeSelected(treeViewId: string, handles: string[]): void { + const treeView = this.treeViews.get(treeViewId); + if (treeView) { + treeView.onNodeSelectedChanged(handles); + } + } + private createExtHostTreeViewer(handle: number, id: string, dataProvider: sqlops.TreeComponentDataProvider): ExtHostTreeView { const treeView = new ExtHostTreeView(handle, id, dataProvider, this._proxy, undefined); this.treeViews.set(`${handle}-${id}`, treeView); @@ -69,6 +75,10 @@ export class ExtHostModelViewTreeViews implements ExtHostModelViewTreeViewsShape export class ExtHostTreeView extends vsTreeExt.ExtHostTreeView { + private _onNodeCheckedChanged = new Emitter>(); + private _onDidChangeSelection = new Emitter(); + public readonly NodeCheckedChanged: vscode.Event> = this._onNodeCheckedChanged.event; + public readonly ChangeSelection: vscode.Event = this._onDidChangeSelection.event; constructor(private handle: number, private componentId: string, private componentDataProvider: sqlops.TreeComponentDataProvider, private modelViewProxy: MainThreadModelViewShape, commands: CommandsConverter) { super(componentId, componentDataProvider, undefined, commands); } @@ -79,7 +89,16 @@ export class ExtHostTreeView extends vsTreeExt.ExtHostTreeView { console.error(`No tree item with id \'${parentHandle}\' found.`); } - this.componentDataProvider.onNodeCheckedChanged(parentElement, checked); + this._onNodeCheckedChanged.fire({element: parentElement, checked: checked}); + } + + onNodeSelectedChanged(parentHandles?: vsTreeExt.TreeItemHandle[]): void { + if (parentHandles) { + let nodes = parentHandles.map(parentHandle => { + return parentHandle ? this.getExtensionElement(parentHandle) : void 0; + }); + this._onDidChangeSelection.fire(nodes); + } } reveal(element: T, options?: { select?: boolean }): TPromise { diff --git a/src/sql/workbench/api/node/sqlExtHost.protocol.ts b/src/sql/workbench/api/node/sqlExtHost.protocol.ts index 09f9c8113e..2e1e9855b8 100644 --- a/src/sql/workbench/api/node/sqlExtHost.protocol.ts +++ b/src/sql/workbench/api/node/sqlExtHost.protocol.ts @@ -604,8 +604,9 @@ export interface ExtHostModelViewShape { export interface ExtHostModelViewTreeViewsShape { $getChildren(treeViewId: string, treeItemHandle?: string): TPromise; - $createTreeView(handle: number, componentId: string, options: { treeDataProvider: vscode.TreeDataProvider }): vscode.TreeView; + $createTreeView(handle: number, componentId: string, options: { treeDataProvider: vscode.TreeDataProvider }): sqlops.TreeComponentView; $onNodeCheckedChanged(treeViewId: string, treeItemHandle?: string, checked?: boolean): void; + $onNodeSelected(treeViewId: string, nodes: string[]): void; } export interface ExtHostBackgroundTaskManagementShape { diff --git a/src/vs/workbench/api/electron-browser/mainThreadTreeViews.ts b/src/vs/workbench/api/electron-browser/mainThreadTreeViews.ts index a2bd828a12..3d4f048ebf 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadTreeViews.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadTreeViews.ts @@ -125,8 +125,7 @@ export class TreeViewDataProvider implements ITreeViewDataProvider { } } - // {{SQL CARBON EDIT}} - protected postGetChildren(elements: ITreeItem[]): ITreeItem[] { + private postGetChildren(elements: ITreeItem[]): ITreeItem[] { const result = []; if (elements) { for (const element of elements) {