fix slickgrid keyboard event handler (#23575)

* fix slickgrid keyboard events

* add back some code
This commit is contained in:
Alan Ren
2023-06-29 17:11:51 -07:00
committed by GitHub
parent f6500febb2
commit f9be3a9ac8
10 changed files with 66 additions and 59 deletions

View File

@@ -118,3 +118,10 @@ export function trapKeyboardNavigation(container: HTMLElement): IDisposable {
}
});
}
/**
* Convert the SlickGrid's keydown event to VSCode standard keyboard event.
*/
export function convertJQueryKeyDownEvent(e: DOMEvent): StandardKeyboardEvent {
return new StandardKeyboardEvent((<any>e as JQuery.KeyDownEvent).originalEvent);
}

View File

@@ -3,6 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { convertJQueryKeyDownEvent } from 'sql/base/browser/dom';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
@@ -15,40 +16,39 @@ export class AdditionalKeyBindings<T> implements Slick.Plugin<T> {
public init(grid: Slick.Grid<T>) {
this.grid = grid;
this.handler.subscribe(this.grid.onKeyDown, (e: DOMEvent, args) => this.handleKeyDown(e as KeyboardEvent, args));
this.handler.subscribe(this.grid.onKeyDown, (e: DOMEvent, args) => this.handleKeyDown(convertJQueryKeyDownEvent(e), args));
}
public destroy() {
this.handler.unsubscribeAll();
}
private handleKeyDown(e: KeyboardEvent, args: Slick.OnKeyDownEventArgs<T>): void {
let event = new StandardKeyboardEvent(e);
private handleKeyDown(e: StandardKeyboardEvent, args: Slick.OnKeyDownEventArgs<T>): void {
let handled = true;
if (event.equals(KeyCode.RightArrow | KeyMod.CtrlCmd)) {
if (e.equals(KeyCode.RightArrow | KeyMod.CtrlCmd)) {
this.grid.setActiveCell(args.row, this.grid.getColumns().length - 1);
} else if (event.equals(KeyCode.LeftArrow | KeyMod.CtrlCmd)) {
} else if (e.equals(KeyCode.LeftArrow | KeyMod.CtrlCmd)) {
// account for row column
if (this.grid.canCellBeActive(args.row, 0)) {
this.grid.setActiveCell(args.row, 0);
} else {
this.grid.setActiveCell(args.row, 1);
}
} else if (event.equals(KeyCode.UpArrow | KeyMod.CtrlCmd)) {
} else if (e.equals(KeyCode.UpArrow | KeyMod.CtrlCmd)) {
this.grid.setActiveCell(0, args.cell);
} else if (event.equals(KeyCode.DownArrow | KeyMod.CtrlCmd)) {
} else if (e.equals(KeyCode.DownArrow | KeyMod.CtrlCmd)) {
this.grid.setActiveCell(this.grid.getDataLength() - 1, args.cell);
} else if (event.equals(KeyCode.Home | KeyMod.CtrlCmd)) {
} else if (e.equals(KeyCode.Home | KeyMod.CtrlCmd)) {
// account for row column
if (this.grid.canCellBeActive(0, 0)) {
this.grid.setActiveCell(0, 0);
} else {
this.grid.setActiveCell(0, 1);
}
} else if (event.equals(KeyCode.End | KeyMod.CtrlCmd)) {
} else if (e.equals(KeyCode.End | KeyMod.CtrlCmd)) {
this.grid.setActiveCell(this.grid.getDataLength() - 1, this.grid.getColumns().length - 1);
} else if (event.equals(KeyCode.KeyA | KeyMod.CtrlCmd)) {
} else if (e.equals(KeyCode.KeyA | KeyMod.CtrlCmd)) {
// check if we can set the rows directly on the selectionModel, its cleaner
let selectionModel = this.grid.getSelectionModel();
if (selectionModel) {
@@ -61,7 +61,7 @@ export class AdditionalKeyBindings<T> implements Slick.Plugin<T> {
if (handled) {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
e.browserEvent.stopImmediatePropagation();
}
}

View File

@@ -6,6 +6,9 @@ import { isUndefinedOrNull } from 'vs/base/common/types';
import * as platform from 'vs/base/common/platform';
import { CellRangeSelector, ICellRangeSelector } from 'sql/base/browser/ui/table/plugins/cellRangeSelector';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode } from 'vs/base/common/keyCodes';
import { convertJQueryKeyDownEvent } from 'sql/base/browser/dom';
export interface ICellSelectionModelOptions {
cellRangeSelector?: any;
@@ -37,14 +40,14 @@ export class CellSelectionModel<T> implements Slick.SelectionModel<T, Array<Slic
if (this.options.cellRangeSelector) {
this.selector = this.options.cellRangeSelector;
} else {
// this is added by the noderequires above
// this is added by the node requires above
this.selector = new CellRangeSelector({ selectionCss: { 'border': '2px dashed grey' } });
}
}
public init(grid: Slick.Grid<T>) {
this.grid = grid;
this._handler.subscribe(this.grid.onKeyDown, (e: DOMEvent) => this.handleKeyDown(e as KeyboardEvent));
this._handler.subscribe(this.grid.onKeyDown, (e: DOMEvent) => this.handleKeyDown(convertJQueryKeyDownEvent(e)));
this._handler.subscribe(this.grid.onAfterKeyboardNavigation, (e: Event) => this.handleAfterKeyboardNavigationEvent());
this._handler.subscribe(this.grid.onClick, (e: DOMEvent, args: Slick.OnClickEventArgs<T>) => this.handleCellClick(e as MouseEvent, args));
this._handler.subscribe(this.grid.onHeaderClick, (e: DOMEvent, args: Slick.OnHeaderClickEventArgs<T>) => this.handleHeaderClick(e as MouseEvent, args));
@@ -273,19 +276,12 @@ export class CellSelectionModel<T> implements Slick.SelectionModel<T, Array<Slic
this.grid.setActiveCell(newActiveCell.row, newActiveCell.cell);
}
private handleKeyDown(e: KeyboardEvent) {
/*
* Key codes
* 37 left
* 38 up
* 39 right
* 40 down
*/
private handleKeyDown(e: StandardKeyboardEvent) {
let active = this.grid.getActiveCell();
let metaKey = e.ctrlKey || e.metaKey;
if (active && e.shiftKey && !metaKey && !e.altKey &&
(e.which === 37 || e.which === 39 || e.which === 38 || e.which === 40)) {
(e.keyCode === KeyCode.LeftArrow || e.keyCode === KeyCode.RightArrow || e.keyCode === KeyCode.UpArrow || e.keyCode === KeyCode.DownArrow)) {
let ranges = this.getSelectedRanges(), last: Slick.Range;
ranges = this.getSelectedRanges();
@@ -307,13 +303,13 @@ export class CellSelectionModel<T> implements Slick.SelectionModel<T, Array<Slic
dirRow = active.row === last.fromRow ? 1 : -1,
dirCell = active.cell === last.fromCell ? 1 : -1;
if (e.which === 37) {
if (e.keyCode === KeyCode.LeftArrow) {
dCell -= dirCell;
} else if (e.which === 39) {
} else if (e.keyCode === KeyCode.RightArrow) {
dCell += dirCell;
} else if (e.which === 38) {
} else if (e.keyCode === KeyCode.UpArrow) {
dRow -= dirRow;
} else if (e.which === 40) {
} else if (e.keyCode === KeyCode.DownArrow) {
dRow += dirRow;
}

View File

@@ -9,6 +9,7 @@ import { escape } from 'sql/base/common/strings';
import { Emitter } from 'vs/base/common/event';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode } from 'vs/base/common/keyCodes';
import { convertJQueryKeyDownEvent } from 'sql/base/browser/dom';
export interface CheckBoxCellValue {
enabled?: boolean;
@@ -38,7 +39,7 @@ export class CheckBoxColumn<T extends Slick.SlickData> implements Slick.Plugin<T
public init(grid: Slick.Grid<T>): void {
this._grid = grid;
this._handler.subscribe(grid.onClick, (e: DOMEvent, args: Slick.OnClickEventArgs<T>) => this.handleClick(args));
this._handler.subscribe(grid.onKeyDown, (e: DOMEvent, args: Slick.OnKeyDownEventArgs<T>) => this.handleKeyboardEvent(e as KeyboardEvent, args));
this._handler.subscribe(grid.onKeyDown, (e: DOMEvent, args: Slick.OnKeyDownEventArgs<T>) => this.handleKeyboardEvent(convertJQueryKeyDownEvent(e), args));
this._handler.subscribe(grid.onActiveCellChanged, (e: DOMEvent, args: Slick.OnActiveCellChangedEventArgs<T>) => { this.handleActiveCellChanged(args); });
}
@@ -82,9 +83,8 @@ export class CheckBoxColumn<T extends Slick.SlickData> implements Slick.Plugin<T
}
}
private handleKeyboardEvent(e: KeyboardEvent, args: Slick.OnKeyDownEventArgs<T>): void {
let event = new StandardKeyboardEvent(e);
if (event.equals(KeyCode.Space) && this.isCurrentColumn(args.cell)) {
private handleKeyboardEvent(e: StandardKeyboardEvent, args: Slick.OnKeyDownEventArgs<T>): void {
if (e.equals(KeyCode.Space) && this.isCurrentColumn(args.cell)) {
this.fireOnChangeEvent();
}
}

View File

@@ -3,6 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { convertJQueryKeyDownEvent } from 'sql/base/browser/dom';
import { ICheckboxStyles } from 'sql/base/browser/ui/checkbox/checkbox';
import { mixin } from 'sql/base/common/objects';
import { escape } from 'sql/base/common/strings';
@@ -102,7 +103,7 @@ export class CheckboxSelectColumn<T extends Slick.SlickData> implements Slick.Pl
this._grid = grid;
this._handler
.subscribe(this._grid.onClick, (e: Event, args: Slick.OnClickEventArgs<T>) => this.handleClick(e, args))
.subscribe(this._grid.onKeyDown, (e: DOMEvent, args: Slick.OnKeyDownEventArgs<T>) => this.handleKeyDown(e as KeyboardEvent, args))
.subscribe(this._grid.onKeyDown, (e: DOMEvent, args: Slick.OnKeyDownEventArgs<T>) => this.handleKeyDown(convertJQueryKeyDownEvent(e), args))
.subscribe(this._grid.onHeaderCellRendered, (e: Event, args: Slick.OnHeaderCellRenderedEventArgs<T>) => this.handleHeaderCellRendered(e, args))
.subscribe(grid.onActiveCellChanged, (e: DOMEvent, args: Slick.OnActiveCellChangedEventArgs<T>) => { this.handleActiveCellChanged(args); });
if (this.isCheckAllHeaderCheckboxShown()) {
@@ -120,16 +121,15 @@ export class CheckboxSelectColumn<T extends Slick.SlickData> implements Slick.Pl
e.preventDefault();
}
private handleKeyDown(e: KeyboardEvent, args: Slick.OnKeyDownEventArgs<T>): void {
const event = new StandardKeyboardEvent(e);
private handleKeyDown(e: StandardKeyboardEvent, args: Slick.OnKeyDownEventArgs<T>): void {
if (args.cell !== this.index) {
return;
}
if (event.equals(KeyCode.Enter) || event.equals(KeyCode.Space)) {
if (e.equals(KeyCode.Enter) || e.equals(KeyCode.Space)) {
this.toggleCellCheckbox(args.row);
e.stopPropagation();
e.stopImmediatePropagation();
e.preventDefault();
e.browserEvent.stopImmediatePropagation();
}
}

View File

@@ -7,6 +7,7 @@ import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { Emitter, Event } from 'vs/base/common/event';
import { isUndefinedOrNull } from 'vs/base/common/types';
import { convertJQueryKeyDownEvent } from 'sql/base/browser/dom';
/**
* Implements the various additional navigation keybindings we want out of slickgrid
@@ -20,18 +21,17 @@ export class CopyKeybind<T> implements Slick.Plugin<T> {
public init(grid: Slick.Grid<T>) {
this.grid = grid;
this.handler.subscribe(this.grid.onKeyDown, (e: DOMEvent, args: Slick.OnKeyDownEventArgs<T>) => this.handleKeyDown(e as KeyboardEvent, args));
this.handler.subscribe(this.grid.onKeyDown, (e: DOMEvent, args: Slick.OnKeyDownEventArgs<T>) => this.handleKeyDown(convertJQueryKeyDownEvent(e), args));
}
public destroy() {
this.handler.unsubscribeAll();
}
private handleKeyDown(e: KeyboardEvent, args: Slick.OnKeyDownEventArgs<T>): void {
let event = new StandardKeyboardEvent(e);
private handleKeyDown(e: StandardKeyboardEvent, args: Slick.OnKeyDownEventArgs<T>): void {
let handled = false;
if (event.equals(KeyCode.KeyC | KeyMod.CtrlCmd)) {
if (e.equals(KeyCode.KeyC | KeyMod.CtrlCmd)) {
handled = true;
let selectionModel = this.grid.getSelectionModel();
let ranges: Slick.Range[];
@@ -53,7 +53,7 @@ export class CopyKeybind<T> implements Slick.Plugin<T> {
if (handled) {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
e.browserEvent.stopImmediatePropagation
}
}

View File

@@ -1,5 +1,8 @@
// Adopted and converted to typescript from https://github.com/6pac/SlickGrid/blob/master/plugins/slick.rowselectionmodel.js
// heavily modified
import { convertJQueryKeyDownEvent } from 'sql/base/browser/dom';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode } from 'vs/base/common/keyCodes';
import { mixin } from 'vs/base/common/objects';
const defaultOptions: IRowSelectionModelOptions = {
@@ -26,7 +29,7 @@ export class RowSelectionModel<T extends Slick.SlickData> implements Slick.Selec
this._grid = grid;
this._handler
.subscribe(this._grid.onActiveCellChanged, (e: Event, data: Slick.OnActiveCellChangedEventArgs<T>) => this.handleActiveCellChange(e, data))
.subscribe(this._grid.onKeyDown, (e: DOMEvent) => this.handleKeyDown(e as KeyboardEvent))
.subscribe(this._grid.onKeyDown, (e: DOMEvent) => this.handleKeyDown(convertJQueryKeyDownEvent(e)))
.subscribe(this._grid.onClick, (e: DOMEvent) => this.handleClick(e as MouseEvent));
}
@@ -85,9 +88,9 @@ export class RowSelectionModel<T extends Slick.SlickData> implements Slick.Selec
}
}
private handleKeyDown(e: KeyboardEvent): void {
private handleKeyDown(e: StandardKeyboardEvent): void {
const activeRow = this._grid.getActiveCell();
if (activeRow && e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey && (e.which === 38 || e.which === 40)) {
if (activeRow && e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey && (e.keyCode === KeyCode.UpArrow || e.keyCode === KeyCode.DownArrow)) {
let selectedRows = this.getSelectedRows();
selectedRows.sort((x, y) => x - y);
@@ -99,7 +102,7 @@ export class RowSelectionModel<T extends Slick.SlickData> implements Slick.Selec
let bottom = selectedRows[selectedRows.length - 1];
let active;
if (e.which === 40) {
if (e.keyCode === KeyCode.DownArrow) {
active = activeRow.row < bottom || top === bottom ? ++bottom : ++top;
} else {
active = activeRow.row < bottom ? --bottom : --top;

View File

@@ -2,6 +2,7 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { convertJQueryKeyDownEvent } from 'sql/base/browser/dom';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { Emitter } from 'vs/base/common/event';
import { KeyCode } from 'vs/base/common/keyCodes';
@@ -36,7 +37,7 @@ export abstract class BaseClickableColumn<T extends Slick.SlickData> implements
public init(grid: Slick.Grid<T>): void {
this._grid = grid;
this._handler.subscribe(grid.onClick, (e: DOMEvent, args: Slick.OnClickEventArgs<T>) => this.handleClick(args));
this._handler.subscribe(grid.onKeyDown, (e: DOMEvent, args: Slick.OnKeyDownEventArgs<T>) => this.handleKeyboardEvent(e as KeyboardEvent, args));
this._handler.subscribe(grid.onKeyDown, (e: DOMEvent, args: Slick.OnKeyDownEventArgs<T>) => this.handleKeyboardEvent(convertJQueryKeyDownEvent(e), args));
this._handler.subscribe(grid.onActiveCellChanged, (e: DOMEvent, args: Slick.OnActiveCellChangedEventArgs<T>) => { this.handleActiveCellChanged(args); });
}
@@ -74,11 +75,10 @@ export abstract class BaseClickableColumn<T extends Slick.SlickData> implements
}
}
private handleKeyboardEvent(e: KeyboardEvent, args: Slick.OnKeyDownEventArgs<T>): void {
let event = new StandardKeyboardEvent(e);
if ((event.equals(KeyCode.Enter) || event.equals(KeyCode.Space)) && this.isCellEnabled(args.row, args.cell)) {
event.stopPropagation();
event.preventDefault();
private handleKeyboardEvent(e: StandardKeyboardEvent, args: Slick.OnKeyDownEventArgs<T>): void {
if ((e.equals(KeyCode.Enter) || e.equals(KeyCode.Space)) && this.isCellEnabled(args.row, args.cell)) {
e.stopPropagation();
e.preventDefault();
this.fireClickEvent();
}
}

View File

@@ -53,6 +53,7 @@ import { IAccessibilityService } from 'vs/platform/accessibility/common/accessib
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
import { IComponentContextService } from 'sql/workbench/services/componentContext/browser/componentContextService';
import { defaultTableStyles } from 'sql/platform/theme/browser/defaultStyles';
import { convertJQueryKeyDownEvent } from 'sql/base/browser/dom';
const labelDisplay = nls.localize("insights.item", "Item");
const valueDisplay = nls.localize("insights.value", "Value");
@@ -305,8 +306,8 @@ export class InsightsDialogView extends Modal {
this._splitView.addView(topTableView, Sizing.Distribute);
this._splitView.addView(bottomTableView, Sizing.Distribute);
this._topTable.grid.onKeyDown.subscribe(e => {
let event = new StandardKeyboardEvent(<unknown>e as KeyboardEvent);
this._topTable.grid.onKeyDown.subscribe((e: DOMEvent) => {
const event = convertJQueryKeyDownEvent(e);
if (event.equals(KeyMod.Shift | KeyCode.Tab)) {
topTableView.focus();
e.stopImmediatePropagation();
@@ -316,8 +317,8 @@ export class InsightsDialogView extends Modal {
}
});
this._bottomTable.grid.onKeyDown.subscribe(e => {
let event = new StandardKeyboardEvent(<unknown>e as KeyboardEvent);
this._bottomTable.grid.onKeyDown.subscribe((e: DOMEvent) => {
const event = convertJQueryKeyDownEvent(e);
if (event.equals(KeyMod.Shift | KeyCode.Tab)) {
bottomTableView.focus();
e.stopImmediatePropagation();

View File

@@ -5,7 +5,6 @@
import 'vs/css!./media/restoreDialog';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { Event, Emitter } from 'vs/base/common/event';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { Widget } from 'vs/base/browser/ui/widget';
@@ -51,6 +50,7 @@ import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
import { IComponentContextService } from 'sql/workbench/services/componentContext/browser/componentContextService';
import { defaultButtonStyles, defaultInputBoxStyles } from 'vs/platform/theme/browser/defaultStyles';
import { defaultCheckboxStyles, defaultEditableDropdownStyles, defaultSelectBoxStyles, defaultTableStyles } from 'sql/platform/theme/browser/defaultStyles';
import { convertJQueryKeyDownEvent } from 'sql/base/browser/dom';
interface FileListElement {
logicalFileName: string;
@@ -450,8 +450,8 @@ export class RestoreDialog extends Modal {
}
}));
this._restorePlanTable.grid.onKeyDown.subscribe(e => {
let event = new StandardKeyboardEvent(<unknown>e as KeyboardEvent);
this._restorePlanTable.grid.onKeyDown.subscribe((e: DOMEvent) => {
const event = convertJQueryKeyDownEvent(e);
if (event.equals(KeyMod.Shift | KeyCode.Tab)) {
this._destinationRestoreToInputBox!.isEnabled() ? this._destinationRestoreToInputBox!.focus() : this._databaseDropdown!.focus();
e.stopImmediatePropagation();
@@ -461,8 +461,8 @@ export class RestoreDialog extends Modal {
}
});
this._fileListTable.grid.onKeyDown.subscribe(e => {
let event = new StandardKeyboardEvent(<unknown>e as KeyboardEvent);
this._fileListTable.grid.onKeyDown.subscribe((e: DOMEvent) => {
const event = convertJQueryKeyDownEvent(e);
if (event.equals(KeyMod.Shift | KeyCode.Tab)) {
if ((<InputBox>this._optionsMap[this._relocatedLogFileFolderOption]).isEnabled()) {
(<InputBox>this._optionsMap[this._relocatedLogFileFolderOption]).focus();