mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Auto Column Sizing (#2778)
* add auto column sizing * add break for performance * update with new library
This commit is contained in:
@@ -1,13 +1,16 @@
|
|||||||
// Adapted from https://github.com/naresh-n/slickgrid-column-data-autosize/blob/master/src/slick.autocolumnsize.js
|
// Adapted from https://github.com/naresh-n/slickgrid-column-data-autosize/blob/master/src/slick.autocolumnsize.js
|
||||||
|
|
||||||
import { mixin, clone } from 'sql/base/common/objects';
|
import { mixin, clone } from 'sql/base/common/objects';
|
||||||
|
import { isInDOM } from 'vs/base/browser/dom';
|
||||||
|
|
||||||
export interface IAutoColumnSizeOptions extends Slick.PluginOptions {
|
export interface IAutoColumnSizeOptions extends Slick.PluginOptions {
|
||||||
maxWidth?: number;
|
maxWidth?: number;
|
||||||
|
autoSizeOnRender?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultOptions: IAutoColumnSizeOptions = {
|
const defaultOptions: IAutoColumnSizeOptions = {
|
||||||
maxWidth: 200
|
maxWidth: 200,
|
||||||
|
autoSizeOnRender: false
|
||||||
};
|
};
|
||||||
|
|
||||||
export class AutoColumnSize<T> implements Slick.Plugin<T> {
|
export class AutoColumnSize<T> implements Slick.Plugin<T> {
|
||||||
@@ -15,6 +18,7 @@ export class AutoColumnSize<T> implements Slick.Plugin<T> {
|
|||||||
private _$container: JQuery;
|
private _$container: JQuery;
|
||||||
private _context: CanvasRenderingContext2D;
|
private _context: CanvasRenderingContext2D;
|
||||||
private _options: IAutoColumnSizeOptions;
|
private _options: IAutoColumnSizeOptions;
|
||||||
|
private onPostEventHandler = new Slick.EventHandler();
|
||||||
|
|
||||||
constructor(options: IAutoColumnSizeOptions = defaultOptions) {
|
constructor(options: IAutoColumnSizeOptions = defaultOptions) {
|
||||||
this._options = mixin(options, defaultOptions, false);
|
this._options = mixin(options, defaultOptions, false);
|
||||||
@@ -23,8 +27,12 @@ export class AutoColumnSize<T> implements Slick.Plugin<T> {
|
|||||||
public init(grid: Slick.Grid<T>) {
|
public init(grid: Slick.Grid<T>) {
|
||||||
this._grid = grid;
|
this._grid = grid;
|
||||||
|
|
||||||
|
if (this._options.autoSizeOnRender) {
|
||||||
|
this.onPostEventHandler.subscribe(this._grid.onRendered, () => this.onPostRender());
|
||||||
|
}
|
||||||
|
|
||||||
this._$container = $(this._grid.getContainerNode());
|
this._$container = $(this._grid.getContainerNode());
|
||||||
this._$container.on('dblclick.autosize', '.slick-resizable-handle', e => this.reSizeColumn(e));
|
this._$container.on('dblclick.autosize', '.slick-resizable-handle', e => this.handleDoubleClick(e));
|
||||||
this._context = document.createElement('canvas').getContext('2d');
|
this._context = document.createElement('canvas').getContext('2d');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,7 +40,66 @@ export class AutoColumnSize<T> implements Slick.Plugin<T> {
|
|||||||
this._$container.off();
|
this._$container.off();
|
||||||
}
|
}
|
||||||
|
|
||||||
private reSizeColumn(e: JQuery.Event<HTMLElement, string>) {
|
private onPostRender() {
|
||||||
|
// this doesn't do anything if the grid isn't on the dom
|
||||||
|
if (!isInDOM(this._grid.getContainerNode())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// since data can be async we want to only do this if we have the data to actual
|
||||||
|
// work on since we are measuring the physical length of data
|
||||||
|
let data = this._grid.getData();
|
||||||
|
let item = data.getItem(0);
|
||||||
|
if (item && Object.keys(item).length > 0) {
|
||||||
|
let hasValue = false;
|
||||||
|
for (let key in item) {
|
||||||
|
if (item.hasOwnProperty(key)) {
|
||||||
|
if (item[key]) {
|
||||||
|
hasValue = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasValue) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let headerColumnsQuery = $(this._grid.getContainerNode()).find('.slick-header-columns');
|
||||||
|
if (headerColumnsQuery && headerColumnsQuery.length) {
|
||||||
|
let headerColumns = headerColumnsQuery[0];
|
||||||
|
let origCols = this._grid.getColumns();
|
||||||
|
let allColumns = clone(origCols);
|
||||||
|
allColumns.forEach((col, index) => {
|
||||||
|
col.formatter = origCols[index].formatter;
|
||||||
|
col.asyncPostRender = origCols[index].asyncPostRender;
|
||||||
|
});
|
||||||
|
let change = false;
|
||||||
|
for (let i = 0; i <= headerColumns.children.length; i++) {
|
||||||
|
let headerEl = $(headerColumns.children.item(i));
|
||||||
|
let columnDef = headerEl.data('column');
|
||||||
|
if (columnDef) {
|
||||||
|
let headerWidth = this.getElementWidth(headerEl[0]);
|
||||||
|
let colIndex = this._grid.getColumnIndex(columnDef.id);
|
||||||
|
let column = allColumns[colIndex];
|
||||||
|
let autoSizeWidth = Math.max(headerWidth, this.getMaxColumnTextWidth(columnDef, colIndex)) + 1;
|
||||||
|
if (autoSizeWidth !== column.width) {
|
||||||
|
allColumns[colIndex].width = autoSizeWidth;
|
||||||
|
change = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (change) {
|
||||||
|
this.onPostEventHandler.unsubscribeAll();
|
||||||
|
this._grid.setColumns(allColumns);
|
||||||
|
this._grid.onColumnsResized.notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleDoubleClick(e: JQuery.Event<HTMLElement, string>) {
|
||||||
let headerEl = $(e.currentTarget).closest('.slick-header-column');
|
let headerEl = $(e.currentTarget).closest('.slick-header-column');
|
||||||
let columnDef = headerEl.data('column');
|
let columnDef = headerEl.data('column');
|
||||||
|
|
||||||
@@ -43,6 +110,10 @@ export class AutoColumnSize<T> implements Slick.Plugin<T> {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
|
this.reSizeColumn(headerEl, columnDef);
|
||||||
|
}
|
||||||
|
|
||||||
|
private reSizeColumn(headerEl: JQuery, columnDef: Slick.Column<T>) {
|
||||||
let headerWidth = this.getElementWidth(headerEl[0]);
|
let headerWidth = this.getElementWidth(headerEl[0]);
|
||||||
let colIndex = this._grid.getColumnIndex(columnDef.id);
|
let colIndex = this._grid.getColumnIndex(columnDef.id);
|
||||||
let origCols = this._grid.getColumns();
|
let origCols = this._grid.getColumns();
|
||||||
|
|||||||
@@ -420,12 +420,12 @@ class GridTable<T> extends Disposable implements IView {
|
|||||||
@IContextMenuService private contextMenuService: IContextMenuService,
|
@IContextMenuService private contextMenuService: IContextMenuService,
|
||||||
@IInstantiationService private instantiationService: IInstantiationService,
|
@IInstantiationService private instantiationService: IInstantiationService,
|
||||||
@IEditorService private editorService: IEditorService,
|
@IEditorService private editorService: IEditorService,
|
||||||
@IUntitledEditorService private untitledEditorService: IUntitledEditorService
|
@IUntitledEditorService private untitledEditorService: IUntitledEditorService,
|
||||||
|
@IConfigurationService private configurationService: IConfigurationService
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this.container.style.width = '100%';
|
this.container.style.width = '100%';
|
||||||
this.container.style.height = '100%';
|
this.container.style.height = '100%';
|
||||||
// this.container.style.marginBottom = BOTTOM_PADDING + 'px';
|
|
||||||
this.container.className = 'grid-panel';
|
this.container.className = 'grid-panel';
|
||||||
|
|
||||||
this.columns = this.resultSet.columnInfo.map((c, i) => {
|
this.columns = this.resultSet.columnInfo.map((c, i) => {
|
||||||
@@ -507,7 +507,7 @@ class GridTable<T> extends Disposable implements IView {
|
|||||||
this.table = this._register(new Table(tableContainer, { dataProvider: this.dataProvider, columns: this.columns }, tableOptions));
|
this.table = this._register(new Table(tableContainer, { dataProvider: this.dataProvider, columns: this.columns }, tableOptions));
|
||||||
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({ autoSizeOnRender: this.configurationService.getValue('resultsGrid.autoSizeColumns') }));
|
||||||
this.table.registerPlugin(copyHandler);
|
this.table.registerPlugin(copyHandler);
|
||||||
this.table.registerPlugin(this.rowNumberColumn);
|
this.table.registerPlugin(this.rowNumberColumn);
|
||||||
this.table.registerPlugin(new AdditionalKeyBindings());
|
this.table.registerPlugin(new AdditionalKeyBindings());
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ const resultsGridConfiguration: IConfigurationNode = {
|
|||||||
type: 'object',
|
type: 'object',
|
||||||
title: nls.localize('resultsGridConfigurationTitle', "Results Grid"),
|
title: nls.localize('resultsGridConfigurationTitle', "Results Grid"),
|
||||||
overridable: true,
|
overridable: true,
|
||||||
scope: ConfigurationScope.RESOURCE,
|
|
||||||
properties: {
|
properties: {
|
||||||
'resultsGrid.fontFamily': {
|
'resultsGrid.fontFamily': {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
@@ -62,6 +61,11 @@ const resultsGridConfiguration: IConfigurationNode = {
|
|||||||
],
|
],
|
||||||
default: RESULTS_GRID_DEFAULTS.cellPadding,
|
default: RESULTS_GRID_DEFAULTS.cellPadding,
|
||||||
description: nls.localize('cellPadding', "Controls the cell padding in pixels")
|
description: nls.localize('cellPadding', "Controls the cell padding in pixels")
|
||||||
|
},
|
||||||
|
'resultsGrid.autoSizeColumns': {
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
description: nls.localize('autoSizeColumns', "Auto size the columns width on inital results. Could have performance problems with large number of columns or large cells")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user