mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
add copy keybind (#2445)
This commit is contained in:
62
src/sql/base/browser/ui/table/plugins/copyKeybind.plugin.ts
Normal file
62
src/sql/base/browser/ui/table/plugins/copyKeybind.plugin.ts
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
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';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements the various additional navigation keybindings we want out of slickgrid
|
||||||
|
*/
|
||||||
|
export class CopyKeybind<T> implements Slick.Plugin<T> {
|
||||||
|
private grid: Slick.Grid<T>;
|
||||||
|
private handler = new Slick.EventHandler();
|
||||||
|
|
||||||
|
private _onCopy = new Emitter<Slick.Range[]>();
|
||||||
|
public onCopy: Event<Slick.Range[]> = this._onCopy.event;
|
||||||
|
|
||||||
|
public init(grid: Slick.Grid<T>) {
|
||||||
|
this.grid = grid;
|
||||||
|
this.handler.subscribe(this.grid.onKeyDown, (e, args) => this.handleKeyDown(e, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
public destroy() {
|
||||||
|
this.handler.unsubscribeAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleKeyDown(e: KeyboardEvent, args: Slick.OnKeyDownEventArgs<T>): void {
|
||||||
|
let event = new StandardKeyboardEvent(e);
|
||||||
|
let handled = false;
|
||||||
|
|
||||||
|
if (event.equals(KeyCode.KEY_C | KeyMod.CtrlCmd)) {
|
||||||
|
handled = true;
|
||||||
|
let selectionModel = this.grid.getSelectionModel();
|
||||||
|
let ranges: Slick.Range[];
|
||||||
|
// check to see if we can get the range from the model directly
|
||||||
|
if (selectionModel && (<any>selectionModel).getSelectedRanges) {
|
||||||
|
ranges = (<any>selectionModel).getSelectedRanges();
|
||||||
|
} else {
|
||||||
|
let selectedRows = this.grid.getSelectedRows();
|
||||||
|
let startColumn = 0;
|
||||||
|
// check for number column
|
||||||
|
if (!isUndefinedOrNull(this.grid.getColumns()[0].selectable) && !this.grid.getColumns()[0].selectable) {
|
||||||
|
startColumn = 1;
|
||||||
|
}
|
||||||
|
ranges = [new Slick.Range(selectedRows[0], startColumn, selectedRows[selectedRows.length - 1], this.grid.getColumns().length)]
|
||||||
|
}
|
||||||
|
this._onCopy.fire(ranges);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handled) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
e.stopImmediatePropagation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -34,6 +34,14 @@ export interface IMessagesActionContext {
|
|||||||
tree: ITree;
|
tree: ITree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function mapForNumberColumn(ranges: Slick.Range[]): Slick.Range[] {
|
||||||
|
if (ranges) {
|
||||||
|
return ranges.map(e => new Slick.Range(e.fromRow, e.fromCell - 1, e.toRow, e.toCell ? e.toCell - 1 : undefined));
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class SaveResultAction extends Action {
|
export class SaveResultAction extends Action {
|
||||||
public static SAVECSV_ID = 'grid.saveAsCsv';
|
public static SAVECSV_ID = 'grid.saveAsCsv';
|
||||||
public static SAVECSV_LABEL = localize('saveAsCsv', 'Save As CSV');
|
public static SAVECSV_LABEL = localize('saveAsCsv', 'Save As CSV');
|
||||||
@@ -51,13 +59,19 @@ export class SaveResultAction extends Action {
|
|||||||
id: string,
|
id: string,
|
||||||
label: string,
|
label: string,
|
||||||
icon: string,
|
icon: string,
|
||||||
private format: SaveFormat
|
private format: SaveFormat,
|
||||||
|
private accountForNumberColumn = true
|
||||||
) {
|
) {
|
||||||
super(id, label, icon);
|
super(id, label, icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
public run(context: IGridActionContext): TPromise<boolean> {
|
public run(context: IGridActionContext): TPromise<boolean> {
|
||||||
context.runner.serializeResults(context.batchId, context.resultId, this.format, context.selection);
|
if (this.accountForNumberColumn) {
|
||||||
|
context.runner.serializeResults(context.batchId, context.resultId, this.format,
|
||||||
|
mapForNumberColumn(context.selection));
|
||||||
|
} else {
|
||||||
|
context.runner.serializeResults(context.batchId, context.resultId, this.format, context.selection);
|
||||||
|
}
|
||||||
return TPromise.as(true);
|
return TPromise.as(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,12 +87,19 @@ export class CopyResultAction extends Action {
|
|||||||
id: string,
|
id: string,
|
||||||
label: string,
|
label: string,
|
||||||
private copyHeader: boolean,
|
private copyHeader: boolean,
|
||||||
|
private accountForNumberColumn = true
|
||||||
) {
|
) {
|
||||||
super(id, label);
|
super(id, label);
|
||||||
}
|
}
|
||||||
|
|
||||||
public run(context: IGridActionContext): TPromise<boolean> {
|
public run(context: IGridActionContext): TPromise<boolean> {
|
||||||
context.runner.copyResults(context.selection, context.batchId, context.resultId, this.copyHeader);
|
if (this.accountForNumberColumn) {
|
||||||
|
context.runner.copyResults(
|
||||||
|
mapForNumberColumn(context.selection),
|
||||||
|
context.batchId, context.resultId, this.copyHeader);
|
||||||
|
} else {
|
||||||
|
context.runner.copyResults(context.selection, context.batchId, context.resultId, this.copyHeader);
|
||||||
|
}
|
||||||
return TPromise.as(true);
|
return TPromise.as(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import { Dimension, getContentWidth } from 'vs/base/browser/dom';
|
|||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
|
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
|
||||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||||
|
import { CopyKeybind } from 'sql/base/browser/ui/table/plugins/copyKeybind.plugin';
|
||||||
|
|
||||||
const ROW_HEIGHT = 29;
|
const ROW_HEIGHT = 29;
|
||||||
const HEADER_HEIGHT = 26;
|
const HEADER_HEIGHT = 26;
|
||||||
@@ -295,11 +296,24 @@ class GridTable<T> extends Disposable implements IView {
|
|||||||
this.renderGridDataRowsRange(startIndex, count);
|
this.renderGridDataRowsRange(startIndex, count);
|
||||||
});
|
});
|
||||||
let numberColumn = new RowNumberColumn({ numberOfRows: this.resultSet.rowCount });
|
let numberColumn = new RowNumberColumn({ numberOfRows: this.resultSet.rowCount });
|
||||||
|
let copyHandler = new CopyKeybind();
|
||||||
|
copyHandler.onCopy(e => {
|
||||||
|
new CopyResultAction(CopyResultAction.COPY_ID, CopyResultAction.COPY_LABEL, false).run({
|
||||||
|
selection: e,
|
||||||
|
batchId: this.resultSet.batchId,
|
||||||
|
resultId: this.resultSet.id,
|
||||||
|
cell: this.table.grid.getActiveCell(),
|
||||||
|
runner: this.runner,
|
||||||
|
table: this.table,
|
||||||
|
tableState: this.state
|
||||||
|
});
|
||||||
|
});
|
||||||
this.columns.unshift(numberColumn.getColumnDefinition());
|
this.columns.unshift(numberColumn.getColumnDefinition());
|
||||||
this.table = this._register(new Table(tableContainer, { dataProvider: new AsyncDataProvider(collection), columns: this.columns }, { rowHeight: ROW_HEIGHT, showRowNumber: true }));
|
this.table = this._register(new Table(tableContainer, { dataProvider: new AsyncDataProvider(collection), columns: this.columns }, { rowHeight: ROW_HEIGHT, showRowNumber: true }));
|
||||||
this.table.setSelectionModel(this.selectionModel);
|
this.table.setSelectionModel(this.selectionModel);
|
||||||
this.table.registerPlugin(new MouseWheelSupport());
|
this.table.registerPlugin(new MouseWheelSupport());
|
||||||
this.table.registerPlugin(new AutoColumnSize());
|
this.table.registerPlugin(new AutoColumnSize());
|
||||||
|
this.table.registerPlugin(copyHandler);
|
||||||
this.table.registerPlugin(numberColumn);
|
this.table.registerPlugin(numberColumn);
|
||||||
this._register(this.table.onContextMenu(this.contextMenu, this));
|
this._register(this.table.onContextMenu(this.contextMenu, this));
|
||||||
this._register(this.table.onClick(this.onTableClick, this));
|
this._register(this.table.onClick(this.onTableClick, this));
|
||||||
|
|||||||
Reference in New Issue
Block a user