diff --git a/package.json b/package.json index cda07ae51e..b099a9be6c 100644 --- a/package.json +++ b/package.json @@ -103,7 +103,7 @@ "rxjs": "5.4.0", "sanitize-html": "1.19.1", "semver-umd": "^5.5.7", - "slickgrid": "github:Microsoft/SlickGrid.ADS#2.3.42", + "slickgrid": "github:Microsoft/SlickGrid.ADS#2.3.43", "spdlog": "^0.13.0", "tas-client-umd": "0.1.4", "turndown": "^7.0.0", diff --git a/remote/package.json b/remote/package.json index b61f40c60a..5c75e805c5 100755 --- a/remote/package.json +++ b/remote/package.json @@ -43,7 +43,7 @@ "sanitize-html": "1.19.1", "semver-umd": "^5.5.7", "spdlog": "^0.13.0", - "slickgrid": "github:Microsoft/SlickGrid.ADS#2.3.42", + "slickgrid": "github:Microsoft/SlickGrid.ADS#2.3.43", "turndown": "^7.0.0", "turndown-plugin-gfm": "^1.0.2", "tas-client-umd": "0.1.4", diff --git a/remote/web/package.json b/remote/web/package.json index 91475eb4b9..e63da3f37f 100755 --- a/remote/web/package.json +++ b/remote/web/package.json @@ -31,7 +31,7 @@ "rxjs": "5.4.0", "sanitize-html": "1.19.1", "semver-umd": "^5.5.7", - "slickgrid": "github:Microsoft/SlickGrid.ADS#2.3.42", + "slickgrid": "github:Microsoft/SlickGrid.ADS#2.3.43", "turndown": "^7.0.0", "turndown-plugin-gfm": "^1.0.2", "tas-client-umd": "0.1.4", diff --git a/remote/web/yarn.lock b/remote/web/yarn.lock index c875f9a5c7..ce1a2f713b 100644 --- a/remote/web/yarn.lock +++ b/remote/web/yarn.lock @@ -437,9 +437,9 @@ semver-umd@^5.5.7: resolved "https://registry.yarnpkg.com/semver-umd/-/semver-umd-5.5.7.tgz#966beb5e96c7da6fbf09c3da14c2872d6836c528" integrity sha512-XgjPNlD0J6aIc8xoTN6GQGwWc2Xg0kq8NzrqMVuKG/4Arl6ab1F8+Am5Y/XKKCR+FceFr2yN/Uv5ZJBhRyRqKg== -"slickgrid@github:Microsoft/SlickGrid.ADS#2.3.42": - version "2.3.42" - resolved "https://codeload.github.com/Microsoft/SlickGrid.ADS/tar.gz/29021c4410512d0d644a3b8eb5115bc84ed277e9" +"slickgrid@github:Microsoft/SlickGrid.ADS#2.3.43": + version "2.3.43" + resolved "https://codeload.github.com/Microsoft/SlickGrid.ADS/tar.gz/877ada4c52320a851bb9f7b54eed10831423c144" source-map@^0.6.1: version "0.6.1" diff --git a/remote/yarn.lock b/remote/yarn.lock index adf32bcb77..314ec16f45 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -854,9 +854,9 @@ simple-get@^4.0.0: once "^1.3.1" simple-concat "^1.0.0" -"slickgrid@github:Microsoft/SlickGrid.ADS#2.3.42": - version "2.3.42" - resolved "https://codeload.github.com/Microsoft/SlickGrid.ADS/tar.gz/29021c4410512d0d644a3b8eb5115bc84ed277e9" +"slickgrid@github:Microsoft/SlickGrid.ADS#2.3.43": + version "2.3.43" + resolved "https://codeload.github.com/Microsoft/SlickGrid.ADS/tar.gz/877ada4c52320a851bb9f7b54eed10831423c144" smart-buffer@^4.2.0: version "4.2.0" diff --git a/src/sql/base/browser/ui/table/plugins/headerFilter.plugin.ts b/src/sql/base/browser/ui/table/plugins/headerFilter.plugin.ts index d576c0379d..2aaf372263 100644 --- a/src/sql/base/browser/ui/table/plugins/headerFilter.plugin.ts +++ b/src/sql/base/browser/ui/table/plugins/headerFilter.plugin.ts @@ -93,8 +93,7 @@ export class HeaderFilter { this.handler.subscribe(this.grid.onHeaderCellRendered, (e: Event, args: Slick.OnHeaderCellRenderedEventArgs) => this.handleHeaderCellRendered(e, args)) .subscribe(this.grid.onBeforeHeaderCellDestroy, (e: Event, args: Slick.OnBeforeHeaderCellDestroyEventArgs) => this.handleBeforeHeaderCellDestroy(e, args)) .subscribe(this.grid.onClick, (e: DOMEvent) => this.handleBodyMouseDown(e as MouseEvent)) - .subscribe(this.grid.onColumnsResized, () => this.columnsResized()) - .subscribe(this.grid.onKeyDown, async (e: DOMEvent) => { await this.handleGridKeyDown(e as KeyboardEvent); }); + .subscribe(this.grid.onColumnsResized, () => this.columnsResized()); if (this.options.refreshColumns !== false) { this.grid.setColumns(this.grid.getColumns()); @@ -109,6 +108,16 @@ export class HeaderFilter { this.disposableStore.dispose(); } + public async showMenu(): Promise { + const cell = this.grid.getActiveCell(); + if (cell) { + const column = this.grid.getColumns()[cell.cell] as FilterableColumn; + if (column.filterable !== false && this.columnButtonMapping[column.id]) { + await this.showFilter(this.columnButtonMapping[column.id]); + } + } + } + private handleKeyDown(e: KeyboardEvent): void { const event = new StandardKeyboardEvent(e); if (this.menu && event.keyCode === KeyCode.Escape) { @@ -120,23 +129,6 @@ export class HeaderFilter { } } - private async handleGridKeyDown(e: KeyboardEvent): Promise { - const event = new StandardKeyboardEvent(e); - // The shortcut key to open the filter menu is provided so that this feature is keyboard accessible. - // The buttons added to the column headers are set to not keyboard focusable so that they won't interfere with the slickgrid's internal focus management. - // F3 key is chosen because it is known for search related features - if (event.keyCode === KeyCode.F3) { - const cell = this.grid.getActiveCell(); - if (cell) { - const column = this.grid.getColumns()[cell.cell] as FilterableColumn; - if (column.filterable !== false && this.columnButtonMapping[column.id]) { - await this.showFilter(this.columnButtonMapping[column.id]); - EventHelper.stop(e, true); - } - } - } - } - private handleBodyMouseDown(e: MouseEvent): void { if (this.menu && this.menu !== e.target && !isAncestor(e.target as Element, this.menu)) { this.hideMenu(); diff --git a/src/sql/base/browser/ui/table/table.ts b/src/sql/base/browser/ui/table/table.ts index b7bfcdf2ce..75ec8a8a6a 100644 --- a/src/sql/base/browser/ui/table/table.ts +++ b/src/sql/base/browser/ui/table/table.ts @@ -20,8 +20,6 @@ import { Event, Emitter } from 'vs/base/common/event'; import { range } from 'vs/base/common/arrays'; import { AsyncDataProvider } from 'sql/base/browser/ui/table/asyncDataView'; import { IDisposableDataProvider } from 'sql/base/common/dataProvider'; -import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; -import { KeyCode } from 'vs/base/common/keyCodes'; import { IAccessibilityProvider } from 'sql/base/browser/ui/accessibility/accessibilityProvider'; import { IQuickInputProvider } from 'sql/base/browser/ui/quickInput/quickInputProvider'; import { localize } from 'vs/nls'; @@ -143,28 +141,9 @@ export class Table extends Widget implements IDisposa this.mapMouseEvent(this._grid.onHeaderClick, this._onHeaderClick); this.mapMouseEvent(this._grid.onDblClick, this._onDoubleClick); this._grid.onColumnsResized.subscribe(() => this._onColumnResize.fire()); - - this._grid.onKeyDown.subscribe(async (e, args: Slick.OnKeyDownEventArgs) => { - const evt = (e as JQuery.TriggeredEvent).originalEvent as KeyboardEvent; - const stdEvt = new StandardKeyboardEvent(evt); - if (stdEvt.altKey && stdEvt.shiftKey && stdEvt.keyCode === KeyCode.KeyS) { - const newWidth = this.resizeActiveCellColumnByQuickInput(); - if (newWidth) { - stdEvt.stopPropagation(); - stdEvt.preventDefault(); - } - } - this._onKeyDown.fire({ - event: evt, - cell: { - row: args.row, - cell: args.cell - } - }); - }); } - private async resizeActiveCellColumnByQuickInput(): Promise { + public async resizeActiveColumn(): Promise { const activeCell = this._grid.getActiveCell(); if (activeCell) { const columns = this._grid.getColumns(); @@ -187,7 +166,6 @@ export class Table extends Widget implements IDisposa this._grid.setColumns(columns); this.grid.setActiveCell(activeCell.row, activeCell.cell); } - return parseInt(newColumnWidth); } } return undefined; diff --git a/src/sql/workbench/browser/designer/designer.ts b/src/sql/workbench/browser/designer/designer.ts index 4718c5ed79..ffea8f052d 100644 --- a/src/sql/workbench/browser/designer/designer.ts +++ b/src/sql/workbench/browser/designer/designer.ts @@ -55,6 +55,7 @@ import { timeout } from 'vs/base/common/async'; import { onUnexpectedError } from 'vs/base/common/errors'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; +import { ITableService } from 'sql/workbench/services/table/browser/tableService'; export interface IDesignerStyle { tabbedPanelStyles?: ITabbedPanelStyles; @@ -117,7 +118,8 @@ export class Designer extends Disposable implements IThemable { @IThemeService private readonly _themeService: IThemeService, @IContextMenuService private readonly _contextMenuService: IContextMenuService, @IAccessibilityService private readonly _accessibilityService: IAccessibilityService, - @IQuickInputService private readonly _quickInputService: IQuickInputService) { + @IQuickInputService private readonly _quickInputService: IQuickInputService, + @ITableService private readonly _tableService: ITableService) { super(); this._tableCellEditorFactory = new TableCellEditorFactory( { @@ -1026,6 +1028,7 @@ export class Designer extends Disposable implements IThemable { currentTableActions.forEach(a => a.updateState()); table.grid.setSelectedRows([]); }); + this._register(this._tableService.registerTable(table)); component = table; break; default: diff --git a/src/sql/workbench/browser/modelComponents/table.component.ts b/src/sql/workbench/browser/modelComponents/table.component.ts index 4695456f7f..2f6f7f818d 100644 --- a/src/sql/workbench/browser/modelComponents/table.component.ts +++ b/src/sql/workbench/browser/modelComponents/table.component.ts @@ -39,6 +39,7 @@ import { MenuItemAction, MenuRegistry } from 'vs/platform/actions/common/actions import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; +import { ITableService } from 'sql/workbench/services/table/browser/tableService'; export enum ColumnSizingMode { ForceFit = 0, // all columns will be sized to fit in viewable space, no horiz scroll bar @@ -92,7 +93,8 @@ export default class TableComponent extends ComponentBasethis.rowDetail); this._table.registerPlugin(filterPlugin); - + this._register(this.tableService.registerTable(this._table)); this.placeholderElem = document.createElement('span'); this.placeholderElem.className = 'placeholder'; diff --git a/src/sql/workbench/contrib/charts/browser/tableInsight.ts b/src/sql/workbench/contrib/charts/browser/tableInsight.ts index 7c417e951f..3f8adbf06c 100644 --- a/src/sql/workbench/contrib/charts/browser/tableInsight.ts +++ b/src/sql/workbench/contrib/charts/browser/tableInsight.ts @@ -16,6 +16,7 @@ import { IInsightOptions, InsightType } from 'sql/workbench/contrib/charts/commo import { IInsightData } from 'sql/platform/dashboard/browser/insightRegistry'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; +import { ITableService } from 'sql/workbench/services/table/browser/tableService'; export class TableInsight extends Disposable implements IInsight { public static readonly types = [InsightType.Table]; @@ -29,7 +30,8 @@ export class TableInsight extends Disposable implements IInsight { constructor(container: HTMLElement, options: any, @IThemeService themeService: IThemeService, @IAccessibilityService accessibilityService: IAccessibilityService, - @IQuickInputService quickInputService: IQuickInputService + @IQuickInputService quickInputService: IQuickInputService, + @ITableService private tableService: ITableService ) { super(); let tableContainer = $('div'); @@ -40,6 +42,7 @@ export class TableInsight extends Disposable implements IInsight { this.table = new Table(tableContainer, accessibilityService, quickInputService, { dataProvider: this.dataView }, { showRowNumber: true }); this.table.setSelectionModel(new CellSelectionModel()); this._register(attachTableStyler(this.table, themeService)); + this._register(this.tableService.registerTable(this.table)); } set data(data: IInsightData) { diff --git a/src/sql/workbench/contrib/dashboard/browser/widgets/explorer/explorerTable.ts b/src/sql/workbench/contrib/dashboard/browser/widgets/explorer/explorerTable.ts index c885665d07..3e985fb3fb 100644 --- a/src/sql/workbench/contrib/dashboard/browser/widgets/explorer/explorerTable.ts +++ b/src/sql/workbench/contrib/dashboard/browser/widgets/explorer/explorerTable.ts @@ -20,6 +20,7 @@ import { ExplorerFilter } from 'sql/workbench/contrib/dashboard/browser/widgets/ import { ExplorerView, NameProperty } from 'sql/workbench/contrib/dashboard/browser/widgets/explorer/explorerView'; import { ObjectMetadataWrapper } from 'sql/workbench/contrib/dashboard/browser/widgets/explorer/objectMetadataWrapper'; import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service'; +import { ITableService } from 'sql/workbench/services/table/browser/tableService'; import * as DOM from 'vs/base/browser/dom'; import { status } from 'vs/base/browser/ui/aria/aria'; import { IAction } from 'vs/base/common/actions'; @@ -67,7 +68,8 @@ export class ExplorerTable extends Disposable { private readonly logService: ILogService, private readonly dashboardService: IDashboardService, readonly accessibilityService: IAccessibilityService, - readonly quickInputService: IQuickInputService) { + readonly quickInputService: IQuickInputService, + private readonly tableService: ITableService) { super(); this._explorerView = new ExplorerView(this.context); const connectionInfo = this.bootStrapService.connectionManagementService.connectionInfo; @@ -113,6 +115,7 @@ export class ExplorerTable extends Disposable { this._table.grid.invalidateAllRows(); this._table.updateRowCount(); })); + this._register(this.tableService.registerTable(this._table)); } private showContextMenu(item: Slick.SlickData, anchor: HTMLElement | { x: number, y: number }): void { diff --git a/src/sql/workbench/contrib/dashboard/browser/widgets/explorer/explorerWidget.component.ts b/src/sql/workbench/contrib/dashboard/browser/widgets/explorer/explorerWidget.component.ts index 7645cafc3d..58a1f4df51 100644 --- a/src/sql/workbench/contrib/dashboard/browser/widgets/explorer/explorerWidget.component.ts +++ b/src/sql/workbench/contrib/dashboard/browser/widgets/explorer/explorerWidget.component.ts @@ -33,6 +33,7 @@ import { getFlavor } from 'sql/workbench/contrib/dashboard/browser/dashboardRegi import { IDashboardService } from 'sql/platform/dashboard/browser/dashboardService'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; +import { ITableService } from 'sql/workbench/services/table/browser/tableService'; @Component({ selector: 'explorer-widget', @@ -64,6 +65,7 @@ export class ExplorerWidget extends DashboardWidget implements IDashboardWidget, @Inject(IDashboardService) private readonly dashboardService: IDashboardService, @Inject(IAccessibilityService) private readonly accessibilityService: IAccessibilityService, @Inject(IQuickInputService) private readonly quickInputService: IQuickInputService, + @Inject(ITableService) private readonly tableService: ITableService, @Inject(forwardRef(() => ChangeDetectorRef)) changeRef: ChangeDetectorRef ) { super(changeRef); @@ -98,7 +100,8 @@ export class ExplorerWidget extends DashboardWidget implements IDashboardWidget, this.logService, this.dashboardService, this.accessibilityService, - this.quickInputService); + this.quickInputService, + this.tableService); this._register(this._input); this._register(attachInputBoxStyler(this._input, this.themeService)); this._register(this._table); diff --git a/src/sql/workbench/contrib/dashboard/browser/widgets/insights/views/tableInsight.component.ts b/src/sql/workbench/contrib/dashboard/browser/widgets/insights/views/tableInsight.component.ts index d5a12bf65c..e360723bda 100644 --- a/src/sql/workbench/contrib/dashboard/browser/widgets/insights/views/tableInsight.component.ts +++ b/src/sql/workbench/contrib/dashboard/browser/widgets/insights/views/tableInsight.component.ts @@ -16,6 +16,7 @@ import { CellSelectionModel } from 'sql/base/browser/ui/table/plugins/cellSelect import { IInsightsView, IInsightData } from 'sql/platform/dashboard/browser/insightRegistry'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; +import { ITableService } from 'sql/workbench/services/table/browser/tableService'; @Component({ template: '' @@ -29,7 +30,8 @@ export default class TableInsight extends Disposable implements IInsightsView, O @Inject(forwardRef(() => ElementRef)) private _elementRef: ElementRef, @Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService, @Inject(IAccessibilityService) private accessibilityService: IAccessibilityService, - @Inject(IQuickInputService) private quickInputService: IQuickInputService + @Inject(IQuickInputService) private quickInputService: IQuickInputService, + @Inject(ITableService) private tableService: ITableService ) { super(); } @@ -68,6 +70,7 @@ export default class TableInsight extends Disposable implements IInsightsView, O this.table = new Table(this._elementRef.nativeElement, this.accessibilityService, this.quickInputService, { dataProvider: this.dataView, columns: this.columns }, { showRowNumber: true }); this.table.setSelectionModel(new CellSelectionModel()); this._register(attachTableStyler(this.table, this.themeService)); + this._register(this.tableService.registerTable(this.table)); } } } diff --git a/src/sql/workbench/contrib/executionPlan/browser/executionPlanComparisonPropertiesView.ts b/src/sql/workbench/contrib/executionPlan/browser/executionPlanComparisonPropertiesView.ts index c045f6c39c..4feb6591ae 100644 --- a/src/sql/workbench/contrib/executionPlan/browser/executionPlanComparisonPropertiesView.ts +++ b/src/sql/workbench/contrib/executionPlan/browser/executionPlanComparisonPropertiesView.ts @@ -20,6 +20,7 @@ import { Codicon } from 'vs/base/common/codicons'; import { deepClone } from 'vs/base/common/objects'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; +import { ITableService } from 'sql/workbench/services/table/browser/tableService'; export enum ExecutionPlanCompareOrientation { Horizontal = 'horizontal', @@ -66,9 +67,10 @@ export class ExecutionPlanComparisonPropertiesView extends ExecutionPlanProperti @IContextMenuService contextMenuService: IContextMenuService, @IContextViewService contextViewService: IContextViewService, @IAccessibilityService accessibilityService: IAccessibilityService, - @IQuickInputService quickInputService: IQuickInputService + @IQuickInputService quickInputService: IQuickInputService, + @ITableService tableService: ITableService ) { - super(parentContainer, themeService, instantiationService, contextMenuService, contextViewService, accessibilityService, quickInputService); + super(parentContainer, themeService, instantiationService, contextMenuService, contextViewService, accessibilityService, quickInputService, tableService); this._model = {}; this._parentContainer.style.display = 'none'; const header = DOM.$('.compare-operation-name'); diff --git a/src/sql/workbench/contrib/executionPlan/browser/executionPlanPropertiesView.ts b/src/sql/workbench/contrib/executionPlan/browser/executionPlanPropertiesView.ts index 715baf1e36..55f0515b7f 100644 --- a/src/sql/workbench/contrib/executionPlan/browser/executionPlanPropertiesView.ts +++ b/src/sql/workbench/contrib/executionPlan/browser/executionPlanPropertiesView.ts @@ -15,6 +15,7 @@ import { IContextMenuService, IContextViewService } from 'vs/platform/contextvie import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; +import { ITableService } from 'sql/workbench/services/table/browser/tableService'; export class ExecutionPlanPropertiesView extends ExecutionPlanPropertiesViewBase { // Div that holds the name of the element selected @@ -28,9 +29,10 @@ export class ExecutionPlanPropertiesView extends ExecutionPlanPropertiesViewBase @IContextMenuService contextMenuService: IContextMenuService, @IContextViewService contextViewService: IContextViewService, @IAccessibilityService accessibilityService: IAccessibilityService, - @IQuickInputService quickInputService: IQuickInputService + @IQuickInputService quickInputService: IQuickInputService, + @ITableService tableService: ITableService ) { - super(parentContainer, themeService, instantiationService, contextMenuService, contextViewService, accessibilityService, quickInputService); + super(parentContainer, themeService, instantiationService, contextMenuService, contextViewService, accessibilityService, quickInputService, tableService); this._model = {}; this._operationName = DOM.$('h3'); this._operationName.classList.add('operation-name'); diff --git a/src/sql/workbench/contrib/executionPlan/browser/executionPlanPropertiesViewBase.ts b/src/sql/workbench/contrib/executionPlan/browser/executionPlanPropertiesViewBase.ts index 2261381d3c..c930358bdd 100644 --- a/src/sql/workbench/contrib/executionPlan/browser/executionPlanPropertiesViewBase.ts +++ b/src/sql/workbench/contrib/executionPlan/browser/executionPlanPropertiesViewBase.ts @@ -27,6 +27,7 @@ import { deepClone } from 'vs/base/common/objects'; import { Disposable } from 'vs/base/common/lifecycle'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; +import { ITableService } from 'sql/workbench/services/table/browser/tableService'; export abstract class ExecutionPlanPropertiesViewBase extends Disposable implements IVerticalSashLayoutProvider { // Title bar with close button action @@ -71,7 +72,8 @@ export abstract class ExecutionPlanPropertiesViewBase extends Disposable impleme @IContextMenuService private _contextMenuService: IContextMenuService, @IContextViewService private _contextViewService: IContextViewService, @IAccessibilityService accessibilityService: IAccessibilityService, - @IQuickInputService quickInputService: IQuickInputService + @IQuickInputService quickInputService: IQuickInputService, + @ITableService private _tableService: ITableService ) { super(); const sashContainer = DOM.$('.properties-sash'); @@ -190,6 +192,8 @@ export abstract class ExecutionPlanPropertiesViewBase extends Disposable impleme this._register(copyHandler.onCopy(e => { this._instantiationService.createInstance(CopyTableData).run(this.getCopyString()); })); + this._register(this._tableService.registerTable(this._tableComponent)); + new ResizeObserver((e) => { this.resizeSash.layout(); diff --git a/src/sql/workbench/contrib/executionPlan/browser/executionPlanTreeTab.ts b/src/sql/workbench/contrib/executionPlan/browser/executionPlanTreeTab.ts index 850050ff87..ed102dd5f2 100644 --- a/src/sql/workbench/contrib/executionPlan/browser/executionPlanTreeTab.ts +++ b/src/sql/workbench/contrib/executionPlan/browser/executionPlanTreeTab.ts @@ -26,6 +26,7 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { deepClone } from 'vs/base/common/objects'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; +import { ITableService } from 'sql/workbench/services/table/browser/tableService'; export class ExecutionPlanTreeTab extends Disposable implements IPanelTab { public readonly title: string = localize('planTreeTab.title', 'Plan Tree'); @@ -55,7 +56,8 @@ export class ExecutionPlanTreeTabView extends Disposable implements IPanelView { @IInstantiationService private _instantiationService: IInstantiationService, @IContextMenuService private _contextMenuService: IContextMenuService, @IAccessibilityService private _accessibilityService: IAccessibilityService, - @IQuickInputService private _quickInputService: IQuickInputService + @IQuickInputService private _quickInputService: IQuickInputService, + @ITableService private _tableService: ITableService ) { super(); } @@ -278,6 +280,7 @@ export class ExecutionPlanTreeTabView extends Disposable implements IPanelView { treeGrid.registerPlugin(copyHandler); treeGrid.setTableTitle(localize('topOperationsTableTitle', "Execution Plan Tree")); this._treeGrids.push(treeGrid); + this._register(this._tableService.registerTable(treeGrid)); const contextMenuAction = [ this._register(this._instantiationService.createInstance(CopyTableData)), diff --git a/src/sql/workbench/contrib/executionPlan/browser/topOperationsTab.ts b/src/sql/workbench/contrib/executionPlan/browser/topOperationsTab.ts index 4f9f2bd4e9..6f902cea14 100644 --- a/src/sql/workbench/contrib/executionPlan/browser/topOperationsTab.ts +++ b/src/sql/workbench/contrib/executionPlan/browser/topOperationsTab.ts @@ -32,6 +32,7 @@ import { InputBox } from 'sql/base/browser/ui/inputBox/inputBox'; import { filterIconClassNames, searchPlaceholder, topOperationsSearchDescription } from 'sql/workbench/contrib/executionPlan/browser/constants'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; +import { ITableService } from 'sql/workbench/services/table/browser/tableService'; const TABLE_SORT_COLUMN_KEY = 'tableCostColumnForSorting'; @@ -66,6 +67,7 @@ export class TopOperationsTabView extends Disposable implements IPanelView { @IContextViewService private _contextViewService: IContextViewService, @IAccessibilityService private _accessibilityService: IAccessibilityService, @IQuickInputService private _quickInputService: IQuickInputService, + @ITableService private _tableService: ITableService ) { super(); } @@ -408,6 +410,8 @@ export class TopOperationsTabView extends Disposable implements IPanelView { table.layout(new DOM.Dimension(tableContainer.clientWidth, tableContainer.clientHeight)); }).observe(tableContainer); + this._register(this._tableService.registerTable(table)); + return table; } diff --git a/src/sql/workbench/contrib/jobManagement/browser/alertsView.component.ts b/src/sql/workbench/contrib/jobManagement/browser/alertsView.component.ts index ec7d168683..293be6e3b7 100644 --- a/src/sql/workbench/contrib/jobManagement/browser/alertsView.component.ts +++ b/src/sql/workbench/contrib/jobManagement/browser/alertsView.component.ts @@ -26,6 +26,7 @@ import { AlertsCacheObject } from 'sql/workbench/services/jobManagement/common/j import { RowDetailView } from 'sql/base/browser/ui/table/plugins/rowDetailView'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; +import { ITableService } from 'sql/workbench/services/table/browser/tableService'; export const VIEW_SELECTOR: string = 'jobalertsview-component'; export const ROW_HEIGHT: number = 45; @@ -80,7 +81,8 @@ export class AlertsViewComponent extends JobManagementView implements OnInit, On @Inject(IKeybindingService) keybindingService: IKeybindingService, @Inject(IDashboardService) _dashboardService: IDashboardService, @Inject(IAccessibilityService) private _accessibilityService: IAccessibilityService, - @Inject(IQuickInputService) private _quickInputService: IQuickInputService) { + @Inject(IQuickInputService) private _quickInputService: IQuickInputService, + @Inject(ITableService) private _tableService: ITableService) { super(commonService, _dashboardService, contextMenuService, keybindingService, instantiationService, _agentViewComponent); this._didTabChange = false; this._isCloud = commonService.connectionManagementService.connectionInfo.serverInfo.isCloud; @@ -148,6 +150,7 @@ export class AlertsViewComponent extends JobManagementView implements OnInit, On this.initActionBar(); this._table = new Table(this._gridEl.nativeElement, this._accessibilityService, this._quickInputService, { columns }, this.options); + this._register(this._tableService.registerTable(this._table)); this._table.grid.setData(this.dataView, true); this._register(this._table.onContextMenu(e => { self.openContextMenu(e); diff --git a/src/sql/workbench/contrib/jobManagement/browser/jobsView.component.ts b/src/sql/workbench/contrib/jobManagement/browser/jobsView.component.ts index 31b6c7aaed..a1819a88a3 100644 --- a/src/sql/workbench/contrib/jobManagement/browser/jobsView.component.ts +++ b/src/sql/workbench/contrib/jobManagement/browser/jobsView.component.ts @@ -36,6 +36,7 @@ import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry'; import { attachTableFilterStyler } from 'sql/platform/theme/common/styler'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; +import { ITableService } from 'sql/workbench/services/table/browser/tableService'; export const JOBSVIEW_SELECTOR: string = 'jobsview-component'; export const ROW_HEIGHT: number = 45; @@ -112,7 +113,8 @@ export class JobsViewComponent extends JobManagementView implements OnInit, OnDe @Inject(IAdsTelemetryService) private _telemetryService: IAdsTelemetryService, @Inject(IContextViewService) private _contextViewService: IContextViewService, @Inject(IAccessibilityService) private _accessibilityService: IAccessibilityService, - @Inject(IQuickInputService) private _quickInputService: IQuickInputService + @Inject(IQuickInputService) private _quickInputService: IQuickInputService, + @Inject(ITableService) private _tableService: ITableService ) { super(commonService, _dashboardService, contextMenuService, keybindingService, instantiationService, _agentViewComponent); let jobCacheObjectMap = this._jobManagementService.jobCacheObjectMap; @@ -200,6 +202,7 @@ export class JobsViewComponent extends JobManagementView implements OnInit, OnDe self._agentViewComponent.agentJobInfo = job; self._agentViewComponent.showHistory = true; }); + this._register(this._tableService.registerTable(this._table)); this._register(this._table.onContextMenu(e => { self.openContextMenu(e); })); diff --git a/src/sql/workbench/contrib/jobManagement/browser/notebooksView.component.ts b/src/sql/workbench/contrib/jobManagement/browser/notebooksView.component.ts index d13c2ce786..4ae6d15252 100644 --- a/src/sql/workbench/contrib/jobManagement/browser/notebooksView.component.ts +++ b/src/sql/workbench/contrib/jobManagement/browser/notebooksView.component.ts @@ -37,6 +37,7 @@ import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry'; import { attachTableFilterStyler } from 'sql/platform/theme/common/styler'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; +import { ITableService } from 'sql/workbench/services/table/browser/tableService'; export const NOTEBOOKSVIEW_SELECTOR: string = 'notebooksview-component'; @@ -111,7 +112,8 @@ export class NotebooksViewComponent extends JobManagementView implements OnInit, @Inject(IAdsTelemetryService) private _telemetryService: IAdsTelemetryService, @Inject(IContextViewService) private _contextViewService: IContextViewService, @Inject(IAccessibilityService) private _accessibilityService: IAccessibilityService, - @Inject(IQuickInputService) private _quickInputService: IQuickInputService + @Inject(IQuickInputService) private _quickInputService: IQuickInputService, + @Inject(ITableService) private _tableService: ITableService ) { super(commonService, _dashboardService, contextMenuService, keybindingService, instantiationService, _agentViewComponent); let notebookCacheObjectMap = this._jobManagementService.notebookCacheObjectMap; @@ -199,6 +201,7 @@ export class NotebooksViewComponent extends JobManagementView implements OnInit, self._agentViewComponent.agentNotebookInfo = notebook; self._agentViewComponent.showNotebookHistory = true; }); + this._register(this._tableService.registerTable(this._table)); this._register(this._table.onContextMenu(e => { self.openContextMenu(e); })); diff --git a/src/sql/workbench/contrib/jobManagement/browser/operatorsView.component.ts b/src/sql/workbench/contrib/jobManagement/browser/operatorsView.component.ts index 2eaf9f54ea..693e4b6a26 100644 --- a/src/sql/workbench/contrib/jobManagement/browser/operatorsView.component.ts +++ b/src/sql/workbench/contrib/jobManagement/browser/operatorsView.component.ts @@ -26,6 +26,7 @@ import { OperatorsCacheObject } from 'sql/workbench/services/jobManagement/commo import { RowDetailView } from 'sql/base/browser/ui/table/plugins/rowDetailView'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; +import { ITableService } from 'sql/workbench/services/table/browser/tableService'; export const VIEW_SELECTOR: string = 'joboperatorsview-component'; export const ROW_HEIGHT: number = 45; @@ -79,7 +80,8 @@ export class OperatorsViewComponent extends JobManagementView implements OnInit, @Inject(IKeybindingService) keybindingService: IKeybindingService, @Inject(IDashboardService) _dashboardService: IDashboardService, @Inject(IAccessibilityService) private _accessibilityService: IAccessibilityService, - @Inject(IQuickInputService) private _quickInputService: IQuickInputService + @Inject(IQuickInputService) private _quickInputService: IQuickInputService, + @Inject(ITableService) private _tableService: ITableService ) { super(commonService, _dashboardService, contextMenuService, keybindingService, instantiationService, _agentViewComponent); this._isCloud = commonService.connectionManagementService.connectionInfo.serverInfo.isCloud; @@ -149,6 +151,7 @@ export class OperatorsViewComponent extends JobManagementView implements OnInit, this.initActionBar(); this._table = new Table(this._gridEl.nativeElement, this._accessibilityService, this._quickInputService, { columns }, this.options); this._table.grid.setData(this.dataView, true); + this._register(this._tableService.registerTable(this._table)); this._register(this._table.onContextMenu(e => { self.openContextMenu(e); diff --git a/src/sql/workbench/contrib/jobManagement/browser/proxiesView.component.ts b/src/sql/workbench/contrib/jobManagement/browser/proxiesView.component.ts index c22cd27ba8..a24a8e8821 100644 --- a/src/sql/workbench/contrib/jobManagement/browser/proxiesView.component.ts +++ b/src/sql/workbench/contrib/jobManagement/browser/proxiesView.component.ts @@ -26,6 +26,7 @@ import { ProxiesCacheObject } from 'sql/workbench/services/jobManagement/common/ import { RowDetailView } from 'sql/base/browser/ui/table/plugins/rowDetailView'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; +import { ITableService } from 'sql/workbench/services/table/browser/tableService'; export const VIEW_SELECTOR: string = 'jobproxiesview-component'; export const ROW_HEIGHT: number = 45; @@ -80,7 +81,8 @@ export class ProxiesViewComponent extends JobManagementView implements OnInit, O @Inject(IKeybindingService) keybindingService: IKeybindingService, @Inject(IDashboardService) _dashboardService: IDashboardService, @Inject(IAccessibilityService) private _accessibilityService: IAccessibilityService, - @Inject(IQuickInputService) private _quickInputService: IQuickInputService + @Inject(IQuickInputService) private _quickInputService: IQuickInputService, + @Inject(ITableService) private _tableService: ITableService ) { super(commonService, _dashboardService, contextMenuService, keybindingService, instantiationService, _agentViewComponent); this._isCloud = commonService.connectionManagementService.connectionInfo.serverInfo.isCloud; @@ -148,6 +150,7 @@ export class ProxiesViewComponent extends JobManagementView implements OnInit, O jQuery(this.actionBarContainer.nativeElement).empty(); this.initActionBar(); this._table = new Table(this._gridEl.nativeElement, this._accessibilityService, this._quickInputService, { columns }, this.options); + this._register(this._tableService.registerTable(this._table)); this._table.grid.setData(this.dataView, true); this._register(this._table.onContextMenu(e => { diff --git a/src/sql/workbench/contrib/notebook/browser/outputs/gridOutput.component.ts b/src/sql/workbench/contrib/notebook/browser/outputs/gridOutput.component.ts index 62fc08074f..aa96fcef43 100644 --- a/src/sql/workbench/contrib/notebook/browser/outputs/gridOutput.component.ts +++ b/src/sql/workbench/contrib/notebook/browser/outputs/gridOutput.component.ts @@ -51,6 +51,7 @@ import { ITextResourcePropertiesService } from 'vs/editor/common/services/textRe import { mssqlProviderName } from 'sql/platform/connection/common/constants'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; +import { ITableService } from 'sql/workbench/services/table/browser/tableService'; @Component({ selector: GridOutputComponent.SELECTOR, @@ -244,12 +245,13 @@ class DataResourceTable extends GridTableBase { @INotificationService notificationService: INotificationService, @IExecutionPlanService executionPlanService: IExecutionPlanService, @IAccessibilityService accessibilityService: IAccessibilityService, - @IQuickInputService quickInputService: IQuickInputService + @IQuickInputService quickInputService: IQuickInputService, + @ITableService tableService: ITableService ) { super(state, createResultSet(source), { actionOrientation: ActionsOrientation.HORIZONTAL, inMemoryDataProcessing: true - }, contextMenuService, instantiationService, editorService, untitledEditorService, configurationService, queryModelService, themeService, contextViewService, notificationService, executionPlanService, accessibilityService, quickInputService); + }, contextMenuService, instantiationService, editorService, untitledEditorService, configurationService, queryModelService, themeService, contextViewService, notificationService, executionPlanService, accessibilityService, quickInputService, tableService); this._gridDataProvider = this.instantiationService.createInstance(DataResourceDataProvider, source, this.resultSet, this.cellModel); this._chart = this.instantiationService.createInstance(ChartView, false); diff --git a/src/sql/workbench/contrib/profiler/browser/profilerEditor.ts b/src/sql/workbench/contrib/profiler/browser/profilerEditor.ts index 3c83453301..deafd18665 100644 --- a/src/sql/workbench/contrib/profiler/browser/profilerEditor.ts +++ b/src/sql/workbench/contrib/profiler/browser/profilerEditor.ts @@ -56,6 +56,7 @@ import { IModelService } from 'vs/editor/common/services/model'; import { CommonFindController, FindStartFocusAction } from 'vs/editor/contrib/find/browser/findController'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; +import { ITableService } from 'sql/workbench/services/table/browser/tableService'; class BasicView implements IView { public get element(): HTMLElement { @@ -175,7 +176,8 @@ export class ProfilerEditor extends EditorPane { @ITextResourcePropertiesService private readonly textResourcePropertiesService: ITextResourcePropertiesService, @IEditorGroupsService editorGroupsService: IEditorGroupsService, @IAccessibilityService private readonly _accessibilityService: IAccessibilityService, - @IQuickInputService private readonly _quickInputService: IQuickInputService + @IQuickInputService private readonly _quickInputService: IQuickInputService, + @ITableService private readonly _tableService: ITableService ) { super(ProfilerEditor.ID, telemetryService, themeService, storageService); this._profilerEditorContextKey = CONTEXT_PROFILER_EDITOR.bindTo(this._contextKeyService); @@ -429,6 +431,7 @@ export class ProfilerEditor extends EditorPane { }); this._detailTable.setSelectionModel(new CellSelectionModel()); this._detailTable.registerPlugin(detailTableCopyKeybind); + this._register(this._tableService.registerTable(this._detailTable)); this._tabbedPanel.pushTab({ diff --git a/src/sql/workbench/contrib/profiler/browser/profilerTableEditor.ts b/src/sql/workbench/contrib/profiler/browser/profilerTableEditor.ts index 4909737a72..f0c0a3f01d 100644 --- a/src/sql/workbench/contrib/profiler/browser/profilerTableEditor.ts +++ b/src/sql/workbench/contrib/profiler/browser/profilerTableEditor.ts @@ -35,6 +35,7 @@ import { ITextResourcePropertiesService } from 'vs/editor/common/services/textRe import { FindReplaceState, FindReplaceStateChangedEvent } from 'vs/editor/contrib/find/browser/findState'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; +import { ITableService } from 'sql/workbench/services/table/browser/tableService'; export interface ProfilerTableViewState { scrollTop: number; @@ -72,7 +73,8 @@ export class ProfilerTableEditor extends EditorPane implements IProfilerControll @IClipboardService private _clipboardService: IClipboardService, @ITextResourcePropertiesService private readonly textResourcePropertiesService: ITextResourcePropertiesService, @IAccessibilityService private readonly _accessibilityService: IAccessibilityService, - @IQuickInputService private readonly _quickInputService: IQuickInputService + @IQuickInputService private readonly _quickInputService: IQuickInputService, + @ITableService private readonly _tableService: ITableService ) { super(ProfilerTableEditor.ID, telemetryService, _themeService, storageService); this._actionMap[ACTION_IDS.FIND_NEXT] = this._instantiationService.createInstance(ProfilerFindNext, this); @@ -115,6 +117,7 @@ export class ProfilerTableEditor extends EditorPane implements IProfilerControll }); this._profilerTable.registerPlugin(copyKeybind); attachTableStyler(this._profilerTable, this._themeService); + this._register(this._tableService.registerTable(this._profilerTable)); this._findState = new FindReplaceState(); this._findState.onFindReplaceStateChange(e => this._onFindStateChange(e)); diff --git a/src/sql/workbench/contrib/query/browser/gridPanel.ts b/src/sql/workbench/contrib/query/browser/gridPanel.ts index 367adec3b7..3245566d51 100644 --- a/src/sql/workbench/contrib/query/browser/gridPanel.ts +++ b/src/sql/workbench/contrib/query/browser/gridPanel.ts @@ -57,6 +57,7 @@ import { formatDocumentWithSelectedProvider, FormattingMode } from 'vs/editor/co import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { queryEditorNullBackground } from 'sql/platform/theme/common/colorRegistry'; +import { ITableService } from 'sql/workbench/services/table/browser/tableService'; const ROW_HEIGHT = 29; const HEADER_HEIGHT = 26; @@ -417,7 +418,8 @@ export abstract class GridTableBase extends Disposable implements IView { @INotificationService private readonly notificationService: INotificationService, @IExecutionPlanService private readonly executionPlanService: IExecutionPlanService, @IAccessibilityService private readonly accessibilityService: IAccessibilityService, - @IQuickInputService private readonly quickInputService: IQuickInputService + @IQuickInputService private readonly quickInputService: IQuickInputService, + @ITableService private readonly tableService: ITableService ) { super(); @@ -580,6 +582,7 @@ export abstract class GridTableBase extends Disposable implements IView { })); this.table.registerPlugin(this.filterPlugin); + this._register(this.tableService.registerTable(this.table)); if (this.styles) { this.table.style(this.styles); } @@ -966,14 +969,15 @@ class GridTable extends GridTableBase { @INotificationService notificationService: INotificationService, @IExecutionPlanService executionPlanService: IExecutionPlanService, @IAccessibilityService accessibilityService: IAccessibilityService, - @IQuickInputService quickInputService: IQuickInputService + @IQuickInputService quickInputService: IQuickInputService, + @ITableService tableService: ITableService ) { super(state, resultSet, { actionOrientation: ActionsOrientation.VERTICAL, inMemoryDataProcessing: true, showActionBar: configurationService.getValue('queryEditor').results.showActionBar, inMemoryDataCountThreshold: configurationService.getValue('queryEditor').results.inMemoryDataProcessingThreshold, - }, contextMenuService, instantiationService, editorService, untitledEditorService, configurationService, queryModelService, themeService, contextViewService, notificationService, executionPlanService, accessibilityService, quickInputService); + }, contextMenuService, instantiationService, editorService, untitledEditorService, configurationService, queryModelService, themeService, contextViewService, notificationService, executionPlanService, accessibilityService, quickInputService, tableService); this._gridDataProvider = this.instantiationService.createInstance(QueryGridDataProvider, this._runner, resultSet.batchId, resultSet.id); this.providerId = this._runner.getProviderId(); } diff --git a/src/sql/workbench/contrib/resourceViewer/browser/resourceViewerTable.ts b/src/sql/workbench/contrib/resourceViewer/browser/resourceViewerTable.ts index 2b74a677c3..016cf7636d 100644 --- a/src/sql/workbench/contrib/resourceViewer/browser/resourceViewerTable.ts +++ b/src/sql/workbench/contrib/resourceViewer/browser/resourceViewerTable.ts @@ -27,6 +27,7 @@ import { LoadingSpinnerPlugin } from 'sql/base/browser/ui/table/plugins/loadingS import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; +import { ITableService } from 'sql/workbench/services/table/browser/tableService'; export class ResourceViewerTable extends Disposable { @@ -43,7 +44,8 @@ export class ResourceViewerTable extends Disposable { @INotificationService private _notificationService: INotificationService, @IContextViewService private _contextViewService: IContextViewService, @IAccessibilityService private _accessibilityService: IAccessibilityService, - @IQuickInputService private _quickInputService: IQuickInputService) { + @IQuickInputService private _quickInputService: IQuickInputService, + @ITableService private readonly _tableService: ITableService) { super(); let filterFn = (data: Array): Array => { return data.filter(item => this.filter(item)); @@ -89,6 +91,7 @@ export class ResourceViewerTable extends Disposable { }); this._resourceViewerTable.registerPlugin(filterPlugin); this._resourceViewerTable.registerPlugin(this._loadingSpinnerPlugin); + this._register(this._tableService.registerTable(this._resourceViewerTable)); } public set data(data: azdata.DataGridItem[]) { diff --git a/src/sql/workbench/contrib/table/browser/table.contribution.ts b/src/sql/workbench/contrib/table/browser/table.contribution.ts new file mode 100644 index 0000000000..687b0b465d --- /dev/null +++ b/src/sql/workbench/contrib/table/browser/table.contribution.ts @@ -0,0 +1,52 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Table } from 'sql/base/browser/ui/table/table'; +import { FilteringEnabled, InTable } from 'sql/workbench/services/table/browser/tableContext'; +import { ITableService } from 'sql/workbench/services/table/browser/tableService'; +import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; +import { KeybindingWeight, KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; +import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; +import { HeaderFilter } from 'sql/base/browser/ui/table/plugins/headerFilter.plugin'; +import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; + +export const RESIZE_COLUMN_COMMAND_ID = 'table.resizeColumn'; +export const SHOW_COLUMN_MENU_COMMAND_ID = 'table.showColumnMenu'; + +KeybindingsRegistry.registerCommandAndKeybindingRule({ + id: RESIZE_COLUMN_COMMAND_ID, + weight: KeybindingWeight.WorkbenchContrib, + when: InTable, + primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KeyS, + handler: async (accessor) => { + await handleTableCommand(accessor, async (table) => { + await table.resizeActiveColumn(); + }); + } +}); + +KeybindingsRegistry.registerCommandAndKeybindingRule({ + id: SHOW_COLUMN_MENU_COMMAND_ID, + weight: KeybindingWeight.WorkbenchContrib, + when: ContextKeyExpr.and(InTable, FilteringEnabled), + primary: KeyCode.F3, + handler: async (accessor) => { + await handleTableCommand(accessor, async (table) => { + let plugin = table.grid.getPlugins().find(p => p instanceof HeaderFilter) as HeaderFilter; + if (plugin) { + await plugin.showMenu(); + } + }); + } +}); + +async function handleTableCommand(accessor: ServicesAccessor, action: (table: Table) => Promise) { + const tableService = accessor.get(ITableService); + const table = tableService.getActiveTable(); + if (table) { + await action(table); + } +} + diff --git a/src/sql/workbench/services/insights/browser/insightsDialogView.ts b/src/sql/workbench/services/insights/browser/insightsDialogView.ts index 07b8dabbee..0be66761b4 100644 --- a/src/sql/workbench/services/insights/browser/insightsDialogView.ts +++ b/src/sql/workbench/services/insights/browser/insightsDialogView.ts @@ -53,6 +53,7 @@ import { IDisposableDataProvider } from 'sql/base/common/dataProvider'; import { ITextResourcePropertiesService } from 'vs/editor/common/services/textResourceConfiguration'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; +import { ITableService } from 'sql/workbench/services/table/browser/tableService'; const labelDisplay = nls.localize("insights.item", "Item"); const valueDisplay = nls.localize("insights.value", "Value"); @@ -90,7 +91,8 @@ class InsightTableView extends ViewPane { @IThemeService themeService: IThemeService, @ITelemetryService telemetryService: ITelemetryService, @IAccessibilityService private _accessibilityService: IAccessibilityService, - @IQuickInputService private _quickInputService: IQuickInputService + @IQuickInputService private _quickInputService: IQuickInputService, + @ITableService private readonly _tableService: ITableService ) { super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService); } @@ -100,6 +102,7 @@ class InsightTableView extends ViewPane { columns: this.columns, dataProvider: this.data }, this.tableOptions); + this._register(this._tableService.registerTable(this._table)); } protected override layoutBody(size: number): void { diff --git a/src/sql/workbench/services/restore/browser/restoreDialog.ts b/src/sql/workbench/services/restore/browser/restoreDialog.ts index b19930d9de..2d523d8ca1 100644 --- a/src/sql/workbench/services/restore/browser/restoreDialog.ts +++ b/src/sql/workbench/services/restore/browser/restoreDialog.ts @@ -50,6 +50,7 @@ import { MediaDeviceType } from 'sql/workbench/contrib/backup/common/constants'; import { ITextResourcePropertiesService } from 'vs/editor/common/services/textResourceConfiguration'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; +import { ITableService } from 'sql/workbench/services/table/browser/tableService'; interface FileListElement { logicalFileName: string; @@ -161,7 +162,8 @@ export class RestoreDialog extends Modal { @ILogService logService: ILogService, @ITextResourcePropertiesService textResourcePropertiesService: ITextResourcePropertiesService, @IAccessibilityService private _accessibilityService: IAccessibilityService, - @IQuickInputService private _quickInputService: IQuickInputService + @IQuickInputService private _quickInputService: IQuickInputService, + @ITableService private readonly _tableService: ITableService ) { super(localize('RestoreDialogTitle', "Restore database"), TelemetryKeys.ModalDialogName.Restore, telemetryService, layoutService, clipboardService, themeService, logService, textResourcePropertiesService, contextKeyService, { hasErrors: true, width: 'wide', hasSpinner: true }); // view model @@ -317,6 +319,7 @@ export class RestoreDialog extends Modal { this._restorePlanTable.setTableTitle(localize('restorePlan', "Restore plan")); this._restorePlanTable.setSelectionModel(new RowSelectionModel({ selectActiveRow: false })); this._restorePlanTable.onSelectedRowsChanged((e, data) => this.backupFileCheckboxChanged(e, data)); + this._register(this._tableService.registerTable(this._restorePlanTable)); // Content in general tab const generalTab = DOM.$('.restore-dialog'); @@ -366,6 +369,7 @@ export class RestoreDialog extends Modal { this._fileListTable = this._register(new Table(this._fileListTableContainer, this._accessibilityService, this._quickInputService, { dataProvider: this._fileListData, columns }, { enableColumnReorder: false })); this._fileListTable.setSelectionModel(new RowSelectionModel()); + this._register(this._tableService.registerTable(this._fileListTable)); // Content in options tab const optionsContentElement = DOM.$('.restore-dialog'); diff --git a/src/sql/workbench/services/table/browser/tableContext.ts b/src/sql/workbench/services/table/browser/tableContext.ts new file mode 100644 index 0000000000..6d02d909e0 --- /dev/null +++ b/src/sql/workbench/services/table/browser/tableContext.ts @@ -0,0 +1,27 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { HeaderFilter } from 'sql/base/browser/ui/table/plugins/headerFilter.plugin'; +import { Table } from 'sql/base/browser/ui/table/table'; +import { IDisposable } from 'vs/base/common/lifecycle'; +import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; + +export const InTable = new RawContextKey('inTable', true); +export const FilteringEnabled = new RawContextKey('filteringEnabled', false); + +export class TableContext implements IDisposable { + private _inTable: IContextKey; + private _filteringEnabled: IContextKey; + + constructor(contextKeyService: IContextKeyService, table: Table) { + this._inTable = InTable.bindTo(contextKeyService); + this._filteringEnabled = FilteringEnabled.bindTo(contextKeyService); + this._inTable.set(true); + this._filteringEnabled.set(table.grid.getPlugins().find(p => p instanceof HeaderFilter) !== undefined); + } + + dispose(): void { + } +} diff --git a/src/sql/workbench/services/table/browser/tableService.ts b/src/sql/workbench/services/table/browser/tableService.ts new file mode 100644 index 0000000000..97b38f4738 --- /dev/null +++ b/src/sql/workbench/services/table/browser/tableService.ts @@ -0,0 +1,61 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Table } from 'sql/base/browser/ui/table/table'; +import { TableContext } from 'sql/workbench/services/table/browser/tableContext'; +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { IDisposable } from 'vs/base/common/lifecycle'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; + +export const SERVICE_ID = 'tableService'; +export const ITableService = createDecorator(SERVICE_ID); + +/** + * Service to manage the table components used by the application. + */ +export interface ITableService { + _serviceBrand: undefined; + /** + * Register a table + */ + registerTable(table: Table): IDisposable; + /** + * Get the table that has the focus. + */ + getActiveTable(): Table | undefined; +} + +export class TableService implements ITableService { + _serviceBrand: undefined; + + private _tables: Map> = new Map>(); + private _currentId: number = 1; + + constructor(@IContextKeyService private readonly _contextKeyService: IContextKeyService) { } + + registerTable(table: Table): IDisposable { + const id = this._currentId++; + this._tables.set(id, table); + const service = this._contextKeyService.createScoped(table.grid.getContainerNode()); + const context = new TableContext(service, table); + + return { + dispose: () => { + this._tables.delete(id); + service.dispose(); + context.dispose(); + } + }; + } + + getActiveTable(): Table | undefined { + for (const table of this._tables.values()) { + if (table?.grid.getContainerNode().contains(document.activeElement)) { + return table; + } + } + return undefined; + } +} diff --git a/src/sql/workbench/test/electron-browser/modalComponents/table.component.test.ts b/src/sql/workbench/test/electron-browser/modalComponents/table.component.test.ts index fa842d6bf8..73f32b87f0 100644 --- a/src/sql/workbench/test/electron-browser/modalComponents/table.component.test.ts +++ b/src/sql/workbench/test/electron-browser/modalComponents/table.component.test.ts @@ -19,7 +19,7 @@ suite('TableComponent Tests', () => { ['4', '5', '6'] ]; let columns = ['c1', 'c2', 'c3']; - const tableComponent = new TableComponent(undefined, undefined, undefined, new NullLogService(), undefined, undefined, undefined, undefined, undefined); + const tableComponent = new TableComponent(undefined, undefined, undefined, new NullLogService(), undefined, undefined, undefined, undefined, undefined, undefined); let actual = tableComponent.transformData(data, columns); let expected: { [key: string]: string }[] = [ @@ -39,7 +39,7 @@ suite('TableComponent Tests', () => { test('Table transformData should return empty array given undefined rows', () => { let data = undefined; - const tableComponent = new TableComponent(undefined, undefined, undefined, new NullLogService(), undefined, undefined, undefined, undefined, undefined); + const tableComponent = new TableComponent(undefined, undefined, undefined, new NullLogService(), undefined, undefined, undefined, undefined, undefined, undefined); let columns = ['c1', 'c2', 'c3']; let actual = tableComponent.transformData(data, columns); let expected: { [key: string]: string }[] = []; @@ -52,7 +52,7 @@ suite('TableComponent Tests', () => { ['4', '5', '6'] ]; let columns; - const tableComponent = new TableComponent(undefined, undefined, undefined, new NullLogService(), undefined, undefined, undefined, undefined, undefined); + const tableComponent = new TableComponent(undefined, undefined, undefined, new NullLogService(), undefined, undefined, undefined, undefined, undefined, undefined); let actual = tableComponent.transformData(data, columns); let expected: { [key: string]: string }[] = []; assert.deepStrictEqual(actual, expected); @@ -63,7 +63,7 @@ suite('TableComponent Tests', () => { ['1', '2'], ['4', '5'] ]; - const tableComponent = new TableComponent(undefined, undefined, undefined, new NullLogService(), undefined, undefined, undefined, undefined, undefined); + const tableComponent = new TableComponent(undefined, undefined, undefined, new NullLogService(), undefined, undefined, undefined, undefined, undefined, undefined); let columns = ['c1', 'c2', 'c3']; let actual = tableComponent.transformData(data, columns); let expected: { [key: string]: string }[] = [ diff --git a/src/typings/slickgrid.d.ts b/src/typings/slickgrid.d.ts index 5206e0d571..1c4a2a1841 100644 --- a/src/typings/slickgrid.d.ts +++ b/src/typings/slickgrid.d.ts @@ -1243,6 +1243,7 @@ declare namespace Slick { // #region Plugins + public getPlugins(): Plugin[]; public registerPlugin(plugin: Plugin): void; public unregisterPlugin(plugin: Plugin): void; diff --git a/src/vs/workbench/workbench.common.main.ts b/src/vs/workbench/workbench.common.main.ts index 4666367e2b..1e531c2308 100644 --- a/src/vs/workbench/workbench.common.main.ts +++ b/src/vs/workbench/workbench.common.main.ts @@ -222,6 +222,7 @@ import { IExecutionPlanService } from 'sql/workbench/services/executionPlan/comm import { ExecutionPlanService } from 'sql/workbench/services/executionPlan/common/executionPlanService'; import { IErrorDiagnosticsService } from 'sql/workbench/services/diagnostics/common/errorDiagnosticsService'; import { ErrorDiagnosticsService } from 'sql/workbench/services/diagnostics/browser/errorDiagnosticsService'; +import { ITableService, TableService } from 'sql/workbench/services/table/browser/tableService'; registerSingleton(IDashboardService, DashboardService); registerSingleton(IDashboardViewService, DashboardViewService); @@ -266,6 +267,7 @@ registerSingleton(IDataGridProviderService, DataGridProviderService); registerSingleton(ITableDesignerService, TableDesignerService); registerSingleton(IExecutionPlanService, ExecutionPlanService); registerSingleton(IErrorDiagnosticsService, ErrorDiagnosticsService); +registerSingleton(ITableService, TableService); //#endregion @@ -576,4 +578,7 @@ import 'sql/workbench/contrib/tableDesigner/browser/tableDesigner.contribution'; // execution plan import 'sql/workbench/contrib/executionPlan/browser/executionPlanContribution'; +// table +import 'sql/workbench/contrib/table/browser/table.contribution'; + //#endregion diff --git a/yarn.lock b/yarn.lock index 415b5d124d..b5a4e9eff7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9465,9 +9465,9 @@ slice-ansi@^2.1.0: astral-regex "^1.0.0" is-fullwidth-code-point "^2.0.0" -"slickgrid@github:Microsoft/SlickGrid.ADS#2.3.42": - version "2.3.42" - resolved "https://codeload.github.com/Microsoft/SlickGrid.ADS/tar.gz/29021c4410512d0d644a3b8eb5115bc84ed277e9" +"slickgrid@github:Microsoft/SlickGrid.ADS#2.3.43": + version "2.3.43" + resolved "https://codeload.github.com/Microsoft/SlickGrid.ADS/tar.gz/877ada4c52320a851bb9f7b54eed10831423c144" smart-buffer@^4.2.0: version "4.2.0"