From e62486bee6217e9749e687344d7beb1a7dbf0364 Mon Sep 17 00:00:00 2001 From: Alan Ren Date: Wed, 24 May 2023 21:41:00 -0700 Subject: [PATCH] fix query result grid shortcut keys (#23206) * fix query result grid shortcut keys * add comment --- .../workbench/browser/designer/designer.ts | 6 +- .../modelComponents/table.component.ts | 6 +- .../browser/asmtResultsView.component.ts | 6 +- .../contrib/charts/browser/tableInsight.ts | 6 +- .../browser/widgets/explorer/explorerTable.ts | 6 +- .../explorer/explorerWidget.component.ts | 6 +- .../insights/views/tableInsight.component.ts | 6 +- .../executionPlanComparisonPropertiesView.ts | 6 +- .../browser/executionPlanPropertiesView.ts | 6 +- .../executionPlanPropertiesViewBase.ts | 6 +- .../browser/executionPlanTreeTab.ts | 6 +- .../executionPlan/browser/topOperationsTab.ts | 6 +- .../browser/alertsView.component.ts | 6 +- .../browser/jobsView.component.ts | 6 +- .../browser/notebooksView.component.ts | 6 +- .../browser/operatorsView.component.ts | 6 +- .../browser/proxiesView.component.ts | 6 +- .../browser/outputs/gridOutput.component.ts | 23 +-- .../profiler/browser/profilerEditor.ts | 6 +- .../profiler/browser/profilerTableEditor.ts | 6 +- .../contrib/query/browser/actions.ts | 4 +- .../contrib/query/browser/gridPanel.ts | 107 +++++++++--- .../query/browser/query.contribution.ts | 155 +++++++----------- .../browser/resourceViewerTable.ts | 6 +- .../table/browser/table.contribution.ts | 14 +- .../browser/componentContextService.ts | 112 +++++++++++++ .../componentContext/browser/contextKeys.ts | 13 ++ .../insights/browser/insightsDialogView.ts | 6 +- .../services/restore/browser/restoreDialog.ts | 8 +- .../services/table/browser/tableContext.ts | 27 --- .../services/table/browser/tableService.ts | 61 ------- src/vs/workbench/workbench.common.main.ts | 4 +- 32 files changed, 358 insertions(+), 296 deletions(-) create mode 100644 src/sql/workbench/services/componentContext/browser/componentContextService.ts create mode 100644 src/sql/workbench/services/componentContext/browser/contextKeys.ts delete mode 100644 src/sql/workbench/services/table/browser/tableContext.ts delete mode 100644 src/sql/workbench/services/table/browser/tableService.ts diff --git a/src/sql/workbench/browser/designer/designer.ts b/src/sql/workbench/browser/designer/designer.ts index ffea8f052d..041b23b51d 100644 --- a/src/sql/workbench/browser/designer/designer.ts +++ b/src/sql/workbench/browser/designer/designer.ts @@ -55,7 +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'; +import { IComponentContextService } from 'sql/workbench/services/componentContext/browser/componentContextService'; export interface IDesignerStyle { tabbedPanelStyles?: ITabbedPanelStyles; @@ -119,7 +119,7 @@ export class Designer extends Disposable implements IThemable { @IContextMenuService private readonly _contextMenuService: IContextMenuService, @IAccessibilityService private readonly _accessibilityService: IAccessibilityService, @IQuickInputService private readonly _quickInputService: IQuickInputService, - @ITableService private readonly _tableService: ITableService) { + @IComponentContextService private readonly _componentContextService: IComponentContextService) { super(); this._tableCellEditorFactory = new TableCellEditorFactory( { @@ -1028,7 +1028,7 @@ export class Designer extends Disposable implements IThemable { currentTableActions.forEach(a => a.updateState()); table.grid.setSelectedRows([]); }); - this._register(this._tableService.registerTable(table)); + this._register(this._componentContextService.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 cd40ff1c45..60e065fb72 100644 --- a/src/sql/workbench/browser/modelComponents/table.component.ts +++ b/src/sql/workbench/browser/modelComponents/table.component.ts @@ -39,7 +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'; +import { IComponentContextService } from 'sql/workbench/services/componentContext/browser/componentContextService'; import { deepClone, equals } from 'vs/base/common/objects'; export enum ColumnSizingMode { @@ -95,7 +95,7 @@ export default class TableComponent extends ComponentBasethis.rowDetail); this._table.registerPlugin(filterPlugin); - this._register(this.tableService.registerTable(this._table)); + this._register(this.componentContextService.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 3f8adbf06c..6d54da6389 100644 --- a/src/sql/workbench/contrib/charts/browser/tableInsight.ts +++ b/src/sql/workbench/contrib/charts/browser/tableInsight.ts @@ -16,7 +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'; +import { IComponentContextService } from 'sql/workbench/services/componentContext/browser/componentContextService'; export class TableInsight extends Disposable implements IInsight { public static readonly types = [InsightType.Table]; @@ -31,7 +31,7 @@ export class TableInsight extends Disposable implements IInsight { @IThemeService themeService: IThemeService, @IAccessibilityService accessibilityService: IAccessibilityService, @IQuickInputService quickInputService: IQuickInputService, - @ITableService private tableService: ITableService + @IComponentContextService private componentContextService: IComponentContextService ) { super(); let tableContainer = $('div'); @@ -42,7 +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)); + this._register(this.componentContextService.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 3e985fb3fb..71b64921b5 100644 --- a/src/sql/workbench/contrib/dashboard/browser/widgets/explorer/explorerTable.ts +++ b/src/sql/workbench/contrib/dashboard/browser/widgets/explorer/explorerTable.ts @@ -20,7 +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 { IComponentContextService } from 'sql/workbench/services/componentContext/browser/componentContextService'; import * as DOM from 'vs/base/browser/dom'; import { status } from 'vs/base/browser/ui/aria/aria'; import { IAction } from 'vs/base/common/actions'; @@ -69,7 +69,7 @@ export class ExplorerTable extends Disposable { private readonly dashboardService: IDashboardService, readonly accessibilityService: IAccessibilityService, readonly quickInputService: IQuickInputService, - private readonly tableService: ITableService) { + private readonly componentContextService: IComponentContextService) { super(); this._explorerView = new ExplorerView(this.context); const connectionInfo = this.bootStrapService.connectionManagementService.connectionInfo; @@ -115,7 +115,7 @@ export class ExplorerTable extends Disposable { this._table.grid.invalidateAllRows(); this._table.updateRowCount(); })); - this._register(this.tableService.registerTable(this._table)); + this._register(this.componentContextService.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 58a1f4df51..9734d269c4 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,7 +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'; +import { IComponentContextService } from 'sql/workbench/services/componentContext/browser/componentContextService'; @Component({ selector: 'explorer-widget', @@ -65,7 +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(IComponentContextService) private readonly componentContextService: IComponentContextService, @Inject(forwardRef(() => ChangeDetectorRef)) changeRef: ChangeDetectorRef ) { super(changeRef); @@ -101,7 +101,7 @@ export class ExplorerWidget extends DashboardWidget implements IDashboardWidget, this.dashboardService, this.accessibilityService, this.quickInputService, - this.tableService); + this.componentContextService); 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 e360723bda..d90cf78853 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,7 +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'; +import { IComponentContextService } from 'sql/workbench/services/componentContext/browser/componentContextService'; @Component({ template: '' @@ -31,7 +31,7 @@ export default class TableInsight extends Disposable implements IInsightsView, O @Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService, @Inject(IAccessibilityService) private accessibilityService: IAccessibilityService, @Inject(IQuickInputService) private quickInputService: IQuickInputService, - @Inject(ITableService) private tableService: ITableService + @Inject(IComponentContextService) private componentContextService: IComponentContextService ) { super(); } @@ -70,7 +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)); + this._register(this.componentContextService.registerTable(this.table)); } } } diff --git a/src/sql/workbench/contrib/executionPlan/browser/executionPlanComparisonPropertiesView.ts b/src/sql/workbench/contrib/executionPlan/browser/executionPlanComparisonPropertiesView.ts index 4feb6591ae..23b8fe98fa 100644 --- a/src/sql/workbench/contrib/executionPlan/browser/executionPlanComparisonPropertiesView.ts +++ b/src/sql/workbench/contrib/executionPlan/browser/executionPlanComparisonPropertiesView.ts @@ -20,7 +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'; +import { IComponentContextService } from 'sql/workbench/services/componentContext/browser/componentContextService'; export enum ExecutionPlanCompareOrientation { Horizontal = 'horizontal', @@ -68,9 +68,9 @@ export class ExecutionPlanComparisonPropertiesView extends ExecutionPlanProperti @IContextViewService contextViewService: IContextViewService, @IAccessibilityService accessibilityService: IAccessibilityService, @IQuickInputService quickInputService: IQuickInputService, - @ITableService tableService: ITableService + @IComponentContextService componentContextService: IComponentContextService ) { - super(parentContainer, themeService, instantiationService, contextMenuService, contextViewService, accessibilityService, quickInputService, tableService); + super(parentContainer, themeService, instantiationService, contextMenuService, contextViewService, accessibilityService, quickInputService, componentContextService); 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 55f0515b7f..ca9b0c5a31 100644 --- a/src/sql/workbench/contrib/executionPlan/browser/executionPlanPropertiesView.ts +++ b/src/sql/workbench/contrib/executionPlan/browser/executionPlanPropertiesView.ts @@ -15,7 +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'; +import { IComponentContextService } from 'sql/workbench/services/componentContext/browser/componentContextService'; export class ExecutionPlanPropertiesView extends ExecutionPlanPropertiesViewBase { // Div that holds the name of the element selected @@ -30,9 +30,9 @@ export class ExecutionPlanPropertiesView extends ExecutionPlanPropertiesViewBase @IContextViewService contextViewService: IContextViewService, @IAccessibilityService accessibilityService: IAccessibilityService, @IQuickInputService quickInputService: IQuickInputService, - @ITableService tableService: ITableService + @IComponentContextService componentContextService: IComponentContextService ) { - super(parentContainer, themeService, instantiationService, contextMenuService, contextViewService, accessibilityService, quickInputService, tableService); + super(parentContainer, themeService, instantiationService, contextMenuService, contextViewService, accessibilityService, quickInputService, componentContextService); 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 c930358bdd..9079b9079a 100644 --- a/src/sql/workbench/contrib/executionPlan/browser/executionPlanPropertiesViewBase.ts +++ b/src/sql/workbench/contrib/executionPlan/browser/executionPlanPropertiesViewBase.ts @@ -27,7 +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'; +import { IComponentContextService } from 'sql/workbench/services/componentContext/browser/componentContextService'; export abstract class ExecutionPlanPropertiesViewBase extends Disposable implements IVerticalSashLayoutProvider { // Title bar with close button action @@ -73,7 +73,7 @@ export abstract class ExecutionPlanPropertiesViewBase extends Disposable impleme @IContextViewService private _contextViewService: IContextViewService, @IAccessibilityService accessibilityService: IAccessibilityService, @IQuickInputService quickInputService: IQuickInputService, - @ITableService private _tableService: ITableService + @IComponentContextService private _componentContextService: IComponentContextService ) { super(); const sashContainer = DOM.$('.properties-sash'); @@ -192,7 +192,7 @@ 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)); + this._register(this._componentContextService.registerTable(this._tableComponent)); new ResizeObserver((e) => { diff --git a/src/sql/workbench/contrib/executionPlan/browser/executionPlanTreeTab.ts b/src/sql/workbench/contrib/executionPlan/browser/executionPlanTreeTab.ts index ed102dd5f2..d662a1c113 100644 --- a/src/sql/workbench/contrib/executionPlan/browser/executionPlanTreeTab.ts +++ b/src/sql/workbench/contrib/executionPlan/browser/executionPlanTreeTab.ts @@ -26,7 +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'; +import { IComponentContextService } from 'sql/workbench/services/componentContext/browser/componentContextService'; export class ExecutionPlanTreeTab extends Disposable implements IPanelTab { public readonly title: string = localize('planTreeTab.title', 'Plan Tree'); @@ -57,7 +57,7 @@ export class ExecutionPlanTreeTabView extends Disposable implements IPanelView { @IContextMenuService private _contextMenuService: IContextMenuService, @IAccessibilityService private _accessibilityService: IAccessibilityService, @IQuickInputService private _quickInputService: IQuickInputService, - @ITableService private _tableService: ITableService + @IComponentContextService private _componentContextService: IComponentContextService ) { super(); } @@ -280,7 +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)); + this._register(this._componentContextService.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 6f902cea14..e4e70d0c2c 100644 --- a/src/sql/workbench/contrib/executionPlan/browser/topOperationsTab.ts +++ b/src/sql/workbench/contrib/executionPlan/browser/topOperationsTab.ts @@ -32,7 +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'; +import { IComponentContextService } from 'sql/workbench/services/componentContext/browser/componentContextService'; const TABLE_SORT_COLUMN_KEY = 'tableCostColumnForSorting'; @@ -67,7 +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 + @IComponentContextService private _componentContextService: IComponentContextService ) { super(); } @@ -410,7 +410,7 @@ export class TopOperationsTabView extends Disposable implements IPanelView { table.layout(new DOM.Dimension(tableContainer.clientWidth, tableContainer.clientHeight)); }).observe(tableContainer); - this._register(this._tableService.registerTable(table)); + this._register(this._componentContextService.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 293be6e3b7..aed8c5b76c 100644 --- a/src/sql/workbench/contrib/jobManagement/browser/alertsView.component.ts +++ b/src/sql/workbench/contrib/jobManagement/browser/alertsView.component.ts @@ -26,7 +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'; +import { IComponentContextService } from 'sql/workbench/services/componentContext/browser/componentContextService'; export const VIEW_SELECTOR: string = 'jobalertsview-component'; export const ROW_HEIGHT: number = 45; @@ -82,7 +82,7 @@ export class AlertsViewComponent extends JobManagementView implements OnInit, On @Inject(IDashboardService) _dashboardService: IDashboardService, @Inject(IAccessibilityService) private _accessibilityService: IAccessibilityService, @Inject(IQuickInputService) private _quickInputService: IQuickInputService, - @Inject(ITableService) private _tableService: ITableService) { + @Inject(IComponentContextService) private _componentContextService: IComponentContextService) { super(commonService, _dashboardService, contextMenuService, keybindingService, instantiationService, _agentViewComponent); this._didTabChange = false; this._isCloud = commonService.connectionManagementService.connectionInfo.serverInfo.isCloud; @@ -150,7 +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._register(this._componentContextService.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 a1819a88a3..646b11759e 100644 --- a/src/sql/workbench/contrib/jobManagement/browser/jobsView.component.ts +++ b/src/sql/workbench/contrib/jobManagement/browser/jobsView.component.ts @@ -36,7 +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'; +import { IComponentContextService } from 'sql/workbench/services/componentContext/browser/componentContextService'; export const JOBSVIEW_SELECTOR: string = 'jobsview-component'; export const ROW_HEIGHT: number = 45; @@ -114,7 +114,7 @@ export class JobsViewComponent extends JobManagementView implements OnInit, OnDe @Inject(IContextViewService) private _contextViewService: IContextViewService, @Inject(IAccessibilityService) private _accessibilityService: IAccessibilityService, @Inject(IQuickInputService) private _quickInputService: IQuickInputService, - @Inject(ITableService) private _tableService: ITableService + @Inject(IComponentContextService) private _componentContextService: IComponentContextService ) { super(commonService, _dashboardService, contextMenuService, keybindingService, instantiationService, _agentViewComponent); let jobCacheObjectMap = this._jobManagementService.jobCacheObjectMap; @@ -202,7 +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._componentContextService.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 4ae6d15252..db6aa4ad40 100644 --- a/src/sql/workbench/contrib/jobManagement/browser/notebooksView.component.ts +++ b/src/sql/workbench/contrib/jobManagement/browser/notebooksView.component.ts @@ -37,7 +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'; +import { IComponentContextService } from 'sql/workbench/services/componentContext/browser/componentContextService'; export const NOTEBOOKSVIEW_SELECTOR: string = 'notebooksview-component'; @@ -113,7 +113,7 @@ export class NotebooksViewComponent extends JobManagementView implements OnInit, @Inject(IContextViewService) private _contextViewService: IContextViewService, @Inject(IAccessibilityService) private _accessibilityService: IAccessibilityService, @Inject(IQuickInputService) private _quickInputService: IQuickInputService, - @Inject(ITableService) private _tableService: ITableService + @Inject(IComponentContextService) private _componentContextService: IComponentContextService ) { super(commonService, _dashboardService, contextMenuService, keybindingService, instantiationService, _agentViewComponent); let notebookCacheObjectMap = this._jobManagementService.notebookCacheObjectMap; @@ -201,7 +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._componentContextService.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 693e4b6a26..1bb60ff336 100644 --- a/src/sql/workbench/contrib/jobManagement/browser/operatorsView.component.ts +++ b/src/sql/workbench/contrib/jobManagement/browser/operatorsView.component.ts @@ -26,7 +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'; +import { IComponentContextService } from 'sql/workbench/services/componentContext/browser/componentContextService'; export const VIEW_SELECTOR: string = 'joboperatorsview-component'; export const ROW_HEIGHT: number = 45; @@ -81,7 +81,7 @@ export class OperatorsViewComponent extends JobManagementView implements OnInit, @Inject(IDashboardService) _dashboardService: IDashboardService, @Inject(IAccessibilityService) private _accessibilityService: IAccessibilityService, @Inject(IQuickInputService) private _quickInputService: IQuickInputService, - @Inject(ITableService) private _tableService: ITableService + @Inject(IComponentContextService) private _componentContextService: IComponentContextService ) { super(commonService, _dashboardService, contextMenuService, keybindingService, instantiationService, _agentViewComponent); this._isCloud = commonService.connectionManagementService.connectionInfo.serverInfo.isCloud; @@ -151,7 +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._componentContextService.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 a24a8e8821..75e239469a 100644 --- a/src/sql/workbench/contrib/jobManagement/browser/proxiesView.component.ts +++ b/src/sql/workbench/contrib/jobManagement/browser/proxiesView.component.ts @@ -26,7 +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'; +import { IComponentContextService } from 'sql/workbench/services/componentContext/browser/componentContextService'; export const VIEW_SELECTOR: string = 'jobproxiesview-component'; export const ROW_HEIGHT: number = 45; @@ -82,7 +82,7 @@ export class ProxiesViewComponent extends JobManagementView implements OnInit, O @Inject(IDashboardService) _dashboardService: IDashboardService, @Inject(IAccessibilityService) private _accessibilityService: IAccessibilityService, @Inject(IQuickInputService) private _quickInputService: IQuickInputService, - @Inject(ITableService) private _tableService: ITableService + @Inject(IComponentContextService) private _componentContextService: IComponentContextService ) { super(commonService, _dashboardService, contextMenuService, keybindingService, instantiationService, _agentViewComponent); this._isCloud = commonService.connectionManagementService.connectionInfo.serverInfo.isCloud; @@ -150,7 +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._register(this._componentContextService.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 e8c5dad772..d4df07ae79 100644 --- a/src/sql/workbench/contrib/notebook/browser/outputs/gridOutput.component.ts +++ b/src/sql/workbench/contrib/notebook/browser/outputs/gridOutput.component.ts @@ -28,7 +28,7 @@ import { GridTableState } from 'sql/workbench/common/editor/query/gridTableState import { GridTableBase } from 'sql/workbench/contrib/query/browser/gridPanel'; import { getErrorMessage, onUnexpectedError } from 'vs/base/common/errors'; import { ISerializationService, SerializeDataParams } from 'sql/platform/serialization/common/serializationService'; -import { SaveResultAction, IGridActionContext } from 'sql/workbench/contrib/query/browser/actions'; +import { IGridActionContext } from 'sql/workbench/contrib/query/browser/actions'; import { SaveFormat, ResultSerializer, SaveResultsResponse } from 'sql/workbench/services/query/common/resultSerializer'; import { IUntitledTextEditorService } from 'vs/workbench/services/untitled/common/untitledTextEditorService'; import { ChartView } from 'sql/workbench/contrib/charts/browser/chartView'; @@ -50,7 +50,9 @@ 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'; +import { IComponentContextService } from 'sql/workbench/services/componentContext/browser/componentContextService'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { ILogService } from 'vs/platform/log/common/log'; @Component({ selector: GridOutputComponent.SELECTOR, @@ -245,12 +247,14 @@ class DataResourceTable extends GridTableBase { @IExecutionPlanService executionPlanService: IExecutionPlanService, @IAccessibilityService accessibilityService: IAccessibilityService, @IQuickInputService quickInputService: IQuickInputService, - @ITableService tableService: ITableService + @IComponentContextService componentContextService: IComponentContextService, + @IContextKeyService contextKeyService: IContextKeyService, + @ILogService logService: ILogService ) { super(state, createResultSet(source), { actionOrientation: ActionsOrientation.HORIZONTAL, inMemoryDataProcessing: true - }, contextMenuService, instantiationService, editorService, untitledEditorService, configurationService, queryModelService, themeService, contextViewService, notificationService, executionPlanService, accessibilityService, quickInputService, tableService); + }, contextMenuService, instantiationService, editorService, untitledEditorService, configurationService, queryModelService, themeService, contextViewService, notificationService, executionPlanService, accessibilityService, quickInputService, componentContextService, contextKeyService, logService); this._gridDataProvider = this.instantiationService.createInstance(DataResourceDataProvider, source, this.resultSet, this.cellModel); this._chart = this.instantiationService.createInstance(ChartView, false); @@ -273,17 +277,14 @@ class DataResourceTable extends GridTableBase { return this.cellOutput.metadata.azdata_chartOptions !== undefined; } - protected getCurrentActions(): IAction[] { - return this.getContextActions(); + protected override getActionBarItems(): IAction[] { + const items = super.getActionBarItems(); + items.push(this.instantiationService.createInstance(NotebookChartAction, this)); + return items; } protected getContextActions(): IAction[] { return [ - this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVECSV_ID, SaveResultAction.SAVECSV_LABEL, SaveResultAction.SAVECSV_ICON, SaveFormat.CSV), - this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEEXCEL_ID, SaveResultAction.SAVEEXCEL_LABEL, SaveResultAction.SAVEEXCEL_ICON, SaveFormat.EXCEL), - this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEJSON_ID, SaveResultAction.SAVEJSON_LABEL, SaveResultAction.SAVEJSON_ICON, SaveFormat.JSON), - this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEMARKDOWN_ID, SaveResultAction.SAVEMARKDOWN_LABEL, SaveResultAction.SAVEMARKDOWN_ICON, SaveFormat.MARKDOWN), - this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEXML_ID, SaveResultAction.SAVEXML_LABEL, SaveResultAction.SAVEXML_ICON, SaveFormat.XML), this.instantiationService.createInstance(NotebookChartAction, this) ]; } diff --git a/src/sql/workbench/contrib/profiler/browser/profilerEditor.ts b/src/sql/workbench/contrib/profiler/browser/profilerEditor.ts index deafd18665..9153fed37a 100644 --- a/src/sql/workbench/contrib/profiler/browser/profilerEditor.ts +++ b/src/sql/workbench/contrib/profiler/browser/profilerEditor.ts @@ -56,7 +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'; +import { IComponentContextService } from 'sql/workbench/services/componentContext/browser/componentContextService'; class BasicView implements IView { public get element(): HTMLElement { @@ -177,7 +177,7 @@ export class ProfilerEditor extends EditorPane { @IEditorGroupsService editorGroupsService: IEditorGroupsService, @IAccessibilityService private readonly _accessibilityService: IAccessibilityService, @IQuickInputService private readonly _quickInputService: IQuickInputService, - @ITableService private readonly _tableService: ITableService + @IComponentContextService private readonly _componentContextService: IComponentContextService ) { super(ProfilerEditor.ID, telemetryService, themeService, storageService); this._profilerEditorContextKey = CONTEXT_PROFILER_EDITOR.bindTo(this._contextKeyService); @@ -431,7 +431,7 @@ export class ProfilerEditor extends EditorPane { }); this._detailTable.setSelectionModel(new CellSelectionModel()); this._detailTable.registerPlugin(detailTableCopyKeybind); - this._register(this._tableService.registerTable(this._detailTable)); + this._register(this._componentContextService.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 f0c0a3f01d..750f7f065c 100644 --- a/src/sql/workbench/contrib/profiler/browser/profilerTableEditor.ts +++ b/src/sql/workbench/contrib/profiler/browser/profilerTableEditor.ts @@ -35,7 +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'; +import { IComponentContextService } from 'sql/workbench/services/componentContext/browser/componentContextService'; export interface ProfilerTableViewState { scrollTop: number; @@ -74,7 +74,7 @@ export class ProfilerTableEditor extends EditorPane implements IProfilerControll @ITextResourcePropertiesService private readonly textResourcePropertiesService: ITextResourcePropertiesService, @IAccessibilityService private readonly _accessibilityService: IAccessibilityService, @IQuickInputService private readonly _quickInputService: IQuickInputService, - @ITableService private readonly _tableService: ITableService + @IComponentContextService private readonly _componentContextService: IComponentContextService ) { super(ProfilerTableEditor.ID, telemetryService, _themeService, storageService); this._actionMap[ACTION_IDS.FIND_NEXT] = this._instantiationService.createInstance(ProfilerFindNext, this); @@ -117,7 +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._register(this._componentContextService.registerTable(this._profilerTable)); this._findState = new FindReplaceState(); this._findState.onFindReplaceStateChange(e => this._onFindStateChange(e)); diff --git a/src/sql/workbench/contrib/query/browser/actions.ts b/src/sql/workbench/contrib/query/browser/actions.ts index 0d97eca720..d9ecbea720 100644 --- a/src/sql/workbench/contrib/query/browser/actions.ts +++ b/src/sql/workbench/contrib/query/browser/actions.ts @@ -101,7 +101,7 @@ export class SaveResultAction extends Action { } export class CopyResultAction extends Action { - public static COPY_ID = 'grid.copySelection'; + public static COPY_ID = 'editor.action.clipboardCopyAction'; public static COPY_LABEL = localize('copySelection', "Copy"); public static COPYWITHHEADERS_ID = 'grid.copyWithHeaders'; @@ -124,7 +124,7 @@ export class CopyResultAction extends Action { } export class CopyHeadersAction extends Action { - private static ID = 'grid.copyHeaders'; + public static ID = 'grid.copyHeaders'; private static LABEL = localize('copyHeaders', 'Copy Headers'); constructor( diff --git a/src/sql/workbench/contrib/query/browser/gridPanel.ts b/src/sql/workbench/contrib/query/browser/gridPanel.ts index 3245566d51..01ce01f807 100644 --- a/src/sql/workbench/contrib/query/browser/gridPanel.ts +++ b/src/sql/workbench/contrib/query/browser/gridPanel.ts @@ -57,7 +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'; +import { IComponentContextService } from 'sql/workbench/services/componentContext/browser/componentContextService'; const ROW_HEIGHT = 29; const HEADER_HEIGHT = 26; @@ -357,7 +357,12 @@ const defaultGridTableOptions: IGridTableOptions = { actionOrientation: ActionsOrientation.VERTICAL }; -export abstract class GridTableBase extends Disposable implements IView { +export interface IQueryResultGrid { + readonly htmlElement: HTMLElement; + runAction(actionId: string): void; +} + +export abstract class GridTableBase extends Disposable implements IView, IQueryResultGrid { private table: Table; private actionBar: ActionBar; private container = document.createElement('div'); @@ -419,7 +424,9 @@ export abstract class GridTableBase extends Disposable implements IView { @IExecutionPlanService private readonly executionPlanService: IExecutionPlanService, @IAccessibilityService private readonly accessibilityService: IAccessibilityService, @IQuickInputService private readonly quickInputService: IQuickInputService, - @ITableService private readonly tableService: ITableService + @IComponentContextService private readonly componentContextService: IComponentContextService, + @IContextKeyService protected readonly contextKeyService: IContextKeyService, + @ILogService private readonly logService: ILogService ) { super(); @@ -429,7 +436,6 @@ export abstract class GridTableBase extends Disposable implements IView { this.state = state; this.container.style.width = '100%'; this.container.style.height = '100%'; - this.columns = this.resultSet.columnInfo.map((c, i) => { return >{ id: i.toString(), @@ -445,6 +451,47 @@ export abstract class GridTableBase extends Disposable implements IView { }); } + public get htmlElement(): HTMLElement { + return this.tableContainer; + } + + runAction(actionId: string): void { + let action: IAction | undefined; + switch (actionId) { + case CopyResultAction.COPYWITHHEADERS_ID: + action = this.instantiationService.createInstance(CopyResultAction, CopyResultAction.COPYWITHHEADERS_ID, CopyResultAction.COPYWITHHEADERS_LABEL, true); + break; + case CopyHeadersAction.ID: + action = this.instantiationService.createInstance(CopyHeadersAction); + break; + case SelectAllGridAction.ID: + action = this.instantiationService.createInstance(SelectAllGridAction); + break; + case SaveResultAction.SAVECSV_ID: + action = this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVECSV_ID, SaveResultAction.SAVECSV_LABEL, SaveResultAction.SAVECSV_ICON, SaveFormat.CSV); + break; + case SaveResultAction.SAVEEXCEL_ID: + action = this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEEXCEL_ID, SaveResultAction.SAVEEXCEL_LABEL, SaveResultAction.SAVEEXCEL_ICON, SaveFormat.EXCEL); + break; + case SaveResultAction.SAVEJSON_ID: + action = this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEJSON_ID, SaveResultAction.SAVEJSON_LABEL, SaveResultAction.SAVEJSON_ICON, SaveFormat.JSON); + break; + case SaveResultAction.SAVEMARKDOWN_ID: + action = this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEMARKDOWN_ID, SaveResultAction.SAVEMARKDOWN_LABEL, SaveResultAction.SAVEMARKDOWN_ICON, SaveFormat.MARKDOWN); + break; + case SaveResultAction.SAVEXML_ID: + action = this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEXML_ID, SaveResultAction.SAVEXML_LABEL, SaveResultAction.SAVEXML_ICON, SaveFormat.XML); + break; + default: + this.logService.error(`No handler registered for action '${actionId}'`); + break; + } + if (action) { + action.run(this.generateContext()); + action.dispose(); + } + } + abstract get gridDataProvider(): IGridDataProvider; public get resultSet(): ResultSetSummary { @@ -582,7 +629,9 @@ export abstract class GridTableBase extends Disposable implements IView { })); this.table.registerPlugin(this.filterPlugin); - this._register(this.tableService.registerTable(this.table)); + const result = this.componentContextService.registerQueryResultGrid(this); + this._register(result); + this._register(this.componentContextService.registerTable(this.table, result.componentContextKeyService)); if (this.styles) { this.table.style(this.styles); } @@ -809,7 +858,7 @@ export abstract class GridTableBase extends Disposable implements IView { } private rebuildActionBar() { - let actions = this.getCurrentActions(); + let actions = this.getActionBarItems(); this.actionBar.clear(); if (this.options.showActionBar) { this.actionBar.push(actions, { icon: true, label: false }); @@ -827,7 +876,15 @@ export abstract class GridTableBase extends Disposable implements IView { } } - protected abstract getCurrentActions(): IAction[]; + protected getActionBarItems(): IAction[] { + return [ + this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVECSV_ID, SaveResultAction.SAVECSV_LABEL, SaveResultAction.SAVECSV_ICON, SaveFormat.CSV), + this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEEXCEL_ID, SaveResultAction.SAVEEXCEL_LABEL, SaveResultAction.SAVEEXCEL_ICON, SaveFormat.EXCEL), + this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEJSON_ID, SaveResultAction.SAVEJSON_LABEL, SaveResultAction.SAVEJSON_ICON, SaveFormat.JSON), + this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEMARKDOWN_ID, SaveResultAction.SAVEMARKDOWN_LABEL, SaveResultAction.SAVEMARKDOWN_ICON, SaveFormat.MARKDOWN), + this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEXML_ID, SaveResultAction.SAVEXML_LABEL, SaveResultAction.SAVEXML_ICON, SaveFormat.XML) + ]; + } protected abstract getContextActions(): IAction[]; @@ -888,11 +945,18 @@ export abstract class GridTableBase extends Disposable implements IView { new SelectAllGridAction(), new Separator() ]; + actions.push( + this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVECSV_ID, SaveResultAction.SAVECSV_LABEL, SaveResultAction.SAVECSV_ICON, SaveFormat.CSV), + this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEEXCEL_ID, SaveResultAction.SAVEEXCEL_LABEL, SaveResultAction.SAVEEXCEL_ICON, SaveFormat.EXCEL), + this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEJSON_ID, SaveResultAction.SAVEJSON_LABEL, SaveResultAction.SAVEJSON_ICON, SaveFormat.JSON), + this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEMARKDOWN_ID, SaveResultAction.SAVEMARKDOWN_LABEL, SaveResultAction.SAVEMARKDOWN_ICON, SaveFormat.MARKDOWN), + this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEXML_ID, SaveResultAction.SAVEXML_LABEL, SaveResultAction.SAVEXML_ICON, SaveFormat.XML) + ); let contributedActions: IAction[] = this.getContextActions(); if (contributedActions && contributedActions.length > 0) { actions.push(...contributedActions); - actions.push(new Separator()); } + actions.push(new Separator()); actions.push( this.instantiationService.createInstance(CopyResultAction, CopyResultAction.COPY_ID, CopyResultAction.COPY_LABEL, false), this.instantiationService.createInstance(CopyResultAction, CopyResultAction.COPYWITHHEADERS_ID, CopyResultAction.COPYWITHHEADERS_LABEL, true), @@ -959,7 +1023,7 @@ class GridTable extends GridTableBase { state: GridTableState, @IContextMenuService contextMenuService: IContextMenuService, @IInstantiationService instantiationService: IInstantiationService, - @IContextKeyService private contextKeyService: IContextKeyService, + @IContextKeyService contextKeyService: IContextKeyService, @IEditorService editorService: IEditorService, @IUntitledTextEditorService untitledEditorService: IUntitledTextEditorService, @IConfigurationService configurationService: IConfigurationService, @@ -970,14 +1034,15 @@ class GridTable extends GridTableBase { @IExecutionPlanService executionPlanService: IExecutionPlanService, @IAccessibilityService accessibilityService: IAccessibilityService, @IQuickInputService quickInputService: IQuickInputService, - @ITableService tableService: ITableService + @IComponentContextService componentContextService: IComponentContextService, + @ILogService logService: ILogService ) { 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, tableService); + }, contextMenuService, instantiationService, editorService, untitledEditorService, configurationService, queryModelService, themeService, contextViewService, notificationService, executionPlanService, accessibilityService, quickInputService, componentContextService, contextKeyService, logService); this._gridDataProvider = this.instantiationService.createInstance(QueryGridDataProvider, this._runner, resultSet.batchId, resultSet.id); this.providerId = this._runner.getProviderId(); } @@ -986,7 +1051,7 @@ class GridTable extends GridTableBase { return this._gridDataProvider; } - protected getCurrentActions(): IAction[] { + protected override getActionBarItems(): IAction[] { let actions = []; @@ -998,14 +1063,8 @@ class GridTable extends GridTableBase { } } - actions.push( - this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVECSV_ID, SaveResultAction.SAVECSV_LABEL, SaveResultAction.SAVECSV_ICON, SaveFormat.CSV), - this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEEXCEL_ID, SaveResultAction.SAVEEXCEL_LABEL, SaveResultAction.SAVEEXCEL_ICON, SaveFormat.EXCEL), - this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEJSON_ID, SaveResultAction.SAVEJSON_LABEL, SaveResultAction.SAVEJSON_ICON, SaveFormat.JSON), - this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEMARKDOWN_ID, SaveResultAction.SAVEMARKDOWN_LABEL, SaveResultAction.SAVEMARKDOWN_ICON, SaveFormat.MARKDOWN), - this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEXML_ID, SaveResultAction.SAVEXML_LABEL, SaveResultAction.SAVEXML_ICON, SaveFormat.XML), - this.instantiationService.createInstance(ChartDataAction) - ); + actions.push(super.getActionBarItems()); + actions.push(this.instantiationService.createInstance(ChartDataAction)); if (this.contextKeyService.getContextKeyValue('showVisualizer')) { actions.push(this.instantiationService.createInstance(VisualizerDataAction, this._runner)); @@ -1015,13 +1074,7 @@ class GridTable extends GridTableBase { } protected getContextActions(): IAction[] { - return [ - this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVECSV_ID, SaveResultAction.SAVECSV_LABEL, SaveResultAction.SAVECSV_ICON, SaveFormat.CSV), - this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEEXCEL_ID, SaveResultAction.SAVEEXCEL_LABEL, SaveResultAction.SAVEEXCEL_ICON, SaveFormat.EXCEL), - this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEJSON_ID, SaveResultAction.SAVEJSON_LABEL, SaveResultAction.SAVEJSON_ICON, SaveFormat.JSON), - this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEMARKDOWN_ID, SaveResultAction.SAVEMARKDOWN_LABEL, SaveResultAction.SAVEMARKDOWN_ICON, SaveFormat.MARKDOWN), - this.instantiationService.createInstance(SaveResultAction, SaveResultAction.SAVEXML_ID, SaveResultAction.SAVEXML_LABEL, SaveResultAction.SAVEXML_ICON, SaveFormat.XML), - ]; + return []; } } diff --git a/src/sql/workbench/contrib/query/browser/query.contribution.ts b/src/sql/workbench/contrib/query/browser/query.contribution.ts index 3f8550f305..f8ce9c454e 100644 --- a/src/sql/workbench/contrib/query/browser/query.contribution.ts +++ b/src/sql/workbench/contrib/query/browser/query.contribution.ts @@ -21,8 +21,6 @@ import { RunQueryKeyboardAction, RunCurrentQueryKeyboardAction, CancelQueryKeyboardAction, RefreshIntellisenseKeyboardAction, ToggleQueryResultsKeyboardAction, RunQueryShortcutAction, ToggleActualPlanKeyboardAction, CopyQueryWithResultsKeyboardAction, FocusOnCurrentQueryKeyboardAction, ParseSyntaxAction, ToggleFocusBetweenQueryEditorAndResultsAction, EstimatedExecutionPlanKeyboardAction } from 'sql/workbench/contrib/query/browser/keyboardQueryActions'; -import * as gridActions from 'sql/workbench/contrib/editData/browser/gridActions'; -import * as gridCommands from 'sql/workbench/contrib/editData/browser/gridCommands'; import { localize } from 'vs/nls'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution } from 'vs/workbench/common/contributions'; @@ -40,13 +38,16 @@ import { MssqlNodeContext } from 'sql/workbench/services/objectExplorer/browser/ import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands'; import { ManageActionContext } from 'sql/workbench/browser/actions'; import { ItemContextKey } from 'sql/workbench/contrib/dashboard/browser/widgets/explorer/explorerContext'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { FileEditorInput } from 'vs/workbench/contrib/files/browser/editors/fileEditorInput'; import { IEditorResolverService, RegisteredEditorPriority } from 'vs/workbench/services/editor/common/editorResolverService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { ILogService } from 'vs/platform/log/common/log'; import { ILanguageService } from 'vs/editor/common/languages/language'; +import { IComponentContextService } from 'sql/workbench/services/componentContext/browser/componentContextService'; +import { CopyHeadersAction, CopyResultAction, SaveResultAction } from 'sql/workbench/contrib/query/browser/actions'; +import { InQueryResultGridContextKey } from 'sql/workbench/services/componentContext/browser/contextKeys'; export const QueryEditorVisibleCondition = ContextKeyExpr.has(queryContext.queryEditorVisibleId); export const ResultsGridFocusCondition = ContextKeyExpr.and(ContextKeyExpr.has(queryContext.resultsVisibleId), ContextKeyExpr.has(queryContext.resultsGridFocussedId)); @@ -240,117 +241,87 @@ actionRegistry.registerWorkbenchAction( 'Change Language Flavor' ); +const GridKeyBindingWeight = 900; + +function executeActionOnQueryResultGrid(accessor: ServicesAccessor, actionId: string) { + const componentContextService = accessor.get(IComponentContextService); + const activeGrid = componentContextService.getActiveQueryResultGrid(); + if (activeGrid) { + activeGrid.runAction(actionId); + } +} + KeybindingsRegistry.registerCommandAndKeybindingRule({ - id: gridActions.GRID_COPY_ID, - weight: KeybindingWeight.EditorContrib, - when: ResultsGridFocusCondition, - primary: KeyMod.CtrlCmd | KeyCode.KeyC, - handler: gridCommands.copySelection + id: CopyResultAction.COPYWITHHEADERS_ID, + weight: GridKeyBindingWeight, + primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyC, + when: InQueryResultGridContextKey, + handler: (accessor) => { + executeActionOnQueryResultGrid(accessor, CopyResultAction.COPYWITHHEADERS_ID); + } }); KeybindingsRegistry.registerCommandAndKeybindingRule({ - id: gridActions.MESSAGES_SELECTALL_ID, - weight: KeybindingWeight.EditorContrib, - when: ResultsMessagesFocusCondition, - primary: KeyMod.CtrlCmd | KeyCode.KeyA, - handler: gridCommands.selectAllMessages + id: CopyHeadersAction.ID, + weight: GridKeyBindingWeight, + primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyH, + when: InQueryResultGridContextKey, + handler: (accessor) => { + executeActionOnQueryResultGrid(accessor, CopyHeadersAction.ID); + } }); KeybindingsRegistry.registerCommandAndKeybindingRule({ - id: gridActions.GRID_SELECTALL_ID, - weight: KeybindingWeight.EditorContrib, - when: ResultsGridFocusCondition, - primary: KeyMod.CtrlCmd | KeyCode.KeyA, - handler: gridCommands.selectAll + id: SaveResultAction.SAVECSV_ID, + weight: GridKeyBindingWeight, + when: InQueryResultGridContextKey, + primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyC), + handler: (accessor) => { + executeActionOnQueryResultGrid(accessor, SaveResultAction.SAVECSV_ID); + } }); KeybindingsRegistry.registerCommandAndKeybindingRule({ - id: gridActions.MESSAGES_COPY_ID, - weight: KeybindingWeight.EditorContrib, - when: ResultsMessagesFocusCondition, - primary: KeyMod.CtrlCmd | KeyCode.KeyC, - handler: gridCommands.copyMessagesSelection + id: SaveResultAction.SAVEJSON_ID, + weight: GridKeyBindingWeight, + when: InQueryResultGridContextKey, + primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyJ), + handler: (accessor) => { + executeActionOnQueryResultGrid(accessor, SaveResultAction.SAVEJSON_ID); + } }); KeybindingsRegistry.registerCommandAndKeybindingRule({ - id: gridActions.GRID_SAVECSV_ID, - weight: KeybindingWeight.EditorContrib, - when: ResultsGridFocusCondition, - primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyR, KeyMod.CtrlCmd | KeyCode.KeyC), - handler: gridCommands.saveAsCsv + id: SaveResultAction.SAVEMARKDOWN_ID, + weight: GridKeyBindingWeight, + when: InQueryResultGridContextKey, + primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyM), + handler: (accessor) => { + executeActionOnQueryResultGrid(accessor, SaveResultAction.SAVEMARKDOWN_ID); + } }); KeybindingsRegistry.registerCommandAndKeybindingRule({ - id: gridActions.GRID_SAVEJSON_ID, - weight: KeybindingWeight.EditorContrib, - when: ResultsGridFocusCondition, - primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyR, KeyMod.CtrlCmd | KeyCode.KeyJ), - handler: gridCommands.saveAsJson + id: SaveResultAction.SAVEEXCEL_ID, + weight: GridKeyBindingWeight, + when: InQueryResultGridContextKey, + primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyE), + handler: (accessor) => { + executeActionOnQueryResultGrid(accessor, SaveResultAction.SAVEEXCEL_ID); + } }); KeybindingsRegistry.registerCommandAndKeybindingRule({ - id: gridActions.GRID_SAVEMARKDOWN_ID, - weight: KeybindingWeight.EditorContrib, - when: ResultsGridFocusCondition, - primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyR, KeyMod.CtrlCmd | KeyCode.KeyM), - handler: gridCommands.saveAsMarkdown + id: SaveResultAction.SAVEXML_ID, + weight: GridKeyBindingWeight, + when: InQueryResultGridContextKey, + primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyX), + handler: (accessor) => { + executeActionOnQueryResultGrid(accessor, SaveResultAction.SAVEXML_ID); + } }); -KeybindingsRegistry.registerCommandAndKeybindingRule({ - id: gridActions.GRID_SAVEEXCEL_ID, - weight: KeybindingWeight.EditorContrib, - when: ResultsGridFocusCondition, - primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyR, KeyMod.CtrlCmd | KeyCode.KeyE), - handler: gridCommands.saveAsExcel -}); -KeybindingsRegistry.registerCommandAndKeybindingRule({ - id: gridActions.GRID_SAVEXML_ID, - weight: KeybindingWeight.EditorContrib, - when: ResultsGridFocusCondition, - primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyR, KeyMod.CtrlCmd | KeyCode.KeyX), - handler: gridCommands.saveAsXml -}); - -KeybindingsRegistry.registerCommandAndKeybindingRule({ - id: gridActions.GRID_VIEWASCHART_ID, - weight: KeybindingWeight.EditorContrib, - when: ResultsGridFocusCondition, - primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyR, KeyMod.CtrlCmd | KeyCode.KeyV), - handler: gridCommands.viewAsChart -}); - -KeybindingsRegistry.registerCommandAndKeybindingRule({ - id: gridActions.GRID_GOTONEXTGRID_ID, - weight: KeybindingWeight.EditorContrib, - when: ResultsGridFocusCondition, - primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyR, KeyMod.CtrlCmd | KeyCode.KeyN), - handler: gridCommands.goToNextGrid -}); - -KeybindingsRegistry.registerCommandAndKeybindingRule({ - id: gridActions.TOGGLERESULTS_ID, - weight: KeybindingWeight.EditorContrib, - when: QueryEditorVisibleCondition, - primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyR, - handler: gridCommands.toggleResultsPane -}); - -KeybindingsRegistry.registerCommandAndKeybindingRule({ - id: gridActions.TOGGLEMESSAGES_ID, - weight: KeybindingWeight.EditorContrib, - when: QueryEditorVisibleCondition, - primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyY, - handler: gridCommands.toggleMessagePane -}); - -KeybindingsRegistry.registerCommandAndKeybindingRule({ - id: gridActions.GOTONEXTQUERYOUTPUTTAB_ID, - weight: KeybindingWeight.EditorContrib, - when: QueryEditorVisibleCondition, - primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyP, - handler: gridCommands.goToNextQueryOutputTab -}); export const queryEditorConfigurationBaseNode = Object.freeze({ id: 'queryEditor', diff --git a/src/sql/workbench/contrib/resourceViewer/browser/resourceViewerTable.ts b/src/sql/workbench/contrib/resourceViewer/browser/resourceViewerTable.ts index 016cf7636d..d2581f7e83 100644 --- a/src/sql/workbench/contrib/resourceViewer/browser/resourceViewerTable.ts +++ b/src/sql/workbench/contrib/resourceViewer/browser/resourceViewerTable.ts @@ -27,7 +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'; +import { IComponentContextService } from 'sql/workbench/services/componentContext/browser/componentContextService'; export class ResourceViewerTable extends Disposable { @@ -45,7 +45,7 @@ export class ResourceViewerTable extends Disposable { @IContextViewService private _contextViewService: IContextViewService, @IAccessibilityService private _accessibilityService: IAccessibilityService, @IQuickInputService private _quickInputService: IQuickInputService, - @ITableService private readonly _tableService: ITableService) { + @IComponentContextService private readonly _componentContextService: IComponentContextService) { super(); let filterFn = (data: Array): Array => { return data.filter(item => this.filter(item)); @@ -91,7 +91,7 @@ export class ResourceViewerTable extends Disposable { }); this._resourceViewerTable.registerPlugin(filterPlugin); this._resourceViewerTable.registerPlugin(this._loadingSpinnerPlugin); - this._register(this._tableService.registerTable(this._resourceViewerTable)); + this._register(this._componentContextService.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 index 256a0593a2..a8dc6863f6 100644 --- a/src/sql/workbench/contrib/table/browser/table.contribution.ts +++ b/src/sql/workbench/contrib/table/browser/table.contribution.ts @@ -4,14 +4,14 @@ *--------------------------------------------------------------------------------------------*/ 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 { TableFilteringEnabledContextKey, InTableContextKey } from 'sql/workbench/services/componentContext/browser/contextKeys'; 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'; import { HybridDataProvider } from 'sql/base/browser/ui/table/hybridDataProvider'; +import { IComponentContextService } from 'sql/workbench/services/componentContext/browser/componentContextService'; export const RESIZE_COLUMN_COMMAND_ID = 'table.resizeColumn'; export const SHOW_COLUMN_MENU_COMMAND_ID = 'table.showColumnMenu'; @@ -20,7 +20,7 @@ export const SORT_COLUMN_COMMAND_ID = 'table.sortColumn'; KeybindingsRegistry.registerCommandAndKeybindingRule({ id: RESIZE_COLUMN_COMMAND_ID, weight: KeybindingWeight.WorkbenchContrib, - when: InTable, + when: InTableContextKey, primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KeyS, handler: async (accessor) => { await handleTableCommand(accessor, async (table) => { @@ -32,7 +32,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ KeybindingsRegistry.registerCommandAndKeybindingRule({ id: SHOW_COLUMN_MENU_COMMAND_ID, weight: KeybindingWeight.WorkbenchContrib, - when: ContextKeyExpr.and(InTable, FilteringEnabled), + when: ContextKeyExpr.and(InTableContextKey, TableFilteringEnabledContextKey), primary: KeyCode.F3, handler: async (accessor) => { await handleTableCommand(accessor, async (table) => { @@ -47,7 +47,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ KeybindingsRegistry.registerCommandAndKeybindingRule({ id: SORT_COLUMN_COMMAND_ID, weight: KeybindingWeight.WorkbenchContrib, - when: InTable, + when: InTableContextKey, primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KeyO, handler: async (accessor) => { await handleTableCommand(accessor, async (table) => { @@ -85,8 +85,8 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ }); async function handleTableCommand(accessor: ServicesAccessor, action: (table: Table) => Promise) { - const tableService = accessor.get(ITableService); - const table = tableService.getActiveTable(); + const service = accessor.get(IComponentContextService); + const table = service.getActiveTable(); if (table) { await action(table); } diff --git a/src/sql/workbench/services/componentContext/browser/componentContextService.ts b/src/sql/workbench/services/componentContext/browser/componentContextService.ts new file mode 100644 index 0000000000..631eea418c --- /dev/null +++ b/src/sql/workbench/services/componentContext/browser/componentContextService.ts @@ -0,0 +1,112 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { TableFilteringEnabledContextKey, InTableContextKey, InQueryResultGridContextKey } from 'sql/workbench/services/componentContext/browser/contextKeys'; +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { IDisposable } from 'vs/base/common/lifecycle'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IQueryResultGrid } from 'sql/workbench/contrib/query/browser/gridPanel'; +import { HeaderFilter } from 'sql/base/browser/ui/table/plugins/headerFilter.plugin'; + +export const SERVICE_ID = 'componentContextService'; +export const IComponentContextService = createDecorator(SERVICE_ID); + +export interface ComponentRegistrationResult extends IDisposable { + componentContextKeyService: IContextKeyService; +} + +/** + * Service to register components and find out the active component for keybindings. + */ +export interface IComponentContextService { + _serviceBrand: undefined; + /** + * Register a table + * @param table The table to register + * @param contextKeyService The context key service to use for the table. If not provided, the global context key service will be used. + */ + registerTable(table: Table, contextKeyService?: IContextKeyService): ComponentRegistrationResult; + /** + * Get the table that has the focus. + */ + getActiveTable(): Table | undefined; + + /** + * Register a query result grid + * @param grid The grid to register + * @param contextKeyService The context key service to use for the grid. If not provided, the global context key service will be used. + */ + registerQueryResultGrid(grid: IQueryResultGrid, contextKeyService?: IContextKeyService): ComponentRegistrationResult; + /** + * Get the grid that has the focus. + */ + getActiveQueryResultGrid(): IQueryResultGrid | undefined; +} + +enum ComponentType { + Table = 'Table', + QueryResultGrid = 'QueryResultGrid' +} + +export class ComponentContextService implements IComponentContextService { + _serviceBrand: undefined; + + private _components: Map = new Map(); + private _currentId: number = 1; + + constructor(@IContextKeyService private readonly _contextKeyService: IContextKeyService) { } + + public registerTable(table: Table, contextKeyService?: IContextKeyService): ComponentRegistrationResult { + return this.registerComponent(ComponentType.Table, table, table.grid.getContainerNode(), contextKeyService, (service) => { + InTableContextKey.bindTo(service).set(true); + TableFilteringEnabledContextKey.bindTo(service).set(table.grid.getPlugins().find(p => p instanceof HeaderFilter) !== undefined) + }); + } + + public getActiveTable(): Table | undefined { + return this.getActiveComponent>(ComponentType.Table, (table) => table.grid.getContainerNode()); + } + + public registerQueryResultGrid(grid: IQueryResultGrid, contextKeyService?: IContextKeyService): ComponentRegistrationResult { + return this.registerComponent(ComponentType.QueryResultGrid, grid, grid.htmlElement, contextKeyService, (service) => { + InQueryResultGridContextKey.bindTo(service).set(true); + }); + } + + public getActiveQueryResultGrid(): IQueryResultGrid | undefined { + return this.getActiveComponent(ComponentType.QueryResultGrid, (grid) => grid.htmlElement); + } + + private registerComponent(type: ComponentType, component: any, htmlElement: HTMLElement, contextKeyService: IContextKeyService, contextSetter: (contextKeyService: IContextKeyService) => void): ComponentRegistrationResult { + const parentContextKeyService = contextKeyService ?? this._contextKeyService; + const id = this._currentId++; + this._components.set(id, { type, component }); + const service = parentContextKeyService.createScoped(htmlElement); + contextSetter(service); + return { + componentContextKeyService: service, + dispose: () => { + this._components.delete(id); + service.dispose(); + } + }; + } + + /** + * Get the component that has the focus. + * @param type type of the component to look for. + * @param elementGetter function to get the html element of the component. + * @returns the component that has the focus or undefined if no component has the focus. + */ + private getActiveComponent(type: ComponentType, elementGetter: (component: T) => HTMLElement): T | undefined { + for (const item of this._components.values()) { + if (item.type === type && elementGetter(item.component).contains(document.activeElement)) { + return item.component; + } + } + return undefined; + } +} diff --git a/src/sql/workbench/services/componentContext/browser/contextKeys.ts b/src/sql/workbench/services/componentContext/browser/contextKeys.ts new file mode 100644 index 0000000000..b92081e54b --- /dev/null +++ b/src/sql/workbench/services/componentContext/browser/contextKeys.ts @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; + +// Table +export const InTableContextKey = new RawContextKey('inTable', true); +export const TableFilteringEnabledContextKey = new RawContextKey('filteringEnabled', false); + +// Query Result Grid +export const InQueryResultGridContextKey = new RawContextKey('inQueryResultGrid', true); diff --git a/src/sql/workbench/services/insights/browser/insightsDialogView.ts b/src/sql/workbench/services/insights/browser/insightsDialogView.ts index 0be66761b4..7addc9780e 100644 --- a/src/sql/workbench/services/insights/browser/insightsDialogView.ts +++ b/src/sql/workbench/services/insights/browser/insightsDialogView.ts @@ -53,7 +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'; +import { IComponentContextService } from 'sql/workbench/services/componentContext/browser/componentContextService'; const labelDisplay = nls.localize("insights.item", "Item"); const valueDisplay = nls.localize("insights.value", "Value"); @@ -92,7 +92,7 @@ class InsightTableView extends ViewPane { @ITelemetryService telemetryService: ITelemetryService, @IAccessibilityService private _accessibilityService: IAccessibilityService, @IQuickInputService private _quickInputService: IQuickInputService, - @ITableService private readonly _tableService: ITableService + @IComponentContextService private readonly _componentContextService: IComponentContextService ) { super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService); } @@ -102,7 +102,7 @@ class InsightTableView extends ViewPane { columns: this.columns, dataProvider: this.data }, this.tableOptions); - this._register(this._tableService.registerTable(this._table)); + this._register(this._componentContextService.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 2d523d8ca1..b778c74ba6 100644 --- a/src/sql/workbench/services/restore/browser/restoreDialog.ts +++ b/src/sql/workbench/services/restore/browser/restoreDialog.ts @@ -50,7 +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'; +import { IComponentContextService } from 'sql/workbench/services/componentContext/browser/componentContextService'; interface FileListElement { logicalFileName: string; @@ -163,7 +163,7 @@ export class RestoreDialog extends Modal { @ITextResourcePropertiesService textResourcePropertiesService: ITextResourcePropertiesService, @IAccessibilityService private _accessibilityService: IAccessibilityService, @IQuickInputService private _quickInputService: IQuickInputService, - @ITableService private readonly _tableService: ITableService + @IComponentContextService private readonly _componentContextService: IComponentContextService ) { super(localize('RestoreDialogTitle', "Restore database"), TelemetryKeys.ModalDialogName.Restore, telemetryService, layoutService, clipboardService, themeService, logService, textResourcePropertiesService, contextKeyService, { hasErrors: true, width: 'wide', hasSpinner: true }); // view model @@ -319,7 +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)); + this._register(this._componentContextService.registerTable(this._restorePlanTable)); // Content in general tab const generalTab = DOM.$('.restore-dialog'); @@ -369,7 +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)); + this._register(this._componentContextService.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 deleted file mode 100644 index 6d02d909e0..0000000000 --- a/src/sql/workbench/services/table/browser/tableContext.ts +++ /dev/null @@ -1,27 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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 deleted file mode 100644 index 97b38f4738..0000000000 --- a/src/sql/workbench/services/table/browser/tableService.ts +++ /dev/null @@ -1,61 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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/vs/workbench/workbench.common.main.ts b/src/vs/workbench/workbench.common.main.ts index 4e3996129c..e2e988e8d6 100644 --- a/src/vs/workbench/workbench.common.main.ts +++ b/src/vs/workbench/workbench.common.main.ts @@ -222,7 +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'; +import { IComponentContextService, ComponentContextService } from 'sql/workbench/services/componentContext/browser/componentContextService'; registerSingleton(IDashboardService, DashboardService); registerSingleton(IDashboardViewService, DashboardViewService); @@ -267,7 +267,7 @@ registerSingleton(IDataGridProviderService, DataGridProviderService); registerSingleton(ITableDesignerService, TableDesignerService); registerSingleton(IExecutionPlanService, ExecutionPlanService); registerSingleton(IErrorDiagnosticsService, ErrorDiagnosticsService); -registerSingleton(ITableService, TableService); +registerSingleton(IComponentContextService, ComponentContextService); //#endregion