From 4823a768332a4c2b3e5c7a619f85e7c2be391bba Mon Sep 17 00:00:00 2001 From: Aasim Khan Date: Wed, 2 Nov 2022 15:11:16 -0700 Subject: [PATCH] Adding screen reader optimized mode to slickgrid (#21069) --- package.json | 2 +- remote/package.json | 2 +- remote/web/package.json | 2 +- remote/web/yarn.lock | 6 +++--- remote/yarn.lock | 6 +++--- .../browser/ui/accessibility/accessibilityProvider.ts | 8 ++++++++ src/sql/base/browser/ui/table/table.ts | 7 ++++++- src/sql/base/browser/ui/table/treeGrid.ts | 5 +++-- src/sql/workbench/browser/designer/designer.ts | 6 ++++-- .../browser/modelComponents/table.component.ts | 6 ++++-- .../assessment/browser/asmtResultsView.component.ts | 6 ++++-- .../workbench/contrib/charts/browser/tableInsight.ts | 6 ++++-- .../browser/widgets/explorer/explorerTable.ts | 6 ++++-- .../widgets/explorer/explorerWidget.component.ts | 5 ++++- .../widgets/insights/views/tableInsight.component.ts | 6 ++++-- .../contrib/editData/browser/editDataGridPanel.ts | 8 +++++--- .../browser/executionPlanComparisonPropertiesView.ts | 6 ++++-- .../browser/executionPlanPropertiesView.ts | 6 ++++-- .../browser/executionPlanPropertiesViewBase.ts | 6 ++++-- .../executionPlan/browser/executionPlanTreeTab.ts | 6 ++++-- .../contrib/executionPlan/browser/topOperationsTab.ts | 6 ++++-- .../jobManagement/browser/alertsView.component.ts | 6 ++++-- .../jobManagement/browser/jobsView.component.ts | 6 ++++-- .../jobManagement/browser/notebooksView.component.ts | 5 +++-- .../jobManagement/browser/operatorsView.component.ts | 6 ++++-- .../jobManagement/browser/proxiesView.component.ts | 6 ++++-- .../notebook/browser/models/outputProcessor.ts | 1 + .../notebook/browser/outputs/gridOutput.component.ts | 6 ++++-- .../contrib/profiler/browser/profilerEditor.ts | 6 ++++-- .../contrib/profiler/browser/profilerTableEditor.ts | 6 ++++-- src/sql/workbench/contrib/query/browser/gridPanel.ts | 11 +++++++---- .../resourceViewer/browser/resourceViewerTable.ts | 6 ++++-- .../services/insights/browser/insightsDialogView.ts | 4 +++- .../services/notebook/browser/outputs/mimemodel.ts | 9 +++++++++ .../notebook/browser/outputs/renderMimeInterfaces.ts | 3 +++ .../notebook/browser/outputs/tableRenderers.ts | 8 +++++++- .../services/notebook/browser/outputs/widgets.ts | 3 ++- .../services/restore/browser/restoreDialog.ts | 8 +++++--- .../modalComponents/table.component.test.ts | 8 ++++---- src/typings/slickgrid.d.ts | 7 +++++++ yarn.lock | 6 +++--- 41 files changed, 165 insertions(+), 73 deletions(-) create mode 100644 src/sql/base/browser/ui/accessibility/accessibilityProvider.ts diff --git a/package.json b/package.json index a6c373548a..329d688440 100755 --- a/package.json +++ b/package.json @@ -102,7 +102,7 @@ "rxjs": "5.4.0", "sanitize-html": "1.19.1", "semver-umd": "^5.5.7", - "slickgrid": "github:Microsoft/SlickGrid.ADS#2.3.38", + "slickgrid": "github:Microsoft/SlickGrid.ADS#2.3.39", "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 89d353195a..983aafa4a7 100755 --- a/remote/package.json +++ b/remote/package.json @@ -42,7 +42,7 @@ "sanitize-html": "1.19.1", "semver-umd": "^5.5.7", "spdlog": "^0.13.0", - "slickgrid": "github:Microsoft/SlickGrid.ADS#2.3.38", + "slickgrid": "github:Microsoft/SlickGrid.ADS#2.3.39", "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 2f1fa1663d..b53532b4a1 100755 --- a/remote/web/package.json +++ b/remote/web/package.json @@ -30,7 +30,7 @@ "rxjs": "5.4.0", "sanitize-html": "1.19.1", "semver-umd": "^5.5.7", - "slickgrid": "github:Microsoft/SlickGrid.ADS#2.3.38", + "slickgrid": "github:Microsoft/SlickGrid.ADS#2.3.39", "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 b962b17200..11d0b82e79 100644 --- a/remote/web/yarn.lock +++ b/remote/web/yarn.lock @@ -416,9 +416,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.38": - version "2.3.38" - resolved "https://codeload.github.com/Microsoft/SlickGrid.ADS/tar.gz/da030666877487c7407db928be3a28b5ce3668a2" +"slickgrid@github:Microsoft/SlickGrid.ADS#2.3.39": + version "2.3.39" + resolved "https://codeload.github.com/Microsoft/SlickGrid.ADS/tar.gz/4ead9291ec4aab107767940ab0a6eac1455e0627" source-map@^0.6.1: version "0.6.1" diff --git a/remote/yarn.lock b/remote/yarn.lock index 2b77952597..70b2cb45cd 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -878,9 +878,9 @@ simple-get@^4.0.0: once "^1.3.1" simple-concat "^1.0.0" -"slickgrid@github:Microsoft/SlickGrid.ADS#2.3.38": - version "2.3.38" - resolved "https://codeload.github.com/Microsoft/SlickGrid.ADS/tar.gz/da030666877487c7407db928be3a28b5ce3668a2" +"slickgrid@github:Microsoft/SlickGrid.ADS#2.3.39": + version "2.3.39" + resolved "https://codeload.github.com/Microsoft/SlickGrid.ADS/tar.gz/4ead9291ec4aab107767940ab0a6eac1455e0627" smart-buffer@^4.2.0: version "4.2.0" diff --git a/src/sql/base/browser/ui/accessibility/accessibilityProvider.ts b/src/sql/base/browser/ui/accessibility/accessibilityProvider.ts new file mode 100644 index 0000000000..283a31d807 --- /dev/null +++ b/src/sql/base/browser/ui/accessibility/accessibilityProvider.ts @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export interface IAccessibilityProvider { + isScreenReaderOptimized(): boolean; +} diff --git a/src/sql/base/browser/ui/table/table.ts b/src/sql/base/browser/ui/table/table.ts index 98162d76c1..2f0b11f5c4 100644 --- a/src/sql/base/browser/ui/table/table.ts +++ b/src/sql/base/browser/ui/table/table.ts @@ -20,6 +20,7 @@ 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 { IAccessibilityProvider } from 'sql/base/browser/ui/accessibility/accessibilityProvider'; function getDefaultOptions(): Slick.GridOptions { return >{ @@ -65,7 +66,7 @@ export class Table extends Widget implements IDisposa private _onBlur = new Emitter(); public readonly onBlur = this._onBlur.event; - constructor(parent: HTMLElement, configuration?: ITableConfiguration, options?: Slick.GridOptions) { + constructor(parent: HTMLElement, accessibilityProvider: IAccessibilityProvider, configuration?: ITableConfiguration, options?: Slick.GridOptions) { super(); if (!configuration || !configuration.dataProvider || isArray(configuration.dataProvider)) { this._data = new TableDataView(configuration && configuration.dataProvider as Array); @@ -77,6 +78,10 @@ export class Table extends Widget implements IDisposa let newOptions = mixin(options || {}, getDefaultOptions(), false); + if (accessibilityProvider?.isScreenReaderOptimized()) { + newOptions.disableColumnBasedCellVirtualization = true; + } + this._container = document.createElement('div'); this._container.className = 'monaco-table'; this._register(DOM.addDisposableListener(this._container, DOM.EventType.FOCUS, (e: FocusEvent) => { diff --git a/src/sql/base/browser/ui/table/treeGrid.ts b/src/sql/base/browser/ui/table/treeGrid.ts index f15d78455b..2177c10631 100644 --- a/src/sql/base/browser/ui/table/treeGrid.ts +++ b/src/sql/base/browser/ui/table/treeGrid.ts @@ -15,6 +15,7 @@ import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; import { createTreeGridExpandableColumnFormatter, textFormatter } from 'sql/base/browser/ui/table/formatters'; import { escape } from 'sql/base/common/strings'; +import { IAccessibilityProvider } from 'sql/base/browser/ui/accessibility/accessibilityProvider'; function defaultTreeGridFilter(data: T[], columns: FilterableColumn[], cellValueGetter: CellValueGetter = defaultCellValueGetter): T[] { let filteredData = defaultFilter(data, columns, cellValueGetter); @@ -38,8 +39,8 @@ function defaultTreeGridFilter(data: T[], columns: Fi * TreeGrid component displays a hierarchical table data grouped into expandable and collapsible nodes. */ export class TreeGrid extends Table { - constructor(parent: HTMLElement, configuration?: ITableConfiguration, options?: Slick.GridOptions) { - super(parent, configuration, options); + constructor(parent: HTMLElement, accessibilityProvider: IAccessibilityProvider, configuration?: ITableConfiguration, options?: Slick.GridOptions) { + super(parent, accessibilityProvider, configuration, options); this._tableContainer.setAttribute('role', 'treegrid'); if (configuration?.dataProvider && configuration.dataProvider instanceof TableDataView) { this._data = configuration.dataProvider; diff --git a/src/sql/workbench/browser/designer/designer.ts b/src/sql/workbench/browser/designer/designer.ts index 7d8173d8f3..0aa520310d 100644 --- a/src/sql/workbench/browser/designer/designer.ts +++ b/src/sql/workbench/browser/designer/designer.ts @@ -53,6 +53,7 @@ import { RowSelectionModel } from 'sql/base/browser/ui/table/plugins/rowSelectio import { listFocusAndSelectionBackground } from 'sql/platform/theme/common/colors'; import { timeout } from 'vs/base/common/async'; import { onUnexpectedError } from 'vs/base/common/errors'; +import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; export interface IDesignerStyle { tabbedPanelStyles?: ITabbedPanelStyles; @@ -113,7 +114,8 @@ export class Designer extends Disposable implements IThemable { @INotificationService private readonly _notificationService: INotificationService, @IDialogService private readonly _dialogService: IDialogService, @IThemeService private readonly _themeService: IThemeService, - @IContextMenuService private readonly _contextMenuService: IContextMenuService,) { + @IContextMenuService private readonly _contextMenuService: IContextMenuService, + @IAccessibilityService private readonly _accessibilityService: IAccessibilityService) { super(); this._tableCellEditorFactory = new TableCellEditorFactory( { @@ -843,7 +845,7 @@ export class Designer extends Disposable implements IThemable { const tableProperties = componentDefinition.componentProperties as DesignerTableProperties; const taskbar = this.addTableTaskbar(container, tableProperties); const tableContainer = container.appendChild(DOM.$('.full-row')); - const table = new Table(tableContainer, { + const table = new Table(tableContainer, this._accessibilityService, { dataProvider: new TableDataView() }, { editable: true, diff --git a/src/sql/workbench/browser/modelComponents/table.component.ts b/src/sql/workbench/browser/modelComponents/table.component.ts index c42a54ff91..8426f54b62 100644 --- a/src/sql/workbench/browser/modelComponents/table.component.ts +++ b/src/sql/workbench/browser/modelComponents/table.component.ts @@ -39,6 +39,7 @@ import { ContextMenuColumn, ContextMenuCellValue } from 'sql/base/browser/ui/tab import { IAction, Separator } from 'vs/base/common/actions'; 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'; export enum ColumnSizingMode { ForceFit = 0, // all columns will be sized to fit in viewable space, no horiz scroll bar @@ -90,7 +91,8 @@ export default class TableComponent extends ComponentBase(this._inputContainer.nativeElement, { dataProvider: this._tableData, columns: this._tableColumns }, options); + this._table = new Table(this._inputContainer.nativeElement, this.accessibilityService, { dataProvider: this._tableData, columns: this._tableColumns }, options); this._table.setData(this._tableData); this._table.setSelectionModel(new RowSelectionModel({ selectActiveRow: true })); diff --git a/src/sql/workbench/contrib/assessment/browser/asmtResultsView.component.ts b/src/sql/workbench/contrib/assessment/browser/asmtResultsView.component.ts index 4342e40ff1..8be187f2c3 100644 --- a/src/sql/workbench/contrib/assessment/browser/asmtResultsView.component.ts +++ b/src/sql/workbench/contrib/assessment/browser/asmtResultsView.component.ts @@ -48,6 +48,7 @@ import { ConnectionManagementInfo } from 'sql/platform/connection/common/connect import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { attachTableFilterStyler } from 'sql/platform/theme/common/styler'; import { DASHBOARD_BORDER } from 'sql/workbench/common/theme'; +import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; export const ASMTRESULTSVIEW_SELECTOR: string = 'asmt-results-view-component'; export const ROW_HEIGHT: number = 25; @@ -144,7 +145,8 @@ export class AsmtResultsViewComponent extends TabChild implements IAssessmentCom @Inject(IDashboardService) _dashboardService: IDashboardService, @Inject(IAdsTelemetryService) private _telemetryService: IAdsTelemetryService, @Inject(ILogService) protected _logService: ILogService, - @Inject(IContextViewService) private _contextViewService: IContextViewService + @Inject(IContextViewService) private _contextViewService: IContextViewService, + @Inject(IAccessibilityService) private _accessibilityService: IAccessibilityService ) { super(); let self = this; @@ -352,7 +354,7 @@ export class AsmtResultsViewComponent extends TabChild implements IAssessmentCom this.initActionBar(databaseInvokeAsmt, databaseSelectAsmt); } - this._table = this._register(new Table(this._gridEl.nativeElement, { columns }, options)); + this._table = this._register(new Table(this._gridEl.nativeElement, this._accessibilityService, { columns }, options)); this._table.grid.setData(this.dataView, true); this._table.registerPlugin(this.rowDetail); this._table.registerPlugin(filterPlugin); diff --git a/src/sql/workbench/contrib/charts/browser/tableInsight.ts b/src/sql/workbench/contrib/charts/browser/tableInsight.ts index c2389296fa..0ba9b8f61d 100644 --- a/src/sql/workbench/contrib/charts/browser/tableInsight.ts +++ b/src/sql/workbench/contrib/charts/browser/tableInsight.ts @@ -14,6 +14,7 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IInsightOptions, InsightType } from 'sql/workbench/contrib/charts/common/interfaces'; import { IInsightData } from 'sql/platform/dashboard/browser/insightRegistry'; +import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; export class TableInsight extends Disposable implements IInsight { public static readonly types = [InsightType.Table]; @@ -25,7 +26,8 @@ export class TableInsight extends Disposable implements IInsight { public options: IInsightOptions = { type: InsightType.Table }; constructor(container: HTMLElement, options: any, - @IThemeService themeService: IThemeService + @IThemeService themeService: IThemeService, + @IAccessibilityService accessibilityService: IAccessibilityService ) { super(); let tableContainer = $('div'); @@ -33,7 +35,7 @@ export class TableInsight extends Disposable implements IInsight { tableContainer.style.height = '100%'; container.appendChild(tableContainer); this.dataView = new TableDataView(); - this.table = new Table(tableContainer, { dataProvider: this.dataView }, { showRowNumber: true }); + this.table = new Table(tableContainer, accessibilityService, { dataProvider: this.dataView }, { showRowNumber: true }); this.table.setSelectionModel(new CellSelectionModel()); this._register(attachTableStyler(this.table, themeService)); } 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 c5e9bd3105..9cbc3daa7b 100644 --- a/src/sql/workbench/contrib/dashboard/browser/widgets/explorer/explorerTable.ts +++ b/src/sql/workbench/contrib/dashboard/browser/widgets/explorer/explorerTable.ts @@ -26,6 +26,7 @@ import { IAction } from 'vs/base/common/actions'; import { onUnexpectedError } from 'vs/base/common/errors'; import { Disposable } from 'vs/base/common/lifecycle'; import * as nls from 'vs/nls'; +import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { IMenuService, MenuId } from 'vs/platform/actions/common/actions'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; @@ -63,7 +64,8 @@ export class ExplorerTable extends Disposable { private readonly contextKeyService: IContextKeyService, private readonly progressService: IEditorProgressService, private readonly logService: ILogService, - private readonly dashboardService: IDashboardService) { + private readonly dashboardService: IDashboardService, + readonly accessibilityService: IAccessibilityService) { super(); this._explorerView = new ExplorerView(this.context); const connectionInfo = this.bootStrapService.connectionManagementService.connectionInfo; @@ -72,7 +74,7 @@ export class ExplorerTable extends Disposable { this._view = new TableDataView(undefined, undefined, undefined, (data: Slick.SlickData[]): Slick.SlickData[] => { return explorerFilter.filter(this._filterStr, data); }); - this._table = new Table(parentElement, { dataProvider: this._view }, { forceFitColumns: true }); + this._table = new Table(parentElement, accessibilityService, { dataProvider: this._view }, { forceFitColumns: true }); this._table.setSelectionModel(new RowSelectionModel()); this._actionsColumn = new ButtonColumn({ id: 'actions', 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 44b0c622f2..4f1bdb51df 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 @@ -31,6 +31,7 @@ import { attachInputBoxStyler } from 'vs/platform/theme/common/styler'; import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService'; import { getFlavor } from 'sql/workbench/contrib/dashboard/browser/dashboardRegistry'; import { IDashboardService } from 'sql/platform/dashboard/browser/dashboardService'; +import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; @Component({ selector: 'explorer-widget', @@ -60,6 +61,7 @@ export class ExplorerWidget extends DashboardWidget implements IDashboardWidget, @Inject(IConnectionManagementService) private readonly connectionManagementService: IConnectionManagementService, @Inject(ICapabilitiesService) private readonly capabilitiesService: ICapabilitiesService, @Inject(IDashboardService) private readonly dashboardService: IDashboardService, + @Inject(IAccessibilityService) private readonly accessibilityService: IAccessibilityService, @Inject(forwardRef(() => ChangeDetectorRef)) changeRef: ChangeDetectorRef ) { super(changeRef); @@ -92,7 +94,8 @@ export class ExplorerWidget extends DashboardWidget implements IDashboardWidget, this.contextKeyService, this.progressService, this.logService, - this.dashboardService); + this.dashboardService, + this.accessibilityService); 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 1319a9f4c6..6ed8ecace3 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 @@ -14,6 +14,7 @@ import { TableDataView } from 'sql/base/browser/ui/table/tableDataView'; import { attachTableStyler } from 'sql/platform/theme/common/styler'; import { CellSelectionModel } from 'sql/base/browser/ui/table/plugins/cellSelectionModel.plugin'; import { IInsightsView, IInsightData } from 'sql/platform/dashboard/browser/insightRegistry'; +import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; @Component({ template: '' @@ -25,7 +26,8 @@ export default class TableInsight extends Disposable implements IInsightsView, O constructor( @Inject(forwardRef(() => ElementRef)) private _elementRef: ElementRef, - @Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService + @Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService, + @Inject(IAccessibilityService) private accessibilityService: IAccessibilityService ) { super(); } @@ -61,7 +63,7 @@ export default class TableInsight extends Disposable implements IInsightsView, O private createTable() { if (!this.table) { - this.table = new Table(this._elementRef.nativeElement, { dataProvider: this.dataView, columns: this.columns }, { showRowNumber: true }); + this.table = new Table(this._elementRef.nativeElement, this.accessibilityService, { dataProvider: this.dataView, columns: this.columns }, { showRowNumber: true }); this.table.setSelectionModel(new CellSelectionModel()); this._register(attachTableStyler(this.table, this.themeService)); } diff --git a/src/sql/workbench/contrib/editData/browser/editDataGridPanel.ts b/src/sql/workbench/contrib/editData/browser/editDataGridPanel.ts index 295f66a46e..6126f88bcd 100644 --- a/src/sql/workbench/contrib/editData/browser/editDataGridPanel.ts +++ b/src/sql/workbench/contrib/editData/browser/editDataGridPanel.ts @@ -35,6 +35,7 @@ import { Event } from 'vs/base/common/event'; import { equals } from 'vs/base/common/arrays'; import * as DOM from 'vs/base/browser/dom'; import { onUnexpectedError } from 'vs/base/common/errors'; +import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; export class EditDataGridPanel extends GridParentComponent { // The time(in milliseconds) we wait before refreshing the grid. @@ -105,7 +106,8 @@ export class EditDataGridPanel extends GridParentComponent { @IConfigurationService configurationService: IConfigurationService, @IClipboardService clipboardService: IClipboardService, @IQueryEditorService queryEditorService: IQueryEditorService, - @ILogService logService: ILogService + @ILogService logService: ILogService, + @IAccessibilityService private accessibilityService: IAccessibilityService ) { super(contextMenuService, keybindingService, contextKeyService, configurationService, clipboardService, queryEditorService, logService); this.nativeElement = document.createElement('div'); @@ -893,7 +895,7 @@ export class EditDataGridPanel extends GridParentComponent { }; if (dataSet.columnDefinitions) { - this.table = new Table(this.nativeElement.appendChild(newGridContainer), { dataProvider: this.gridDataProvider, columns: dataSet.columnDefinitions }, options); + this.table = new Table(this.nativeElement.appendChild(newGridContainer), this.accessibilityService, { dataProvider: this.gridDataProvider, columns: dataSet.columnDefinitions }, options); for (let plugin of this.plugins) { this.table.registerPlugin(plugin); } @@ -903,7 +905,7 @@ export class EditDataGridPanel extends GridParentComponent { } } else { - this.table = new Table(this.nativeElement.appendChild(newGridContainer)); + this.table = new Table(this.nativeElement.appendChild(newGridContainer), this.accessibilityService); } } diff --git a/src/sql/workbench/contrib/executionPlan/browser/executionPlanComparisonPropertiesView.ts b/src/sql/workbench/contrib/executionPlan/browser/executionPlanComparisonPropertiesView.ts index aff0afd87d..d1c6f049f4 100644 --- a/src/sql/workbench/contrib/executionPlan/browser/executionPlanComparisonPropertiesView.ts +++ b/src/sql/workbench/contrib/executionPlan/browser/executionPlanComparisonPropertiesView.ts @@ -18,6 +18,7 @@ import { IContextMenuService, IContextViewService } from 'vs/platform/contextvie import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { Codicon } from 'vs/base/common/codicons'; import { deepClone } from 'vs/base/common/objects'; +import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; export enum ExecutionPlanCompareOrientation { Horizontal = 'horizontal', @@ -62,9 +63,10 @@ export class ExecutionPlanComparisonPropertiesView extends ExecutionPlanProperti @IThemeService themeService: IThemeService, @IInstantiationService instantiationService: IInstantiationService, @IContextMenuService contextMenuService: IContextMenuService, - @IContextViewService contextViewService: IContextViewService + @IContextViewService contextViewService: IContextViewService, + @IAccessibilityService accessibilityService: IAccessibilityService ) { - super(parentContainer, themeService, instantiationService, contextMenuService, contextViewService); + super(parentContainer, themeService, instantiationService, contextMenuService, contextViewService, accessibilityService); 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 50323acfd8..f8e0983f17 100644 --- a/src/sql/workbench/contrib/executionPlan/browser/executionPlanPropertiesView.ts +++ b/src/sql/workbench/contrib/executionPlan/browser/executionPlanPropertiesView.ts @@ -13,6 +13,7 @@ import { textFormatter } from 'sql/base/browser/ui/table/formatters'; import { ExecutionPlanPropertiesViewBase, PropertiesSortType } from 'sql/workbench/contrib/executionPlan/browser/executionPlanPropertiesViewBase'; import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; export class ExecutionPlanPropertiesView extends ExecutionPlanPropertiesViewBase { // Div that holds the name of the element selected @@ -24,9 +25,10 @@ export class ExecutionPlanPropertiesView extends ExecutionPlanPropertiesViewBase @IThemeService themeService: IThemeService, @IInstantiationService instantiationService: IInstantiationService, @IContextMenuService contextMenuService: IContextMenuService, - @IContextViewService contextViewService: IContextViewService + @IContextViewService contextViewService: IContextViewService, + @IAccessibilityService accessibilityService: IAccessibilityService ) { - super(parentContainer, themeService, instantiationService, contextMenuService, contextViewService); + super(parentContainer, themeService, instantiationService, contextMenuService, contextViewService, accessibilityService); 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 5cb5146a75..222146b313 100644 --- a/src/sql/workbench/contrib/executionPlan/browser/executionPlanPropertiesViewBase.ts +++ b/src/sql/workbench/contrib/executionPlan/browser/executionPlanPropertiesViewBase.ts @@ -25,6 +25,7 @@ import { CopyKeybind } from 'sql/base/browser/ui/table/plugins/copyKeybind.plugi import { InputBox } from 'sql/base/browser/ui/inputBox/inputBox'; import { deepClone } from 'vs/base/common/objects'; import { Disposable } from 'vs/base/common/lifecycle'; +import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; export abstract class ExecutionPlanPropertiesViewBase extends Disposable implements IVerticalSashLayoutProvider { // Title bar with close button action @@ -67,7 +68,8 @@ export abstract class ExecutionPlanPropertiesViewBase extends Disposable impleme private _themeService: IThemeService, @IInstantiationService private _instantiationService: IInstantiationService, @IContextMenuService private _contextMenuService: IContextMenuService, - @IContextViewService private _contextViewService: IContextViewService + @IContextViewService private _contextViewService: IContextViewService, + @IAccessibilityService accessibilityService: IAccessibilityService ) { super(); const sashContainer = DOM.$('.properties-sash'); @@ -155,7 +157,7 @@ export abstract class ExecutionPlanPropertiesViewBase extends Disposable impleme this._selectionModel = new CellSelectionModel(); - this._tableComponent = this._register(new TreeGrid(table, { + this._tableComponent = this._register(new TreeGrid(table, accessibilityService, { columns: [] }, { rowHeight: RESULTS_GRID_DEFAULTS.rowHeight, diff --git a/src/sql/workbench/contrib/executionPlan/browser/executionPlanTreeTab.ts b/src/sql/workbench/contrib/executionPlan/browser/executionPlanTreeTab.ts index 3b68845744..438cabbb13 100644 --- a/src/sql/workbench/contrib/executionPlan/browser/executionPlanTreeTab.ts +++ b/src/sql/workbench/contrib/executionPlan/browser/executionPlanTreeTab.ts @@ -24,6 +24,7 @@ import { ExecutionPlanViewHeader } from 'sql/workbench/contrib/executionPlan/bro import { CopyKeybind } from 'sql/base/browser/ui/table/plugins/copyKeybind.plugin'; import { Disposable } from 'vs/base/common/lifecycle'; import { deepClone } from 'vs/base/common/objects'; +import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; export class ExecutionPlanTreeTab extends Disposable implements IPanelTab { public readonly title: string = localize('planTreeTab.title', 'Plan Tree'); @@ -51,7 +52,8 @@ export class ExecutionPlanTreeTabView extends Disposable implements IPanelView { constructor( @IThemeService private _themeService: IThemeService, @IInstantiationService private _instantiationService: IInstantiationService, - @IContextMenuService private _contextMenuService: IContextMenuService + @IContextMenuService private _contextMenuService: IContextMenuService, + @IAccessibilityService private accessibilityService: IAccessibilityService ) { super(); } @@ -192,7 +194,7 @@ export class ExecutionPlanTreeTabView extends Disposable implements IPanelView { const selectionModel = new CellSelectionModel(); - const treeGrid = this._register(new TreeGrid(tableContainer, { + const treeGrid = this._register(new TreeGrid(tableContainer, this.accessibilityService, { columns: columns, sorter: (args) => { const sortColumn = args.sortCol.field; diff --git a/src/sql/workbench/contrib/executionPlan/browser/topOperationsTab.ts b/src/sql/workbench/contrib/executionPlan/browser/topOperationsTab.ts index 5cff4ea0cb..2555d2dfcb 100644 --- a/src/sql/workbench/contrib/executionPlan/browser/topOperationsTab.ts +++ b/src/sql/workbench/contrib/executionPlan/browser/topOperationsTab.ts @@ -30,6 +30,7 @@ import { ITableKeyboardEvent } from 'sql/base/browser/ui/table/interfaces'; import { Disposable } from 'vs/base/common/lifecycle'; 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'; const TABLE_SORT_COLUMN_KEY = 'tableCostColumnForSorting'; @@ -61,7 +62,8 @@ export class TopOperationsTabView extends Disposable implements IPanelView { @IThemeService private _themeService: IThemeService, @IInstantiationService private _instantiationService: IInstantiationService, @IContextMenuService private _contextMenuService: IContextMenuService, - @IContextViewService private _contextViewService: IContextViewService + @IContextViewService private _contextViewService: IContextViewService, + @IAccessibilityService private _accessibilityService: IAccessibilityService ) { super(); } @@ -236,7 +238,7 @@ export class TopOperationsTabView extends Disposable implements IPanelView { const selectionModel = new CellSelectionModel({ hasRowSelector: true }); - const table = this._register(new Table(tableContainer, { + const table = this._register(new Table(tableContainer, this._accessibilityService, { columns: columns, sorter: (args) => { const column = args.sortCol.field; diff --git a/src/sql/workbench/contrib/jobManagement/browser/alertsView.component.ts b/src/sql/workbench/contrib/jobManagement/browser/alertsView.component.ts index b49894a04b..aa036acb59 100644 --- a/src/sql/workbench/contrib/jobManagement/browser/alertsView.component.ts +++ b/src/sql/workbench/contrib/jobManagement/browser/alertsView.component.ts @@ -24,6 +24,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IDashboardService } from 'sql/platform/dashboard/browser/dashboardService'; import { AlertsCacheObject } from 'sql/workbench/services/jobManagement/common/jobManagementService'; import { RowDetailView } from 'sql/base/browser/ui/table/plugins/rowDetailView'; +import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; export const VIEW_SELECTOR: string = 'jobalertsview-component'; export const ROW_HEIGHT: number = 45; @@ -76,7 +77,8 @@ export class AlertsViewComponent extends JobManagementView implements OnInit, On @Inject(forwardRef(() => CommonServiceInterface)) commonService: CommonServiceInterface, @Inject(IContextMenuService) contextMenuService: IContextMenuService, @Inject(IKeybindingService) keybindingService: IKeybindingService, - @Inject(IDashboardService) _dashboardService: IDashboardService) { + @Inject(IDashboardService) _dashboardService: IDashboardService, + @Inject(IAccessibilityService) private _accessibilityService: IAccessibilityService) { super(commonService, _dashboardService, contextMenuService, keybindingService, instantiationService, _agentViewComponent); this._didTabChange = false; this._isCloud = commonService.connectionManagementService.connectionInfo.serverInfo.isCloud; @@ -143,7 +145,7 @@ export class AlertsViewComponent extends JobManagementView implements OnInit, On jQuery(this.actionBarContainer.nativeElement).empty(); this.initActionBar(); - this._table = new Table(this._gridEl.nativeElement, { columns }, this.options); + this._table = new Table(this._gridEl.nativeElement, this._accessibilityService, { columns }, this.options); 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 0f74780e45..3c44cc0a4c 100644 --- a/src/sql/workbench/contrib/jobManagement/browser/jobsView.component.ts +++ b/src/sql/workbench/contrib/jobManagement/browser/jobsView.component.ts @@ -34,6 +34,7 @@ import { IColorTheme } from 'vs/platform/theme/common/themeService'; import { onUnexpectedError } from 'vs/base/common/errors'; import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry'; import { attachTableFilterStyler } from 'sql/platform/theme/common/styler'; +import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; export const JOBSVIEW_SELECTOR: string = 'jobsview-component'; export const ROW_HEIGHT: number = 45; @@ -108,7 +109,8 @@ export class JobsViewComponent extends JobManagementView implements OnInit, OnDe @Inject(IKeybindingService) keybindingService: IKeybindingService, @Inject(IDashboardService) _dashboardService: IDashboardService, @Inject(IAdsTelemetryService) private _telemetryService: IAdsTelemetryService, - @Inject(IContextViewService) private _contextViewService: IContextViewService + @Inject(IContextViewService) private _contextViewService: IContextViewService, + @Inject(IAccessibilityService) private _accessibilityService: IAccessibilityService ) { super(commonService, _dashboardService, contextMenuService, keybindingService, instantiationService, _agentViewComponent); let jobCacheObjectMap = this._jobManagementService.jobCacheObjectMap; @@ -188,7 +190,7 @@ export class JobsViewComponent extends JobManagementView implements OnInit, OnDe jQuery(this._gridEl.nativeElement).empty(); jQuery(this.actionBarContainer.nativeElement).empty(); this.initActionBar(); - this._table = new Table(this._gridEl.nativeElement, { columns }, options); + this._table = new Table(this._gridEl.nativeElement, this._accessibilityService, { columns }, options); this._table.grid.setData(this.dataView, true); this._table.grid.onClick.subscribe((e, args) => { let job = self.getJob(args); diff --git a/src/sql/workbench/contrib/jobManagement/browser/notebooksView.component.ts b/src/sql/workbench/contrib/jobManagement/browser/notebooksView.component.ts index a5bf296584..29f21c9cbd 100644 --- a/src/sql/workbench/contrib/jobManagement/browser/notebooksView.component.ts +++ b/src/sql/workbench/contrib/jobManagement/browser/notebooksView.component.ts @@ -35,6 +35,7 @@ import { onUnexpectedError } from 'vs/base/common/errors'; import { IColorTheme } from 'vs/platform/theme/common/themeService'; import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry'; import { attachTableFilterStyler } from 'sql/platform/theme/common/styler'; +import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; export const NOTEBOOKSVIEW_SELECTOR: string = 'notebooksview-component'; @@ -108,7 +109,7 @@ export class NotebooksViewComponent extends JobManagementView implements OnInit, @Inject(IDashboardService) _dashboardService: IDashboardService, @Inject(IAdsTelemetryService) private _telemetryService: IAdsTelemetryService, @Inject(IContextViewService) private _contextViewService: IContextViewService, - + @Inject(IAccessibilityService) private _accessibilityService: IAccessibilityService ) { super(commonService, _dashboardService, contextMenuService, keybindingService, instantiationService, _agentViewComponent); let notebookCacheObjectMap = this._jobManagementService.notebookCacheObjectMap; @@ -188,7 +189,7 @@ export class NotebooksViewComponent extends JobManagementView implements OnInit, jQuery(this._gridEl.nativeElement).empty(); jQuery(this.actionBarContainer.nativeElement).empty(); this.initActionBar(); - this._table = this._register(new Table(this._gridEl.nativeElement, { columns }, options)); + this._table = this._register(new Table(this._gridEl.nativeElement, this._accessibilityService, { columns }, options)); this._table.grid.setData(this.dataView, true); this._table.grid.onClick.subscribe((e, args) => { let notebook = self.getNotebook(args); diff --git a/src/sql/workbench/contrib/jobManagement/browser/operatorsView.component.ts b/src/sql/workbench/contrib/jobManagement/browser/operatorsView.component.ts index d2ee7c1a75..0795513f3b 100644 --- a/src/sql/workbench/contrib/jobManagement/browser/operatorsView.component.ts +++ b/src/sql/workbench/contrib/jobManagement/browser/operatorsView.component.ts @@ -24,6 +24,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IDashboardService } from 'sql/platform/dashboard/browser/dashboardService'; import { OperatorsCacheObject } from 'sql/workbench/services/jobManagement/common/jobManagementService'; import { RowDetailView } from 'sql/base/browser/ui/table/plugins/rowDetailView'; +import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; export const VIEW_SELECTOR: string = 'joboperatorsview-component'; export const ROW_HEIGHT: number = 45; @@ -75,7 +76,8 @@ export class OperatorsViewComponent extends JobManagementView implements OnInit, @Inject(forwardRef(() => CommonServiceInterface)) commonService: CommonServiceInterface, @Inject(IContextMenuService) contextMenuService: IContextMenuService, @Inject(IKeybindingService) keybindingService: IKeybindingService, - @Inject(IDashboardService) _dashboardService: IDashboardService + @Inject(IDashboardService) _dashboardService: IDashboardService, + @Inject(IAccessibilityService) private _accessibilityService: IAccessibilityService ) { super(commonService, _dashboardService, contextMenuService, keybindingService, instantiationService, _agentViewComponent); this._isCloud = commonService.connectionManagementService.connectionInfo.serverInfo.isCloud; @@ -143,7 +145,7 @@ export class OperatorsViewComponent extends JobManagementView implements OnInit, jQuery(this._gridEl.nativeElement).empty(); jQuery(this.actionBarContainer.nativeElement).empty(); this.initActionBar(); - this._table = new Table(this._gridEl.nativeElement, { columns }, this.options); + this._table = new Table(this._gridEl.nativeElement, this._accessibilityService, { columns }, this.options); this._table.grid.setData(this.dataView, true); this._register(this._table.onContextMenu(e => { diff --git a/src/sql/workbench/contrib/jobManagement/browser/proxiesView.component.ts b/src/sql/workbench/contrib/jobManagement/browser/proxiesView.component.ts index 42a49fda95..5265974136 100644 --- a/src/sql/workbench/contrib/jobManagement/browser/proxiesView.component.ts +++ b/src/sql/workbench/contrib/jobManagement/browser/proxiesView.component.ts @@ -24,6 +24,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IDashboardService } from 'sql/platform/dashboard/browser/dashboardService'; import { ProxiesCacheObject } from 'sql/workbench/services/jobManagement/common/jobManagementService'; import { RowDetailView } from 'sql/base/browser/ui/table/plugins/rowDetailView'; +import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; export const VIEW_SELECTOR: string = 'jobproxiesview-component'; export const ROW_HEIGHT: number = 45; @@ -76,7 +77,8 @@ export class ProxiesViewComponent extends JobManagementView implements OnInit, O @Inject(forwardRef(() => CommonServiceInterface)) commonService: CommonServiceInterface, @Inject(IContextMenuService) contextMenuService: IContextMenuService, @Inject(IKeybindingService) keybindingService: IKeybindingService, - @Inject(IDashboardService) _dashboardService: IDashboardService + @Inject(IDashboardService) _dashboardService: IDashboardService, + @Inject(IAccessibilityService) private _accessibilityService: IAccessibilityService ) { super(commonService, _dashboardService, contextMenuService, keybindingService, instantiationService, _agentViewComponent); this._isCloud = commonService.connectionManagementService.connectionInfo.serverInfo.isCloud; @@ -143,7 +145,7 @@ export class ProxiesViewComponent extends JobManagementView implements OnInit, O jQuery(this._gridEl.nativeElement).empty(); jQuery(this.actionBarContainer.nativeElement).empty(); this.initActionBar(); - this._table = new Table(this._gridEl.nativeElement, { columns }, this.options); + this._table = new Table(this._gridEl.nativeElement, this._accessibilityService, { columns }, this.options); this._table.grid.setData(this.dataView, true); this._register(this._table.onContextMenu(e => { diff --git a/src/sql/workbench/contrib/notebook/browser/models/outputProcessor.ts b/src/sql/workbench/contrib/notebook/browser/models/outputProcessor.ts index b505393d9a..2042e20f8f 100644 --- a/src/sql/workbench/contrib/notebook/browser/models/outputProcessor.ts +++ b/src/sql/workbench/contrib/notebook/browser/models/outputProcessor.ts @@ -73,6 +73,7 @@ export function getBundleOptions(options: IOutputModelOptions): MimeModel.IOptio let data = getData(options.value); let metadata = getMetadata(options.value); let trusted = !!options.trusted; + return { data, metadata, trusted }; } 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 c1cb449f3c..466b8b5de8 100644 --- a/src/sql/workbench/contrib/notebook/browser/outputs/gridOutput.component.ts +++ b/src/sql/workbench/contrib/notebook/browser/outputs/gridOutput.component.ts @@ -49,6 +49,7 @@ import * as TelemetryKeys from 'sql/platform/telemetry/common/telemetryKeys'; import { IExecutionPlanService } from 'sql/workbench/services/executionPlan/common/interfaces'; import { ITextResourcePropertiesService } from 'vs/editor/common/services/textResourceConfiguration'; import { mssqlProviderName } from 'sql/platform/connection/common/constants'; +import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; @Component({ selector: GridOutputComponent.SELECTOR, @@ -240,12 +241,13 @@ class DataResourceTable extends GridTableBase { @IThemeService themeService: IThemeService, @IContextViewService contextViewService: IContextViewService, @INotificationService notificationService: INotificationService, - @IExecutionPlanService executionPlanService: IExecutionPlanService + @IExecutionPlanService executionPlanService: IExecutionPlanService, + @IAccessibilityService accessibilityService: IAccessibilityService, ) { super(state, createResultSet(source), { actionOrientation: ActionsOrientation.HORIZONTAL, inMemoryDataProcessing: true - }, contextMenuService, instantiationService, editorService, untitledEditorService, configurationService, queryModelService, themeService, contextViewService, notificationService, executionPlanService); + }, contextMenuService, instantiationService, editorService, untitledEditorService, configurationService, queryModelService, themeService, contextViewService, notificationService, executionPlanService, accessibilityService); 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 bc108eeaf5..e34f0016e5 100644 --- a/src/sql/workbench/contrib/profiler/browser/profilerEditor.ts +++ b/src/sql/workbench/contrib/profiler/browser/profilerEditor.ts @@ -54,6 +54,7 @@ import { IEditorOptions } from 'vs/platform/editor/common/editor'; import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; 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'; class BasicView implements IView { public get element(): HTMLElement { @@ -171,7 +172,8 @@ export class ProfilerEditor extends EditorPane { @IStorageService storageService: IStorageService, @IClipboardService private _clipboardService: IClipboardService, @ITextResourcePropertiesService private readonly textResourcePropertiesService: ITextResourcePropertiesService, - @IEditorGroupsService editorGroupsService: IEditorGroupsService + @IEditorGroupsService editorGroupsService: IEditorGroupsService, + @IAccessibilityService private readonly _accessibilityService: IAccessibilityService ) { super(ProfilerEditor.ID, telemetryService, themeService, storageService); this._profilerEditorContextKey = CONTEXT_PROFILER_EDITOR.bindTo(this._contextKeyService); @@ -387,7 +389,7 @@ export class ProfilerEditor extends EditorPane { detailTableContainer.style.width = '100%'; detailTableContainer.style.height = '100%'; this._detailTableData = new TableDataView(); - this._detailTable = new Table(detailTableContainer, { + this._detailTable = new Table(detailTableContainer, this._accessibilityService, { dataProvider: this._detailTableData, columns: [ { id: 'label', diff --git a/src/sql/workbench/contrib/profiler/browser/profilerTableEditor.ts b/src/sql/workbench/contrib/profiler/browser/profilerTableEditor.ts index 24e08ed4c8..0fab132421 100644 --- a/src/sql/workbench/contrib/profiler/browser/profilerTableEditor.ts +++ b/src/sql/workbench/contrib/profiler/browser/profilerTableEditor.ts @@ -33,6 +33,7 @@ import { IClipboardService } from 'sql/platform/clipboard/common/clipboardServic import { handleCopyRequest } from 'sql/workbench/contrib/profiler/browser/profilerCopyHandler'; import { ITextResourcePropertiesService } from 'vs/editor/common/services/textResourceConfiguration'; import { FindReplaceState, FindReplaceStateChangedEvent } from 'vs/editor/contrib/find/browser/findState'; +import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; export interface ProfilerTableViewState { scrollTop: number; @@ -68,7 +69,8 @@ export class ProfilerTableEditor extends EditorPane implements IProfilerControll @IStorageService storageService: IStorageService, @IStatusbarService private _statusbarService: IStatusbarService, @IClipboardService private _clipboardService: IClipboardService, - @ITextResourcePropertiesService private readonly textResourcePropertiesService: ITextResourcePropertiesService + @ITextResourcePropertiesService private readonly textResourcePropertiesService: ITextResourcePropertiesService, + @IAccessibilityService private readonly _accessibilityService: IAccessibilityService ) { super(ProfilerTableEditor.ID, telemetryService, _themeService, storageService); this._actionMap[ACTION_IDS.FIND_NEXT] = this._instantiationService.createInstance(ProfilerFindNext, this); @@ -84,7 +86,7 @@ export class ProfilerTableEditor extends EditorPane implements IProfilerControll this._overlay.style.zIndex = '4'; parent.appendChild(this._overlay); - this._profilerTable = new Table(parent, { + this._profilerTable = new Table(parent, this._accessibilityService, { sorter: (args) => { let input = this.input as ProfilerInput; if (input && input.data) { diff --git a/src/sql/workbench/contrib/query/browser/gridPanel.ts b/src/sql/workbench/contrib/query/browser/gridPanel.ts index 2ca0a2c720..35f83b4cf3 100644 --- a/src/sql/workbench/contrib/query/browser/gridPanel.ts +++ b/src/sql/workbench/contrib/query/browser/gridPanel.ts @@ -54,6 +54,7 @@ import { IExecutionPlanService } from 'sql/workbench/services/executionPlan/comm import { ExecutionPlanInput } from 'sql/workbench/contrib/executionPlan/common/executionPlanInput'; import { CopyAction } from 'vs/editor/contrib/clipboard/browser/clipboard'; import { formatDocumentWithSelectedProvider, FormattingMode } from 'vs/editor/contrib/format/browser/format'; +import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; const ROW_HEIGHT = 29; const HEADER_HEIGHT = 26; @@ -407,7 +408,8 @@ export abstract class GridTableBase extends Disposable implements IView { @IThemeService private readonly themeService: IThemeService, @IContextViewService private readonly contextViewService: IContextViewService, @INotificationService private readonly notificationService: INotificationService, - @IExecutionPlanService private readonly executionPlanService: IExecutionPlanService + @IExecutionPlanService private readonly executionPlanService: IExecutionPlanService, + @IAccessibilityService private readonly accessibilityService: IAccessibilityService ) { super(); @@ -522,7 +524,7 @@ export abstract class GridTableBase extends Disposable implements IView { inMemoryDataProcessing: this.options.inMemoryDataProcessing, inMemoryDataCountThreshold: this.options.inMemoryDataCountThreshold }); - this.table = this._register(new Table(this.tableContainer, { dataProvider: this.dataProvider, columns: this.columns }, tableOptions)); + this.table = this._register(new Table(this.tableContainer, this.accessibilityService, { dataProvider: this.dataProvider, columns: this.columns }, tableOptions)); this.table.setTableTitle(localize('resultsGrid', "Results grid")); this.table.setSelectionModel(this.selectionModel); this.table.registerPlugin(new MouseWheelSupport()); @@ -921,14 +923,15 @@ class GridTable extends GridTableBase { @IThemeService themeService: IThemeService, @IContextViewService contextViewService: IContextViewService, @INotificationService notificationService: INotificationService, - @IExecutionPlanService executionPlanService: IExecutionPlanService + @IExecutionPlanService executionPlanService: IExecutionPlanService, + @IAccessibilityService accessibilityService: IAccessibilityService ) { super(state, resultSet, { actionOrientation: ActionsOrientation.VERTICAL, inMemoryDataProcessing: true, showActionBar: true, inMemoryDataCountThreshold: configurationService.getValue('queryEditor').results.inMemoryDataProcessingThreshold, - }, contextMenuService, instantiationService, editorService, untitledEditorService, configurationService, queryModelService, themeService, contextViewService, notificationService, executionPlanService); + }, contextMenuService, instantiationService, editorService, untitledEditorService, configurationService, queryModelService, themeService, contextViewService, notificationService, executionPlanService, accessibilityService); 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 d00abacb4b..03178b4935 100644 --- a/src/sql/workbench/contrib/resourceViewer/browser/resourceViewerTable.ts +++ b/src/sql/workbench/contrib/resourceViewer/browser/resourceViewerTable.ts @@ -25,6 +25,7 @@ import { Emitter } from 'vs/base/common/event'; import { ContextMenuAnchor } from 'sql/workbench/contrib/resourceViewer/browser/resourceViewerEditor'; import { LoadingSpinnerPlugin } from 'sql/base/browser/ui/table/plugins/loadingSpinner.plugin'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; +import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; export class ResourceViewerTable extends Disposable { @@ -39,14 +40,15 @@ export class ResourceViewerTable extends Disposable { @IOpenerService private _openerService: IOpenerService, @ICommandService private _commandService: ICommandService, @INotificationService private _notificationService: INotificationService, - @IContextViewService private _contextViewService: IContextViewService) { + @IContextViewService private _contextViewService: IContextViewService, + @IAccessibilityService private _accessibilityService: IAccessibilityService) { super(); let filterFn = (data: Array): Array => { return data.filter(item => this.filter(item)); }; this._dataView = new TableDataView(undefined, undefined, undefined, filterFn); - this._resourceViewerTable = this._register(new Table(parent, { + this._resourceViewerTable = this._register(new Table(parent, this._accessibilityService, { sorter: (args) => { this._dataView.sort(args); } diff --git a/src/sql/workbench/services/insights/browser/insightsDialogView.ts b/src/sql/workbench/services/insights/browser/insightsDialogView.ts index 7682df4433..ba900d15ea 100644 --- a/src/sql/workbench/services/insights/browser/insightsDialogView.ts +++ b/src/sql/workbench/services/insights/browser/insightsDialogView.ts @@ -51,6 +51,7 @@ import { IInsightsConfigDetails } from 'sql/platform/extensions/common/extension import { attachButtonStyler } from 'vs/platform/theme/common/styler'; import { IDisposableDataProvider } from 'sql/base/common/dataProvider'; import { ITextResourcePropertiesService } from 'vs/editor/common/services/textResourceConfiguration'; +import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; const labelDisplay = nls.localize("insights.item", "Item"); const valueDisplay = nls.localize("insights.value", "Value"); @@ -87,12 +88,13 @@ class InsightTableView extends ViewPane { @IOpenerService openerService: IOpenerService, @IThemeService themeService: IThemeService, @ITelemetryService telemetryService: ITelemetryService, + @IAccessibilityService private _accessibilityService: IAccessibilityService ) { super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService); } protected override renderBody(container: HTMLElement): void { - this._table = new Table(container, { + this._table = new Table(container, this._accessibilityService, { columns: this.columns, dataProvider: this.data }, this.tableOptions); diff --git a/src/sql/workbench/services/notebook/browser/outputs/mimemodel.ts b/src/sql/workbench/services/notebook/browser/outputs/mimemodel.ts index adbcfd0aa7..4222350fe6 100644 --- a/src/sql/workbench/services/notebook/browser/outputs/mimemodel.ts +++ b/src/sql/workbench/services/notebook/browser/outputs/mimemodel.ts @@ -5,6 +5,7 @@ import { IRenderMime } from 'sql/workbench/services/notebook/browser/outputs/renderMimeInterfaces'; import { ReadonlyJSONObject } from 'sql/workbench/services/notebook/common/jsonext'; +import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IThemeService } from 'vs/platform/theme/common/themeService'; /** @@ -20,6 +21,7 @@ export class MimeModel implements IRenderMime.IMimeModel { this._metadata = options.metadata || {}; this._callback = options.callback; this._themeService = options.themeService; + this._accessibilityService = options.accessibilityService; } /** @@ -45,6 +47,10 @@ export class MimeModel implements IRenderMime.IMimeModel { return this._themeService; } + get accessibilityService(): IAccessibilityService { + return this._accessibilityService; + } + /** * Set the data associated with the model. * @@ -62,6 +68,7 @@ export class MimeModel implements IRenderMime.IMimeModel { private _data: ReadonlyJSONObject; private _metadata: ReadonlyJSONObject; private _themeService: IThemeService; + private _accessibilityService: IAccessibilityService; } /** @@ -96,5 +103,7 @@ export namespace MimeModel { * Theme service used to react to theme change events */ themeService?: IThemeService; + + accessibilityService?: IAccessibilityService; } } diff --git a/src/sql/workbench/services/notebook/browser/outputs/renderMimeInterfaces.ts b/src/sql/workbench/services/notebook/browser/outputs/renderMimeInterfaces.ts index 0b7b203b6e..8882935451 100644 --- a/src/sql/workbench/services/notebook/browser/outputs/renderMimeInterfaces.ts +++ b/src/sql/workbench/services/notebook/browser/outputs/renderMimeInterfaces.ts @@ -4,6 +4,7 @@ |----------------------------------------------------------------------------*/ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { ReadonlyJSONObject } from 'sql/workbench/services/notebook/common/jsonext'; +import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; /** * A namespace for rendermime associated interfaces. @@ -42,6 +43,8 @@ export namespace IRenderMime { * Theme service used to react to theme change events */ readonly themeService: IThemeService; + + readonly accessibilityService: IAccessibilityService; } /** diff --git a/src/sql/workbench/services/notebook/browser/outputs/tableRenderers.ts b/src/sql/workbench/services/notebook/browser/outputs/tableRenderers.ts index ac1f2e7941..20bd104cf5 100644 --- a/src/sql/workbench/services/notebook/browser/outputs/tableRenderers.ts +++ b/src/sql/workbench/services/notebook/browser/outputs/tableRenderers.ts @@ -16,6 +16,7 @@ import { AutoColumnSize } from 'sql/base/browser/ui/table/plugins/autoSizeColumn import { AdditionalKeyBindings } from 'sql/base/browser/ui/table/plugins/additionalKeyBindings.plugin'; import { RESULTS_GRID_DEFAULTS } from 'sql/workbench/common/constants'; import { values } from 'vs/base/common/collections'; +import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; /** * Render DataResource as a grid into a host node. @@ -55,7 +56,7 @@ export function renderDataResource( let transformedData = transformData(sourceObject.data, columnsTransformed); tableResultsData.push(transformedData); - let detailTable = new Table(tableContainer, { + let detailTable = new Table(tableContainer, options.accessibilityService, { dataProvider: tableResultsData, columns: columnsTransformed }, { rowHeight: RESULTS_GRID_DEFAULTS.rowHeight, @@ -135,5 +136,10 @@ export namespace renderDataResource { * Theme service used to react to theme change events */ themeService?: IThemeService; + + /** + * Accessibility service used to get screen reader optimization flag state + */ + accessibilityService: IAccessibilityService; } } diff --git a/src/sql/workbench/services/notebook/browser/outputs/widgets.ts b/src/sql/workbench/services/notebook/browser/outputs/widgets.ts index 667021724b..1af9b5ae1a 100644 --- a/src/sql/workbench/services/notebook/browser/outputs/widgets.ts +++ b/src/sql/workbench/services/notebook/browser/outputs/widgets.ts @@ -401,7 +401,8 @@ export class RenderedDataResource extends RenderedCommon { return tableRenderers.renderDataResource({ host: this.node, source: JSON.stringify(model.data[this.mimeType]), - themeService: model.themeService + themeService: model.themeService, + accessibilityService: model.accessibilityService }); } } diff --git a/src/sql/workbench/services/restore/browser/restoreDialog.ts b/src/sql/workbench/services/restore/browser/restoreDialog.ts index ee52bb0d54..c37b8df4d5 100644 --- a/src/sql/workbench/services/restore/browser/restoreDialog.ts +++ b/src/sql/workbench/services/restore/browser/restoreDialog.ts @@ -48,6 +48,7 @@ import { Dropdown } from 'sql/base/browser/ui/editableDropdown/browser/dropdown' import { IBackupRestoreUrlBrowserDialogService } from 'sql/workbench/services/backupRestoreUrlBrowser/common/urlBrowserDialogService'; 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'; interface FileListElement { logicalFileName: string; @@ -157,7 +158,8 @@ export class RestoreDialog extends Modal { @IBackupRestoreUrlBrowserDialogService private backupRestoreUrlBrowserDialogService: IBackupRestoreUrlBrowserDialogService, @IClipboardService clipboardService: IClipboardService, @ILogService logService: ILogService, - @ITextResourcePropertiesService textResourcePropertiesService: ITextResourcePropertiesService + @ITextResourcePropertiesService textResourcePropertiesService: ITextResourcePropertiesService, + @IAccessibilityService private _accessibilityService: IAccessibilityService ) { super(localize('RestoreDialogTitle', "Restore database"), TelemetryKeys.ModalDialogName.Restore, telemetryService, layoutService, clipboardService, themeService, logService, textResourcePropertiesService, contextKeyService, { hasErrors: true, width: 'wide', hasSpinner: true }); // view model @@ -308,7 +310,7 @@ export class RestoreDialog extends Modal { this._restorePlanTableContainer = DOM.append(restorePlanElement, DOM.$('.dialog-input-section.restore-list')); DOM.hide(this._restorePlanTableContainer); this._restorePlanData = new TableDataView(); - this._restorePlanTable = this._register(new Table(this._restorePlanTableContainer, + this._restorePlanTable = this._register(new Table(this._restorePlanTableContainer, this._accessibilityService, { dataProvider: this._restorePlanData, columns: this._restorePlanColumn }, { enableColumnReorder: false })); this._restorePlanTable.setTableTitle(localize('restorePlan', "Restore plan")); this._restorePlanTable.setSelectionModel(new RowSelectionModel({ selectActiveRow: false })); @@ -359,7 +361,7 @@ export class RestoreDialog extends Modal { field: 'restoreAs' }]; this._fileListData = new TableDataView(); - this._fileListTable = this._register(new Table(this._fileListTableContainer, + this._fileListTable = this._register(new Table(this._fileListTableContainer, this._accessibilityService, { dataProvider: this._fileListData, columns }, { enableColumnReorder: false })); this._fileListTable.setSelectionModel(new RowSelectionModel()); 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 3d2fdf9bf7..c0778d6159 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); + const tableComponent = new TableComponent(undefined, undefined, undefined, new NullLogService(), 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); + const tableComponent = new TableComponent(undefined, undefined, undefined, new NullLogService(), 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); + const tableComponent = new TableComponent(undefined, undefined, undefined, new NullLogService(), 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); + const tableComponent = new TableComponent(undefined, undefined, undefined, new NullLogService(), 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 0b9eec1145..9a68e3ba3f 100644 --- a/src/typings/slickgrid.d.ts +++ b/src/typings/slickgrid.d.ts @@ -673,6 +673,13 @@ declare namespace Slick { * */ minRowBuffer?: number; + + /** + * Disable dom virtualization based on visible columns. When true, the grid will render all columns, even if they are not visible. + * This is a mitigation for screen reader issues not announcing column number of visible cells properly. + * Link to the accessibility issue: https://github.com/microsoft/azuredatastudio/issues/20784 + */ + disableColumnBasedCellVirtualization?: boolean; } export interface DataProvider { diff --git a/yarn.lock b/yarn.lock index b084007f93..780598faf0 100755 --- a/yarn.lock +++ b/yarn.lock @@ -9500,9 +9500,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.38": - version "2.3.38" - resolved "https://codeload.github.com/Microsoft/SlickGrid.ADS/tar.gz/da030666877487c7407db928be3a28b5ce3668a2" +"slickgrid@github:Microsoft/SlickGrid.ADS#2.3.39": + version "2.3.39" + resolved "https://codeload.github.com/Microsoft/SlickGrid.ADS/tar.gz/4ead9291ec4aab107767940ab0a6eac1455e0627" smart-buffer@^4.2.0: version "4.2.0"