From 2f4feb9b36c14513f728a026c97b66d009676d4b Mon Sep 17 00:00:00 2001 From: martinRenou Date: Mon, 5 Sep 2022 11:49:26 +0200 Subject: [PATCH 01/25] Explore datagrid performance improvements --- packages/datagrid/src/datagrid.ts | 280 ++++++++++++++++++++---------- 1 file changed, 190 insertions(+), 90 deletions(-) diff --git a/packages/datagrid/src/datagrid.ts b/packages/datagrid/src/datagrid.ts index ed0c69fc9..6a0cde3ef 100644 --- a/packages/datagrid/src/datagrid.ts +++ b/packages/datagrid/src/datagrid.ts @@ -3189,14 +3189,14 @@ export class DataGrid extends Widget { } // Render entire grid if scrolling merged cells grid - const paintEverything = Private.shouldPaintEverything(this._dataModel!); + // const paintEverything = Private.shouldPaintEverything(this._dataModel!); - if (paintEverything) { - this.paintContent(0, 0, vw, vh); - this._paintOverlay(); - this._syncScrollState(); - return; - } + // if (paintEverything) { + // this.paintContent(0, 0, vw, vh); + // this._paintOverlay(); + // this._syncScrollState(); + // return; + // } // Compute the size delta. let delta = newSize - oldSize; @@ -3311,14 +3311,14 @@ export class DataGrid extends Widget { } // Render entire grid if scrolling merged cells grid - const paintEverything = Private.shouldPaintEverything(this._dataModel!); + // const paintEverything = Private.shouldPaintEverything(this._dataModel!); - if (paintEverything) { - this.paintContent(0, 0, vw, vh); - this._paintOverlay(); - this._syncScrollState(); - return; - } + // if (paintEverything) { + // this.paintContent(0, 0, vw, vh); + // this._paintOverlay(); + // this._syncScrollState(); + // return; + // } // Compute the size delta. let delta = newSize - oldSize; @@ -3433,14 +3433,14 @@ export class DataGrid extends Widget { } // Render entire grid if scrolling merged cells grid - const paintEverything = Private.shouldPaintEverything(this._dataModel!); + // const paintEverything = Private.shouldPaintEverything(this._dataModel!); - if (paintEverything) { - this.paintContent(0, 0, vw, vh); - this._paintOverlay(); - this._syncScrollState(); - return; - } + // if (paintEverything) { + // this.paintContent(0, 0, vw, vh); + // this._paintOverlay(); + // this._syncScrollState(); + // return; + // } // Compute the size delta. let delta = newSize - oldSize; @@ -3531,14 +3531,14 @@ export class DataGrid extends Widget { } // Render entire grid if scrolling merged cells grid - const paintEverything = Private.shouldPaintEverything(this._dataModel!); + // const paintEverything = Private.shouldPaintEverything(this._dataModel!); - if (paintEverything) { - this.paintContent(0, 0, vw, vh); - this._paintOverlay(); - this._syncScrollState(); - return; - } + // if (paintEverything) { + // this.paintContent(0, 0, vw, vh); + // this._paintOverlay(); + // this._syncScrollState(); + // return; + // } // Paint the overlay. this._paintOverlay(); @@ -4652,17 +4652,17 @@ export class DataGrid extends Widget { return; } - // Determine if the cell intersects with a merged group at row or column - let intersectingColumnGroups = CellGroup.getCellGroupsAtColumn( - this._dataModel!, - rgn.region, - rgn.column - ); - let intersectingRowGroups = CellGroup.getCellGroupsAtRow( - this._dataModel!, - rgn.region, - rgn.row - ); + // // Determine if the region intersects with a merged group at row or column + // let intersectingColumnGroups = CellGroup.getCellGroupsAtColumn( + // this._dataModel!, + // rgn.region, + // rgn.column + // ); + // let intersectingRowGroups = CellGroup.getCellGroupsAtRow( + // this._dataModel!, + // rgn.region, + // rgn.row + // ); // move the bounds of the region if edges of the region are part of a merge group. // after the move, new region contains entirety of the merge groups @@ -4761,38 +4761,40 @@ export class DataGrid extends Widget { yOffset = height; /** - * For merged cell regions, only rendering the merged region - * if the "parent" cell is the one being painted. Bail otherwise. + * For merged cell regions, don't do anything, we draw merged regions later. */ if (groupIndex !== -1) { - const group = this.dataModel!.group(config.region, groupIndex)!; - if (group.r1 === row && group.c1 === column) { - width = 0; - for (let c = group.c1; c <= group.c2; c++) { - width += this._getColumnSize(config.region, c); - } - - height = 0; - for (let r = group.r1; r <= group.r2; r++) { - height += this._getRowSize(config.region, r); - } - } else { - y += yOffset; - continue; - } - } else { - /** - * Reset column width if we're rendering a column-header - * which is not part of a merged cell group. - */ - if (rgn.region == 'column-header') { - width = rgn.columnSizes[i]; - } + y += yOffset; + continue; + // const group = this.dataModel!.group(config.region, groupIndex)!; + // if (group.r1 === row && group.c1 === column) { + // width = 0; + // for (let c = group.c1; c <= group.c2; c++) { + // width += this._getColumnSize(config.region, c); + // } + + // height = 0; + // for (let r = group.r1; r <= group.r2; r++) { + // height += this._getRowSize(config.region, r); + // } + // } else { + // y += yOffset; + // continue; + // } + // } else { + // /** + // * Reset column width if we're rendering a column-header + // * which is not part of a merged cell group. + // */ + // if (rgn.region == 'column-header') { + // width = rgn.columnSizes[i]; + // } } // Clear the buffer rect for the cell. gc.clearRect(x, y, width, height); + // Why are there two saves? // Save the GC state. gc.save(); @@ -4830,6 +4832,9 @@ export class DataGrid extends Widget { // Paint the cell into the off-screen buffer. try { + if (groupIndex !== -1) { + console.log('drawing merged cell anyway') + } renderer.paint(gc, config); } catch (err) { console.error(err); @@ -4846,32 +4851,33 @@ export class DataGrid extends Widget { let y1 = Math.max(rgn.yMin, config.y); let y2 = Math.min(config.y + config.height - 1, rgn.yMax); - if ( - intersectingColumnGroups.length !== 0 || - intersectingRowGroups.length !== 0 - ) { - if (x2 > x1 && y2 > y1) { - this._blitContent( - this._buffer, - x1, - y1, - x2 - x1 + 1, - y2 - y1 + 1, - x1, - y1 - ); - } - } else { - this._blitContent( - this._buffer, - x1, - y1, - x2 - x1 + 1, - y2 - y1 + 1, - x1, - y1 - ); - } + // TODO Do we still need this? + // if ( + // intersectingColumnGroups.length !== 0 || + // intersectingRowGroups.length !== 0 + // ) { + // if (x2 > x1 && y2 > y1) { + // this._blitContent( + // this._buffer, + // x1, + // y1, + // x2 - x1 + 1, + // y2 - y1 + 1, + // x1, + // y1 + // ); + // } + // } else { + this._blitContent( + this._buffer, + x1, + y1, + x2 - x1 + 1, + y2 - y1 + 1, + x1, + y1 + ); + // } // Increment the running Y coordinate. y += yOffset; @@ -4884,6 +4890,100 @@ export class DataGrid extends Widget { x += xOffset; } + // Draw merged groups that intersects with the region + const cellGroups = CellGroup.getCellGroupsAtRegion( + this.dataModel!, + rgn.region + ); + + for (const group of cellGroups) { + let x = 0; + for (let c = 0; c < group.c1; c++) { + x += this._getColumnSize(rgn.region, c); + } + + let y = 0; + for (let r = 0; r < group.r1; r++) { + y += this._getRowSize(rgn.region, r); + } + + let width = 0; + for (let c = group.c1; c <= group.c2; c++) { + width += this._getColumnSize(rgn.region, c); + } + + let height = 0; + for (let r = group.r1; r <= group.r2; r++) { + height += this._getRowSize(rgn.region, r); + } + + let value: any; + try { + value = this._dataModel.data(rgn.region, group.r1, group.c1); + } catch (err) { + value = undefined; + console.error(err); + } + + // Get the metadata for the cell. + let metadata: DataModel.Metadata; + try { + metadata = this._dataModel.metadata(rgn.region, group.r1, group.c1); + } catch (err) { + metadata = DataModel.emptyMetadata; + console.error(err); + } + + config.x = rgn.x + x; + config.y = rgn.y + y; + config.width = width; + config.height = height; + config.region = rgn.region; + config.row = group.r1; + config.column = group.c1; + config.value = value; + config.metadata = metadata; + + console.log('trying to draw', JSON.stringify(config)) + + // Get the renderer for the cell. + let renderer = this._cellRenderers.get(config); + + // Clear the buffer rect for the cell. + gc.clearRect(x, y, width, height); + + // Save the GC state. + gc.save(); + + // Paint the cell into the off-screen buffer. + try { + renderer.paint(gc, config); + } catch (err) { + console.error(err); + } + + // Restore the GC state. + gc.restore(); + + // Compute the actual X bounds for the cell. + let x1 = Math.max(rgn.xMin, config.x); + let x2 = Math.min(config.x + config.width - 1, rgn.xMax); + + // Compute the actual Y bounds for the cell. + let y1 = Math.max(rgn.yMin, config.y); + let y2 = Math.min(config.y + config.height - 1, rgn.yMax); + + this._blitContent( + this._buffer, + x1, + y1, + x2 - x1 + 1, + y2 - y1 + 1, + x1, + y1 + ); + } + // Dispose of the wrapped gc. gc.dispose(); From f5010d8f07c6855db8077953b6ea3bb01b8b76d5 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Mon, 5 Sep 2022 17:05:23 +0200 Subject: [PATCH 02/25] Iterate --- packages/datagrid/src/datagrid.ts | 94 ++++++++++++++++--------------- 1 file changed, 49 insertions(+), 45 deletions(-) diff --git a/packages/datagrid/src/datagrid.ts b/packages/datagrid/src/datagrid.ts index 6a0cde3ef..a3885c7f0 100644 --- a/packages/datagrid/src/datagrid.ts +++ b/packages/datagrid/src/datagrid.ts @@ -3484,7 +3484,7 @@ export class DataGrid extends Widget { let x = this.headerWidth + this._columnSections.offsetOf(c); this.paintContent(x, 0, vw - x, vh); } else if (delta < 0) { - this.paintContent(vw + delta, 0, -delta + 1, vh); + this.paintContent(vw + delta, 0, -delta, vh); } // Paint the overlay. @@ -3585,7 +3585,7 @@ export class DataGrid extends Widget { let y = this.headerHeight + this._rowSections.offsetOf(r); this.paintContent(0, y, vw, vh - y); } else if (delta < 0) { - this.paintContent(0, vh + delta, vw, -delta + 1); + this.paintContent(0, vh + delta, vw, -delta); } // Paint the overlay. @@ -4668,30 +4668,30 @@ export class DataGrid extends Widget { // after the move, new region contains entirety of the merge groups rgn = JSONExt.deepCopy(rgn); - const joinedGroup = CellGroup.joinCellGroupWithMergedCellGroups( - this.dataModel!, - { - r1: rgn.row, - r2: rgn.row + rgn.rowSizes.length - 1, - c1: rgn.column, - c2: rgn.column + rgn.columnSizes.length - 1 - }, - rgn.region - ); + // const joinedGroup = CellGroup.joinCellGroupWithMergedCellGroups( + // this.dataModel!, + // { + // r1: rgn.row, + // r2: rgn.row + rgn.rowSizes.length - 1, + // c1: rgn.column, + // c2: rgn.column + rgn.columnSizes.length - 1 + // }, + // rgn.region + // ); - for (let r = joinedGroup.r1; r < rgn.row; r++) { - const h = this._getRowSize(rgn.region, r); - rgn.y -= h; - rgn.rowSizes = [h].concat(rgn.rowSizes); - } - rgn.row = joinedGroup.r1; + // for (let r = joinedGroup.r1; r < rgn.row; r++) { + // const h = this._getRowSize(rgn.region, r); + // rgn.y -= h; + // rgn.rowSizes = [h].concat(rgn.rowSizes); + // } + // rgn.row = joinedGroup.r1; - for (let c = joinedGroup.c1; c < rgn.column; c++) { - const w = this._getColumnSize(rgn.region, c); - rgn.x -= w; - rgn.columnSizes = [w].concat(rgn.columnSizes); - } - rgn.column = joinedGroup.c1; + // for (let c = joinedGroup.c1; c < rgn.column; c++) { + // const w = this._getColumnSize(rgn.region, c); + // rgn.x -= w; + // rgn.columnSizes = [w].concat(rgn.columnSizes); + // } + // rgn.column = joinedGroup.c1; // Set up the cell config object for rendering. let config = { @@ -4794,10 +4794,6 @@ export class DataGrid extends Widget { // Clear the buffer rect for the cell. gc.clearRect(x, y, width, height); - // Why are there two saves? - // Save the GC state. - gc.save(); - // Get the value for the cell. let value: any; try { @@ -4832,9 +4828,6 @@ export class DataGrid extends Widget { // Paint the cell into the off-screen buffer. try { - if (groupIndex !== -1) { - console.log('drawing merged cell anyway') - } renderer.paint(gc, config); } catch (err) { console.error(err); @@ -4897,16 +4890,6 @@ export class DataGrid extends Widget { ); for (const group of cellGroups) { - let x = 0; - for (let c = 0; c < group.c1; c++) { - x += this._getColumnSize(rgn.region, c); - } - - let y = 0; - for (let r = 0; r < group.r1; r++) { - y += this._getRowSize(rgn.region, r); - } - let width = 0; for (let c = group.c1; c <= group.c2; c++) { width += this._getColumnSize(rgn.region, c); @@ -4934,8 +4917,29 @@ export class DataGrid extends Widget { console.error(err); } - config.x = rgn.x + x; - config.y = rgn.y + y; + let x = 0; + let y = 0; + switch (rgn.region) { + case 'body': + x = this._columnSections.offsetOf(group.c1) + this.headerWidth - this._scrollX; + y = this._rowSections.offsetOf(group.r1) + this.headerHeight - this._scrollY; + break; + case 'column-header': + x = this._columnSections.offsetOf(group.c1) + this.headerWidth - this._scrollX; + y = this._rowSections.offsetOf(group.r1) - this._scrollY; + break; + case 'row-header': + x = this._columnSections.offsetOf(group.c1) - this._scrollX; + y = this._rowSections.offsetOf(group.r1) + this.headerHeight - this._scrollY; + break; + case 'corner-header': + x = this._columnSections.offsetOf(group.c1); + y = this._rowSections.offsetOf(group.r1); + break; + } + + config.x = x; + config.y = y; config.width = width; config.height = height; config.region = rgn.region; @@ -4944,13 +4948,13 @@ export class DataGrid extends Widget { config.value = value; config.metadata = metadata; - console.log('trying to draw', JSON.stringify(config)) + // console.log('trying to draw', JSON.stringify(config)) // Get the renderer for the cell. let renderer = this._cellRenderers.get(config); // Clear the buffer rect for the cell. - gc.clearRect(x, y, width, height); + gc.clearRect(config.x, config.y, width, height); // Save the GC state. gc.save(); From e134881b7db1e39a0df802150895aaf645f5b470 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Tue, 6 Sep 2022 10:16:16 +0200 Subject: [PATCH 03/25] Iterate --- packages/datagrid/src/cellgroup.ts | 73 ------------------ packages/datagrid/src/datagrid.ts | 116 ++++++----------------------- 2 files changed, 23 insertions(+), 166 deletions(-) diff --git a/packages/datagrid/src/cellgroup.ts b/packages/datagrid/src/cellgroup.ts index 689fb7f62..7aaa087ff 100644 --- a/packages/datagrid/src/cellgroup.ts +++ b/packages/datagrid/src/cellgroup.ts @@ -4,7 +4,6 @@ */ import { DataModel } from './datamodel'; -import { SectionList } from './sectionlist'; /** * An interface describing a merged cell group. @@ -52,78 +51,6 @@ export namespace CellGroup { return false; } - /** - * Calculates the cell boundary offsets needed for - * a row or column at the given index by taking - * into account merged cell groups in the region. - * @param dataModel - * @param regions - * @param axis - * @param sectionList - * @param index - */ - export function calculateMergeOffsets( - dataModel: DataModel, - regions: DataModel.CellRegion[], - axis: 'row' | 'column', - sectionList: SectionList, - index: number - ): [number, number, CellGroup] { - let mergeStartOffset = 0; - let mergeEndOffset = 0; - let mergedCellGroups: CellGroup[] = []; - - for (const region of regions) { - mergedCellGroups = mergedCellGroups.concat( - getCellGroupsAtRegion(dataModel, region) - ); - } - - let groupsAtAxis: CellGroup[] = []; - - if (axis === 'row') { - for (const region of regions) { - groupsAtAxis = groupsAtAxis.concat( - getCellGroupsAtRow(dataModel, region, index) - ); - } - } else { - for (const region of regions) { - groupsAtAxis = groupsAtAxis.concat( - getCellGroupsAtColumn(dataModel, region, index) - ); - } - } - - if (groupsAtAxis.length === 0) { - return [0, 0, { r1: -1, r2: -1, c1: -1, c2: -1 }]; - } - - let joinedGroup = groupsAtAxis[0]; - - for (let g = 0; g < mergedCellGroups.length; g++) { - const group = mergedCellGroups[g]; - if (areCellGroupsIntersectingAtAxis(joinedGroup, group, axis)) { - joinedGroup = joinCellGroups([group, joinedGroup]); - mergedCellGroups.splice(g, 1); - g = 0; - } - } - - let minRow = joinedGroup.r1; - let maxRow = joinedGroup.r2; - - for (let r = index - 1; r >= minRow; r--) { - mergeStartOffset += sectionList.sizeOf(r); - } - - for (let r = index + 1; r <= maxRow; r++) { - mergeEndOffset += sectionList.sizeOf(r); - } - - return [mergeStartOffset, mergeEndOffset, joinedGroup]; - } - /** * Checks if two cell-groups are intersecting * in the given axis. diff --git a/packages/datagrid/src/datagrid.ts b/packages/datagrid/src/datagrid.ts index a3885c7f0..8a3d5c691 100644 --- a/packages/datagrid/src/datagrid.ts +++ b/packages/datagrid/src/datagrid.ts @@ -2146,7 +2146,7 @@ export class DataGrid extends Widget { } // Test whether there is content to blit. - let needBlit = curH > 0 && curH > 0 && width > 0 && height > 0; + let needBlit = curW > 0 && curH > 0 && width > 0 && height > 0; // Copy the valid canvas content into the buffer if needed. if (needBlit) { @@ -4652,47 +4652,10 @@ export class DataGrid extends Widget { return; } - // // Determine if the region intersects with a merged group at row or column - // let intersectingColumnGroups = CellGroup.getCellGroupsAtColumn( - // this._dataModel!, - // rgn.region, - // rgn.column - // ); - // let intersectingRowGroups = CellGroup.getCellGroupsAtRow( - // this._dataModel!, - // rgn.region, - // rgn.row - // ); - // move the bounds of the region if edges of the region are part of a merge group. // after the move, new region contains entirety of the merge groups rgn = JSONExt.deepCopy(rgn); - // const joinedGroup = CellGroup.joinCellGroupWithMergedCellGroups( - // this.dataModel!, - // { - // r1: rgn.row, - // r2: rgn.row + rgn.rowSizes.length - 1, - // c1: rgn.column, - // c2: rgn.column + rgn.columnSizes.length - 1 - // }, - // rgn.region - // ); - - // for (let r = joinedGroup.r1; r < rgn.row; r++) { - // const h = this._getRowSize(rgn.region, r); - // rgn.y -= h; - // rgn.rowSizes = [h].concat(rgn.rowSizes); - // } - // rgn.row = joinedGroup.r1; - - // for (let c = joinedGroup.c1; c < rgn.column; c++) { - // const w = this._getColumnSize(rgn.region, c); - // rgn.x -= w; - // rgn.columnSizes = [w].concat(rgn.columnSizes); - // } - // rgn.column = joinedGroup.c1; - // Set up the cell config object for rendering. let config = { x: 0, @@ -4718,9 +4681,6 @@ export class DataGrid extends Widget { // Loop over the columns in the region. for (let x = rgn.x, i = 0, n = rgn.columnSizes.length; i < n; ++i) { - let xOffset = 0; - let yOffset = 0; - // Fetch the size of the column. let width = rgn.columnSizes[i]; @@ -4729,8 +4689,6 @@ export class DataGrid extends Widget { continue; } - xOffset = width; - // Compute the column index. let column = rgn.column + i; @@ -4758,37 +4716,11 @@ export class DataGrid extends Widget { row, column ); - yOffset = height; - /** - * For merged cell regions, don't do anything, we draw merged regions later. - */ + // For merged cell regions, don't do anything, we draw merged regions later. if (groupIndex !== -1) { - y += yOffset; + y += height; continue; - // const group = this.dataModel!.group(config.region, groupIndex)!; - // if (group.r1 === row && group.c1 === column) { - // width = 0; - // for (let c = group.c1; c <= group.c2; c++) { - // width += this._getColumnSize(config.region, c); - // } - - // height = 0; - // for (let r = group.r1; r <= group.r2; r++) { - // height += this._getRowSize(config.region, r); - // } - // } else { - // y += yOffset; - // continue; - // } - // } else { - // /** - // * Reset column width if we're rendering a column-header - // * which is not part of a merged cell group. - // */ - // if (rgn.region == 'column-header') { - // width = rgn.columnSizes[i]; - // } } // Clear the buffer rect for the cell. @@ -4844,23 +4776,6 @@ export class DataGrid extends Widget { let y1 = Math.max(rgn.yMin, config.y); let y2 = Math.min(config.y + config.height - 1, rgn.yMax); - // TODO Do we still need this? - // if ( - // intersectingColumnGroups.length !== 0 || - // intersectingRowGroups.length !== 0 - // ) { - // if (x2 > x1 && y2 > y1) { - // this._blitContent( - // this._buffer, - // x1, - // y1, - // x2 - x1 + 1, - // y2 - y1 + 1, - // x1, - // y1 - // ); - // } - // } else { this._blitContent( this._buffer, x1, @@ -4870,17 +4785,16 @@ export class DataGrid extends Widget { x1, y1 ); - // } // Increment the running Y coordinate. - y += yOffset; + y += height; } // Restore the GC state. gc.restore(); // Increment the running X coordinate. - x += xOffset; + x += width; } // Draw merged groups that intersects with the region @@ -4889,7 +4803,25 @@ export class DataGrid extends Widget { rgn.region ); + // TODO Move this in the utils dir (but we need the PaintRegion typing) + const intersects = (grp: CellGroup, rgn: Private.PaintRegion) => { + const rgnR1 = rgn.row; + const rgnR2 = rgn.row + rgn.rowSizes.length; + + const rgnC1 = rgn.column; + const rgnC2 = rgn.column + rgn.columnSizes.length; + + const dx = Math.min(grp.r2, rgnR2) - Math.max(grp.r1, rgnR1); + const dy = Math.min(grp.c2, rgnC2) - Math.max(grp.c1, rgnC1); + + return dx >= 0 && dy >= 0; + } + for (const group of cellGroups) { + if (!intersects(group, rgn)) { + continue; + } + let width = 0; for (let c = group.c1; c <= group.c2; c++) { width += this._getColumnSize(rgn.region, c); @@ -4948,8 +4880,6 @@ export class DataGrid extends Widget { config.value = value; config.metadata = metadata; - // console.log('trying to draw', JSON.stringify(config)) - // Get the renderer for the cell. let renderer = this._cellRenderers.get(config); From bf6904ad058bf13113c5d983c08a108e5ad35fcd Mon Sep 17 00:00:00 2001 From: martinRenou Date: Tue, 6 Sep 2022 10:20:50 +0200 Subject: [PATCH 04/25] Remove commented code and unused functions --- packages/datagrid/src/cellgroup.ts | 23 ----------------- packages/datagrid/src/datagrid.ts | 40 ------------------------------ 2 files changed, 63 deletions(-) diff --git a/packages/datagrid/src/cellgroup.ts b/packages/datagrid/src/cellgroup.ts index 7aaa087ff..47ab707b6 100644 --- a/packages/datagrid/src/cellgroup.ts +++ b/packages/datagrid/src/cellgroup.ts @@ -271,29 +271,6 @@ export namespace CellGroup { return groupsAtColumn; } - /** - * Checks if cell group 1 is above cell group 2. - * @param group1 cell group 1. - * @param group2 cell group 2. - * @returns boolean. - */ - export function isCellGroupAbove( - group1: CellGroup, - group2: CellGroup - ): boolean { - return group2.r2 >= group1.r1; - } - - /** - * Checks if cell group 1 is below cell group 2. - */ - export function isCellGroupBelow( - group1: CellGroup, - group2: CellGroup - ): boolean { - return group2.r1 <= group1.r2; - } - /** * Merges a target cell group with any cell groups * it intersects with at a given row or column. diff --git a/packages/datagrid/src/datagrid.ts b/packages/datagrid/src/datagrid.ts index 8a3d5c691..7ce38d420 100644 --- a/packages/datagrid/src/datagrid.ts +++ b/packages/datagrid/src/datagrid.ts @@ -3188,16 +3188,6 @@ export class DataGrid extends Widget { return; } - // Render entire grid if scrolling merged cells grid - // const paintEverything = Private.shouldPaintEverything(this._dataModel!); - - // if (paintEverything) { - // this.paintContent(0, 0, vw, vh); - // this._paintOverlay(); - // this._syncScrollState(); - // return; - // } - // Compute the size delta. let delta = newSize - oldSize; @@ -3310,16 +3300,6 @@ export class DataGrid extends Widget { return; } - // Render entire grid if scrolling merged cells grid - // const paintEverything = Private.shouldPaintEverything(this._dataModel!); - - // if (paintEverything) { - // this.paintContent(0, 0, vw, vh); - // this._paintOverlay(); - // this._syncScrollState(); - // return; - // } - // Compute the size delta. let delta = newSize - oldSize; @@ -3432,16 +3412,6 @@ export class DataGrid extends Widget { return; } - // Render entire grid if scrolling merged cells grid - // const paintEverything = Private.shouldPaintEverything(this._dataModel!); - - // if (paintEverything) { - // this.paintContent(0, 0, vw, vh); - // this._paintOverlay(); - // this._syncScrollState(); - // return; - // } - // Compute the size delta. let delta = newSize - oldSize; @@ -3530,16 +3500,6 @@ export class DataGrid extends Widget { return; } - // Render entire grid if scrolling merged cells grid - // const paintEverything = Private.shouldPaintEverything(this._dataModel!); - - // if (paintEverything) { - // this.paintContent(0, 0, vw, vh); - // this._paintOverlay(); - // this._syncScrollState(); - // return; - // } - // Paint the overlay. this._paintOverlay(); From 7801a85f29a738a8004c954ae0ffc7a230923f49 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Tue, 6 Sep 2022 17:10:34 +0200 Subject: [PATCH 05/25] Iterate --- packages/datagrid/src/datagrid.ts | 185 +++++++++++++++++++++++++----- 1 file changed, 156 insertions(+), 29 deletions(-) diff --git a/packages/datagrid/src/datagrid.ts b/packages/datagrid/src/datagrid.ts index 7ce38d420..3f3c0395f 100644 --- a/packages/datagrid/src/datagrid.ts +++ b/packages/datagrid/src/datagrid.ts @@ -39,8 +39,6 @@ import { ICellEditorController } from './celleditorcontroller'; -import { JSONExt } from '@lumino/coreutils'; - import { TextRenderer } from './textrenderer'; /** @@ -3355,11 +3353,17 @@ export class DataGrid extends Widget { // Blit the valid content to the destination. this._blitContent(this._canvas, sx, sy, sw, sh, dx, dy); + // this._canvasGC.lineWidth = 10; + // this._canvasGC.strokeRect(sx, sy, sw, sh); + // Repaint the section if needed. if (newSize > 0 && offset + newSize > hw) { this.paintContent(pos, 0, offset + newSize - pos, vh); } + // this._canvasGC.lineWidth = 10; + // this._canvasGC.strokeRect(pos, 0, offset + newSize - pos, vh); + // Paint the trailing space as needed. if (this._stretchLastColumn && this.pageWidth > this.bodyWidth) { let c = this._columnSections.count - 1; @@ -3369,6 +3373,19 @@ export class DataGrid extends Widget { this.paintContent(vw + delta, 0, -delta, vh); } + // Repaint merged cells that are intersected by the resized column + // Otherwise it will be cut in two and drawn incorrectly + + // x = this._columnSections.offsetOf(0) + this.headerWidth - this._scrollX; + // y = this._rowSections.offsetOf(group.r1) + this.headerHeight - this._scrollY; + + this.paintMergedCellsAtColumn( + 'body', index, + this._columnSections.offsetOf(0), 3000, + this._rowSections.offsetOf(0), 3000 + ); + // this.paintMergedCellsAtColumn('column-header', index); + // Paint the overlay. this._paintOverlay(); @@ -3764,6 +3781,56 @@ export class DataGrid extends Widget { this.drawCornerHeaderRegion(rx, ry, rw, rh); } + /** + * Force a repaint of cells group. + */ + // protected paintCellGroup(cellGroup: CellGroup, rgn: DataModel.CellRegion, xMin: number, xMax: number, yMin: number, yMax: number) { + // const mergedCellRegion: Private.PaintRegion = { + // region: rgn, + // xMin: , + // yMin: , + // xMax: x2, + // yMax: y2, + // x, + // y, + // width, + // height, + // row: r1, + // column: c1, + // rowSizes, + // columnSizes + // }; + + // Draw the background. + // this._drawBackground(mergedCellRegion, this._style.backgroundColor); + + // Draw the row background. + // this._drawRowBackground(mergedCellRegion, this._style.rowBackgroundColor); + + // Draw the column background. + // this._drawColumnBackground(mergedCellRegion, this._style.columnBackgroundColor); + + // this._drawCellGroup(cellGroup, mergedCellRegion); + // } + + /** + * Force a repaint of some grouped cells that are intersecting a given column. + */ + protected paintMergedCellsAtColumn(rgn: DataModel.CellRegion, index: number, xMin: number, xMax: number, yMin: number, yMax: number) { + const cellGroups = CellGroup.getCellGroupsAtColumn(this.dataModel!, rgn, index); + + this._drawMergedCellsGroups(cellGroups, rgn, xMin, yMin, xMax, yMax); + } + + /** + * Force a repaint of some grouped cells that are intersecting a given row. + */ + protected paintMergedCellsAtRow(rgn: DataModel.CellRegion, index: number, xMin: number, xMax: number, yMin: number, yMax: number) { + const cellGroups = CellGroup.getCellGroupsAtRow(this.dataModel!, rgn, index); + + this._drawMergedCellsGroups(cellGroups, rgn, xMin, yMin, xMax, yMax); + } + /** * Resizes body column headers so their text fits * without clipping or wrapping. @@ -4073,6 +4140,9 @@ export class DataGrid extends Widget { // Draw the cell content for the paint region. this._drawCells(rgn); + // Draw the cell groups for the paint region + this._drawMergedCells(rgn); + // Draw the horizontal grid lines. this._drawHorizontalGridLines( rgn, @@ -4207,6 +4277,9 @@ export class DataGrid extends Widget { // Draw the cell content for the paint region. this._drawCells(rgn); + // Draw the cell groups for the paint region + this._drawMergedCells(rgn); + // Draw the horizontal grid lines. this._drawHorizontalGridLines( rgn, @@ -4342,6 +4415,9 @@ export class DataGrid extends Widget { // Draw the cell content for the paint region. this._drawCells(rgn); + // Draw the cell groups for the paint region + this._drawMergedCells(rgn); + // Draw the horizontal grid lines. this._drawHorizontalGridLines( rgn, @@ -4461,6 +4537,9 @@ export class DataGrid extends Widget { // Draw the cell content for the paint region. this._drawCells(rgn); + // Draw the cell groups for the paint region + this._drawMergedCells(rgn); + // Draw the horizontal grid lines. this._drawHorizontalGridLines( rgn, @@ -4612,10 +4691,6 @@ export class DataGrid extends Widget { return; } - // move the bounds of the region if edges of the region are part of a merge group. - // after the move, new region contains entirety of the merge groups - rgn = JSONExt.deepCopy(rgn); - // Set up the cell config object for rendering. let config = { x: 0, @@ -4757,11 +4832,21 @@ export class DataGrid extends Widget { x += width; } - // Draw merged groups that intersects with the region - const cellGroups = CellGroup.getCellGroupsAtRegion( - this.dataModel!, - rgn.region - ); + // Dispose of the wrapped gc. + gc.dispose(); + + // Restore the final buffer gc state. + this._bufferGC.restore(); + } + + /** + * Draw the cell groups for the given paint region. + */ + private _drawMergedCells(rgn: Private.PaintRegion): void { + // Bail if there is no data model. + if (!this._dataModel) { + return; + } // TODO Move this in the utils dir (but we need the PaintRegion typing) const intersects = (grp: CellGroup, rgn: Private.PaintRegion) => { @@ -4777,24 +4862,59 @@ export class DataGrid extends Widget { return dx >= 0 && dy >= 0; } - for (const group of cellGroups) { - if (!intersects(group, rgn)) { - continue; - } + // Draw only merged groups that intersects with the region + const cellGroups = CellGroup.getCellGroupsAtRegion( + this.dataModel!, + rgn.region + ).filter((group) => { + return intersects(group, rgn); + }); + + return this._drawMergedCellsGroups(cellGroups, rgn.region, rgn.xMin, rgn.yMin, rgn.xMax, rgn.yMax); + } + + /** + * Draw the given cell groups. + */ + private _drawMergedCellsGroups(cellGroups: CellGroup[], rgn: DataModel.CellRegion, xMin: number, yMin: number, xMax: number, yMax: number): void { + // Bail if there is no data model. + if (!this._dataModel) { + return; + } + // Set up the cell config object for rendering. + let config = { + x: 0, + y: 0, + width: 0, + height: 0, + region: rgn, + row: 0, + column: 0, + value: null as any, + metadata: DataModel.emptyMetadata + }; + + // Save the buffer gc before wrapping. + this._bufferGC.save(); + + // Wrap the buffer gc for painting the cells. + let gc = new GraphicsContext(this._bufferGC); + + for (const group of cellGroups) { let width = 0; for (let c = group.c1; c <= group.c2; c++) { - width += this._getColumnSize(rgn.region, c); + width += this._getColumnSize(rgn, c); } let height = 0; for (let r = group.r1; r <= group.r2; r++) { - height += this._getRowSize(rgn.region, r); + height += this._getRowSize(rgn, r); } let value: any; try { - value = this._dataModel.data(rgn.region, group.r1, group.c1); + value = this._dataModel.data(rgn, group.r1, group.c1); } catch (err) { value = undefined; console.error(err); @@ -4803,7 +4923,7 @@ export class DataGrid extends Widget { // Get the metadata for the cell. let metadata: DataModel.Metadata; try { - metadata = this._dataModel.metadata(rgn.region, group.r1, group.c1); + metadata = this._dataModel.metadata(rgn, group.r1, group.c1); } catch (err) { metadata = DataModel.emptyMetadata; console.error(err); @@ -4811,7 +4931,7 @@ export class DataGrid extends Widget { let x = 0; let y = 0; - switch (rgn.region) { + switch (rgn) { case 'body': x = this._columnSections.offsetOf(group.c1) + this.headerWidth - this._scrollX; y = this._rowSections.offsetOf(group.r1) + this.headerHeight - this._scrollY; @@ -4834,18 +4954,33 @@ export class DataGrid extends Widget { config.y = y; config.width = width; config.height = height; - config.region = rgn.region; + config.region = rgn; config.row = group.r1; config.column = group.c1; config.value = value; config.metadata = metadata; + // Compute the actual X bounds for the cell. + let x1 = Math.max(xMin, config.x); + let x2 = Math.min(config.x + config.width - 1, xMax); + + // Compute the actual Y bounds for the cell. + let y1 = Math.max(yMin, config.y); + let y2 = Math.min(config.y + config.height - 1, yMax); + // Get the renderer for the cell. let renderer = this._cellRenderers.get(config); // Clear the buffer rect for the cell. gc.clearRect(config.x, config.y, width, height); + // TODO Remove this workaround + // Fill the region with the specified color. + gc.save(); + this._canvasGC.fillStyle = this._style.backgroundColor!; + this._canvasGC.fillRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1); + gc.restore(); + // Save the GC state. gc.save(); @@ -4859,14 +4994,6 @@ export class DataGrid extends Widget { // Restore the GC state. gc.restore(); - // Compute the actual X bounds for the cell. - let x1 = Math.max(rgn.xMin, config.x); - let x2 = Math.min(config.x + config.width - 1, rgn.xMax); - - // Compute the actual Y bounds for the cell. - let y1 = Math.max(rgn.yMin, config.y); - let y2 = Math.min(config.y + config.height - 1, rgn.yMax); - this._blitContent( this._buffer, x1, From de11b2bcfc9e292f4204ba233c973b1170a3a3dd Mon Sep 17 00:00:00 2001 From: martinRenou Date: Wed, 7 Sep 2022 10:32:53 +0200 Subject: [PATCH 06/25] Iterate --- packages/datagrid/src/datagrid.ts | 285 +++++++++++++++++++++--------- 1 file changed, 202 insertions(+), 83 deletions(-) diff --git a/packages/datagrid/src/datagrid.ts b/packages/datagrid/src/datagrid.ts index 3f3c0395f..4c06c7e72 100644 --- a/packages/datagrid/src/datagrid.ts +++ b/packages/datagrid/src/datagrid.ts @@ -3353,17 +3353,11 @@ export class DataGrid extends Widget { // Blit the valid content to the destination. this._blitContent(this._canvas, sx, sy, sw, sh, dx, dy); - // this._canvasGC.lineWidth = 10; - // this._canvasGC.strokeRect(sx, sy, sw, sh); - // Repaint the section if needed. if (newSize > 0 && offset + newSize > hw) { this.paintContent(pos, 0, offset + newSize - pos, vh); } - // this._canvasGC.lineWidth = 10; - // this._canvasGC.strokeRect(pos, 0, offset + newSize - pos, vh); - // Paint the trailing space as needed. if (this._stretchLastColumn && this.pageWidth > this.bodyWidth) { let c = this._columnSections.count - 1; @@ -3374,17 +3368,49 @@ export class DataGrid extends Widget { } // Repaint merged cells that are intersected by the resized column - // Otherwise it will be cut in two and drawn incorrectly + // Otherwise it will be cut in two by the valid content, and drawn incorrectly + for (const rgn of ['body', 'column-header'] as DataModel.CellRegion[]) { + const cellGroups = CellGroup.getCellGroupsAtColumn(this.dataModel!, rgn, index); + + // TODO We're not creating a fully implemented paint-region, + // We probably need another type + let paintRgn = { + region: rgn, + xMin: 0, + xMax: 0, + yMin: 0, + yMax: 0 + }; + + switch (rgn) { + case 'body': + paintRgn.xMin = this.headerWidth; + paintRgn.xMax = this.headerWidth + this.bodyWidth; + paintRgn.yMin = this.headerHeight; + paintRgn.yMax = this.headerHeight + this.bodyHeight; + break; + case 'column-header': + paintRgn.xMin = this.headerWidth; + paintRgn.xMax = this.headerWidth + this.bodyWidth; + paintRgn.yMin = 0; + paintRgn.yMax = this.headerHeight; + break; + } - // x = this._columnSections.offsetOf(0) + this.headerWidth - this._scrollX; - // y = this._rowSections.offsetOf(group.r1) + this.headerHeight - this._scrollY; + // Draw the background for merged cells + this._drawMergedCellsBackground(cellGroups, paintRgn as Private.PaintRegion, this._style.backgroundColor); - this.paintMergedCellsAtColumn( - 'body', index, - this._columnSections.offsetOf(0), 3000, - this._rowSections.offsetOf(0), 3000 - ); - // this.paintMergedCellsAtColumn('column-header', index); + // Draw the cell groups for the paint region + this._drawMergedCells(cellGroups, paintRgn as Private.PaintRegion); + + // Draw grid lines close to merged cells + // this._drawMergedCellsBorder( + // cellGroups, + // rgn, + // this._style.horizontalGridLineColor || this._style.gridLineColor, + // this._style.verticalGridLineColor || this._style.gridLineColor + // ); + } // Paint the overlay. this._paintOverlay(); @@ -3813,23 +3839,23 @@ export class DataGrid extends Widget { // this._drawCellGroup(cellGroup, mergedCellRegion); // } - /** - * Force a repaint of some grouped cells that are intersecting a given column. - */ - protected paintMergedCellsAtColumn(rgn: DataModel.CellRegion, index: number, xMin: number, xMax: number, yMin: number, yMax: number) { - const cellGroups = CellGroup.getCellGroupsAtColumn(this.dataModel!, rgn, index); + // /** + // * Force a repaint of some grouped cells that are intersecting a given column. + // */ + // protected paintMergedCellsAtColumn(rgn: DataModel.CellRegion, index: number, xMin: number, xMax: number, yMin: number, yMax: number) { + // const cellGroups = CellGroup.getCellGroupsAtColumn(this.dataModel!, rgn, index); - this._drawMergedCellsGroups(cellGroups, rgn, xMin, yMin, xMax, yMax); - } + // this._drawMergedCellsGroups(cellGroups, rgn, xMin, yMin, xMax, yMax); + // } - /** - * Force a repaint of some grouped cells that are intersecting a given row. - */ - protected paintMergedCellsAtRow(rgn: DataModel.CellRegion, index: number, xMin: number, xMax: number, yMin: number, yMax: number) { - const cellGroups = CellGroup.getCellGroupsAtRow(this.dataModel!, rgn, index); + // /** + // * Force a repaint of some grouped cells that are intersecting a given row. + // */ + // protected paintMergedCellsAtRow(rgn: DataModel.CellRegion, index: number, xMin: number, xMax: number, yMin: number, yMax: number) { + // const cellGroups = CellGroup.getCellGroupsAtRow(this.dataModel!, rgn, index); - this._drawMergedCellsGroups(cellGroups, rgn, xMin, yMin, xMax, yMax); - } + // this._drawMergedCellsGroups(cellGroups, rgn, xMin, yMin, xMax, yMax); + // } /** * Resizes body column headers so their text fits @@ -4140,9 +4166,6 @@ export class DataGrid extends Widget { // Draw the cell content for the paint region. this._drawCells(rgn); - // Draw the cell groups for the paint region - this._drawMergedCells(rgn); - // Draw the horizontal grid lines. this._drawHorizontalGridLines( rgn, @@ -4154,6 +4177,28 @@ export class DataGrid extends Widget { rgn, this._style.verticalGridLineColor || this._style.gridLineColor ); + + // Get the cellgroups from the cell-region that intersects with the paint region + const cellGroups = CellGroup.getCellGroupsAtRegion( + this.dataModel!, + rgn.region + ).filter(group => { + return this.cellGroupInteresectsRegion(group, rgn); + }); + + // Draw the background for merged cells + this._drawMergedCellsBackground(cellGroups, rgn, this._style.backgroundColor); + + // Draw the cell groups for the paint region + this._drawMergedCells(cellGroups, rgn); + + // Draw grid lines close to merged cells + // this._drawMergedCellsBorder( + // cellGroups, + // rgn, + // this._style.horizontalGridLineColor || this._style.gridLineColor, + // this._style.verticalGridLineColor || this._style.gridLineColor + // ); } /** @@ -4277,9 +4322,6 @@ export class DataGrid extends Widget { // Draw the cell content for the paint region. this._drawCells(rgn); - // Draw the cell groups for the paint region - this._drawMergedCells(rgn); - // Draw the horizontal grid lines. this._drawHorizontalGridLines( rgn, @@ -4292,6 +4334,20 @@ export class DataGrid extends Widget { rgn, this._style.headerVerticalGridLineColor || this._style.headerGridLineColor ); + + // Get the cellgroups from the cell-region that intersects with the paint region + const cellGroups = CellGroup.getCellGroupsAtRegion( + this.dataModel!, + rgn.region + ).filter(group => { + return this.cellGroupInteresectsRegion(group, rgn); + }); + + // Draw the background for merged cells + this._drawMergedCellsBackground(cellGroups, rgn, this._style.headerBackgroundColor); + + // Draw the cell groups for the paint region + this._drawMergedCells(cellGroups, rgn); } /** @@ -4415,9 +4471,6 @@ export class DataGrid extends Widget { // Draw the cell content for the paint region. this._drawCells(rgn); - // Draw the cell groups for the paint region - this._drawMergedCells(rgn); - // Draw the horizontal grid lines. this._drawHorizontalGridLines( rgn, @@ -4430,6 +4483,20 @@ export class DataGrid extends Widget { rgn, this._style.headerVerticalGridLineColor || this._style.headerGridLineColor ); + + // Get the cellgroups from the cell-region that intersects with the paint region + const cellGroups = CellGroup.getCellGroupsAtRegion( + this.dataModel!, + rgn.region + ).filter(group => { + return this.cellGroupInteresectsRegion(group, rgn); + }); + + // Draw the background for merged cells + this._drawMergedCellsBackground(cellGroups, rgn, this._style.headerBackgroundColor); + + // Draw the cell groups for the paint region + this._drawMergedCells(cellGroups, rgn); } /** @@ -4537,9 +4604,6 @@ export class DataGrid extends Widget { // Draw the cell content for the paint region. this._drawCells(rgn); - // Draw the cell groups for the paint region - this._drawMergedCells(rgn); - // Draw the horizontal grid lines. this._drawHorizontalGridLines( rgn, @@ -4552,6 +4616,20 @@ export class DataGrid extends Widget { rgn, this._style.headerVerticalGridLineColor || this._style.headerGridLineColor ); + + // Get the cellgroups from the cell-region that intersects with the paint region + const cellGroups = CellGroup.getCellGroupsAtRegion( + this.dataModel!, + rgn.region + ).filter(group => { + return this.cellGroupInteresectsRegion(group, rgn); + }); + + // Draw the background for merged cells + this._drawMergedCellsBackground(cellGroups, rgn, this._style.headerBackgroundColor); + + // Draw the cell groups for the paint region + this._drawMergedCells(cellGroups, rgn); } /** @@ -4839,44 +4917,92 @@ export class DataGrid extends Widget { this._bufferGC.restore(); } + // TODO Move this in the utils file (but we need the PaintRegion typing) + private cellGroupInteresectsRegion(group: CellGroup, rgn: Private.PaintRegion) { + const rgnR1 = rgn.row; + const rgnR2 = rgn.row + rgn.rowSizes.length; + + const rgnC1 = rgn.column; + const rgnC2 = rgn.column + rgn.columnSizes.length; + + const dx = Math.min(group.r2, rgnR2) - Math.max(group.r1, rgnR1); + const dy = Math.min(group.c2, rgnC2) - Math.max(group.c1, rgnC1); + + return dx >= 0 && dy >= 0; + } + /** - * Draw the cell groups for the given paint region. + * Draw the background for given group cells. */ - private _drawMergedCells(rgn: Private.PaintRegion): void { - // Bail if there is no data model. - if (!this._dataModel) { + private _drawMergedCellsBackground( + cellGroups: CellGroup[], + rgn: Private.PaintRegion, + color: string | undefined + ): void { + // Bail if there is no color to draw. + if (!color) { return; } - // TODO Move this in the utils dir (but we need the PaintRegion typing) - const intersects = (grp: CellGroup, rgn: Private.PaintRegion) => { - const rgnR1 = rgn.row; - const rgnR2 = rgn.row + rgn.rowSizes.length; + // Unpack the region. + let { xMin, yMin, xMax, yMax } = rgn; - const rgnC1 = rgn.column; - const rgnC2 = rgn.column + rgn.columnSizes.length; + this._canvasGC.fillStyle = color; - const dx = Math.min(grp.r2, rgnR2) - Math.max(grp.r1, rgnR1); - const dy = Math.min(grp.c2, rgnC2) - Math.max(grp.c1, rgnC1); + for (const group of cellGroups) { + let width = 0; + for (let c = group.c1; c <= group.c2; c++) { + width += this._getColumnSize(rgn.region, c); + } - return dx >= 0 && dy >= 0; - } + let height = 0; + for (let r = group.r1; r <= group.r2; r++) { + height += this._getRowSize(rgn.region, r); + } - // Draw only merged groups that intersects with the region - const cellGroups = CellGroup.getCellGroupsAtRegion( - this.dataModel!, - rgn.region - ).filter((group) => { - return intersects(group, rgn); - }); + let x = 0; + let y = 0; + switch (rgn.region) { + case 'body': + x = this._columnSections.offsetOf(group.c1) + this.headerWidth - this._scrollX; + y = this._rowSections.offsetOf(group.r1) + this.headerHeight - this._scrollY; + break; + case 'column-header': + x = this._columnSections.offsetOf(group.c1) + this.headerWidth - this._scrollX; + y = this._rowSections.offsetOf(group.r1) - this._scrollY; + break; + case 'row-header': + x = this._columnSections.offsetOf(group.c1) - this._scrollX; + y = this._rowSections.offsetOf(group.r1) + this.headerHeight - this._scrollY; + break; + case 'corner-header': + x = this._columnSections.offsetOf(group.c1); + y = this._rowSections.offsetOf(group.r1); + break; + } + + // Compute the actual X bounds for the cell. + let x1 = Math.max(xMin, x); + let x2 = Math.min(x + width - 1, xMax); - return this._drawMergedCellsGroups(cellGroups, rgn.region, rgn.xMin, rgn.yMin, rgn.xMax, rgn.yMax); + // Compute the actual Y bounds for the cell. + let y1 = Math.max(yMin, y); + let y2 = Math.min(y + height - 1, yMax); + + // Fill the region with the specified color. + this._canvasGC.fillRect( + x1, + y1, + x2 - x1 + 1, + y2 - y1 + 1 + ); + } } /** - * Draw the given cell groups. + * Draw the cell groups for the given paint region. */ - private _drawMergedCellsGroups(cellGroups: CellGroup[], rgn: DataModel.CellRegion, xMin: number, yMin: number, xMax: number, yMax: number): void { + private _drawMergedCells(cellGroups: CellGroup[], rgn: Private.PaintRegion): void { // Bail if there is no data model. if (!this._dataModel) { return; @@ -4888,7 +5014,7 @@ export class DataGrid extends Widget { y: 0, width: 0, height: 0, - region: rgn, + region: rgn.region, row: 0, column: 0, value: null as any, @@ -4904,17 +5030,17 @@ export class DataGrid extends Widget { for (const group of cellGroups) { let width = 0; for (let c = group.c1; c <= group.c2; c++) { - width += this._getColumnSize(rgn, c); + width += this._getColumnSize(rgn.region, c); } let height = 0; for (let r = group.r1; r <= group.r2; r++) { - height += this._getRowSize(rgn, r); + height += this._getRowSize(rgn.region, r); } let value: any; try { - value = this._dataModel.data(rgn, group.r1, group.c1); + value = this._dataModel.data(rgn.region, group.r1, group.c1); } catch (err) { value = undefined; console.error(err); @@ -4923,7 +5049,7 @@ export class DataGrid extends Widget { // Get the metadata for the cell. let metadata: DataModel.Metadata; try { - metadata = this._dataModel.metadata(rgn, group.r1, group.c1); + metadata = this._dataModel.metadata(rgn.region, group.r1, group.c1); } catch (err) { metadata = DataModel.emptyMetadata; console.error(err); @@ -4931,7 +5057,7 @@ export class DataGrid extends Widget { let x = 0; let y = 0; - switch (rgn) { + switch (rgn.region) { case 'body': x = this._columnSections.offsetOf(group.c1) + this.headerWidth - this._scrollX; y = this._rowSections.offsetOf(group.r1) + this.headerHeight - this._scrollY; @@ -4954,19 +5080,19 @@ export class DataGrid extends Widget { config.y = y; config.width = width; config.height = height; - config.region = rgn; + config.region = rgn.region; config.row = group.r1; config.column = group.c1; config.value = value; config.metadata = metadata; // Compute the actual X bounds for the cell. - let x1 = Math.max(xMin, config.x); - let x2 = Math.min(config.x + config.width - 1, xMax); + let x1 = Math.max(rgn.xMin, config.x); + let x2 = Math.min(config.x + config.width - 1, rgn.xMax); // Compute the actual Y bounds for the cell. - let y1 = Math.max(yMin, config.y); - let y2 = Math.min(config.y + config.height - 1, yMax); + let y1 = Math.max(rgn.yMin, config.y); + let y2 = Math.min(config.y + config.height - 1, rgn.yMax); // Get the renderer for the cell. let renderer = this._cellRenderers.get(config); @@ -4974,13 +5100,6 @@ export class DataGrid extends Widget { // Clear the buffer rect for the cell. gc.clearRect(config.x, config.y, width, height); - // TODO Remove this workaround - // Fill the region with the specified color. - gc.save(); - this._canvasGC.fillStyle = this._style.backgroundColor!; - this._canvasGC.fillRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1); - gc.restore(); - // Save the GC state. gc.save(); From ce7e13f35f23ac5ca26d559f8e2f304a7fbfcec8 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Wed, 7 Sep 2022 10:48:33 +0200 Subject: [PATCH 07/25] Remove merged cells handling in linegrid drawing --- packages/datagrid/src/cellgroup.ts | 28 ----------------- packages/datagrid/src/datagrid.ts | 48 +++++------------------------- 2 files changed, 8 insertions(+), 68 deletions(-) diff --git a/packages/datagrid/src/cellgroup.ts b/packages/datagrid/src/cellgroup.ts index 47ab707b6..92a22e265 100644 --- a/packages/datagrid/src/cellgroup.ts +++ b/packages/datagrid/src/cellgroup.ts @@ -23,34 +23,6 @@ export interface CellGroup { * A collection of helper functions relating to merged cell groups */ export namespace CellGroup { - export function areCellsMerged( - dataModel: DataModel, - rgn: DataModel.CellRegion, - cell1: number[], - cell2: number[] - ): boolean { - const numGroups = dataModel.groupCount(rgn); - const [row1, column1] = cell1; - const [row2, column2] = cell2; - - for (let i = 0; i < numGroups; i++) { - const group = dataModel.group(rgn, i)!; - if ( - row1 >= group.r1 && - row1 <= group.r2 && - column1 >= group.c1 && - column1 <= group.c2 && - row2 >= group.r1 && - row2 <= group.r2 && - column2 >= group.c1 && - column2 <= group.c2 - ) { - return true; - } - } - return false; - } - /** * Checks if two cell-groups are intersecting * in the given axis. diff --git a/packages/datagrid/src/datagrid.ts b/packages/datagrid/src/datagrid.ts index 4c06c7e72..7585c8e46 100644 --- a/packages/datagrid/src/datagrid.ts +++ b/packages/datagrid/src/datagrid.ts @@ -5183,26 +5183,10 @@ export class DataGrid extends Widget { for (let c = rgn.column; c < rgn.column + rgn.columnSizes.length; c++) { const cIndex = c - rgn.column; - const cellUp = [rgn.row + j, c]; - const cellDown = [rgn.row + j + 1, c]; - - if ( - CellGroup.areCellsMerged( - this.dataModel!, - rgn.region, - cellUp, - cellDown - ) - ) { - if (lineStarted) { - lines.push([xStart, leftCurrent]); - } - lineStarted = false; - } else { - if (!lineStarted) { - lineStarted = true; - xStart = leftCurrent; - } + + if (!lineStarted) { + lineStarted = true; + xStart = leftCurrent; } leftCurrent += rgn.columnSizes[cIndex]; @@ -5296,26 +5280,10 @@ export class DataGrid extends Widget { for (let r = rgn.row; r < rgn.row + rgn.rowSizes.length; r++) { const rIndex = r - rgn.row; - const cellLeft = [r, rgn.column + i]; - const cellRight = [r, rgn.column + i + 1]; - - if ( - CellGroup.areCellsMerged( - this.dataModel!, - rgn.region, - cellLeft, - cellRight - ) - ) { - if (lineStarted) { - lines.push([yStart, topCurrent]); - } - lineStarted = false; - } else { - if (!lineStarted) { - lineStarted = true; - yStart = topCurrent; - } + + if (!lineStarted) { + lineStarted = true; + yStart = topCurrent; } topCurrent += rgn.rowSizes[rIndex]; From 55a043156f8f4893f74311f28b3e3ed665b9e1f3 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Wed, 7 Sep 2022 10:56:33 +0200 Subject: [PATCH 08/25] Finally remove "shouldPaintEverything" --- packages/datagrid/src/datagrid.ts | 177 ++++++++++-------------------- 1 file changed, 61 insertions(+), 116 deletions(-) diff --git a/packages/datagrid/src/datagrid.ts b/packages/datagrid/src/datagrid.ts index 7585c8e46..427225d53 100644 --- a/packages/datagrid/src/datagrid.ts +++ b/packages/datagrid/src/datagrid.ts @@ -3404,12 +3404,12 @@ export class DataGrid extends Widget { this._drawMergedCells(cellGroups, paintRgn as Private.PaintRegion); // Draw grid lines close to merged cells - // this._drawMergedCellsBorder( - // cellGroups, - // rgn, - // this._style.horizontalGridLineColor || this._style.gridLineColor, - // this._style.verticalGridLineColor || this._style.gridLineColor - // ); + this._drawMergedCellsBorder( + cellGroups, + paintRgn as Private.PaintRegion, + this._style.horizontalGridLineColor || this._style.gridLineColor, + this._style.verticalGridLineColor || this._style.gridLineColor + ); } // Paint the overlay. @@ -3807,56 +3807,6 @@ export class DataGrid extends Widget { this.drawCornerHeaderRegion(rx, ry, rw, rh); } - /** - * Force a repaint of cells group. - */ - // protected paintCellGroup(cellGroup: CellGroup, rgn: DataModel.CellRegion, xMin: number, xMax: number, yMin: number, yMax: number) { - // const mergedCellRegion: Private.PaintRegion = { - // region: rgn, - // xMin: , - // yMin: , - // xMax: x2, - // yMax: y2, - // x, - // y, - // width, - // height, - // row: r1, - // column: c1, - // rowSizes, - // columnSizes - // }; - - // Draw the background. - // this._drawBackground(mergedCellRegion, this._style.backgroundColor); - - // Draw the row background. - // this._drawRowBackground(mergedCellRegion, this._style.rowBackgroundColor); - - // Draw the column background. - // this._drawColumnBackground(mergedCellRegion, this._style.columnBackgroundColor); - - // this._drawCellGroup(cellGroup, mergedCellRegion); - // } - - // /** - // * Force a repaint of some grouped cells that are intersecting a given column. - // */ - // protected paintMergedCellsAtColumn(rgn: DataModel.CellRegion, index: number, xMin: number, xMax: number, yMin: number, yMax: number) { - // const cellGroups = CellGroup.getCellGroupsAtColumn(this.dataModel!, rgn, index); - - // this._drawMergedCellsGroups(cellGroups, rgn, xMin, yMin, xMax, yMax); - // } - - // /** - // * Force a repaint of some grouped cells that are intersecting a given row. - // */ - // protected paintMergedCellsAtRow(rgn: DataModel.CellRegion, index: number, xMin: number, xMax: number, yMin: number, yMax: number) { - // const cellGroups = CellGroup.getCellGroupsAtRow(this.dataModel!, rgn, index); - - // this._drawMergedCellsGroups(cellGroups, rgn, xMin, yMin, xMax, yMax); - // } - /** * Resizes body column headers so their text fits * without clipping or wrapping. @@ -4193,12 +4143,12 @@ export class DataGrid extends Widget { this._drawMergedCells(cellGroups, rgn); // Draw grid lines close to merged cells - // this._drawMergedCellsBorder( - // cellGroups, - // rgn, - // this._style.horizontalGridLineColor || this._style.gridLineColor, - // this._style.verticalGridLineColor || this._style.gridLineColor - // ); + this._drawMergedCellsBorder( + cellGroups, + rgn, + this._style.horizontalGridLineColor || this._style.gridLineColor, + this._style.verticalGridLineColor || this._style.gridLineColor + ); } /** @@ -4348,6 +4298,14 @@ export class DataGrid extends Widget { // Draw the cell groups for the paint region this._drawMergedCells(cellGroups, rgn); + + // Draw grid lines close to merged cells + this._drawMergedCellsBorder( + cellGroups, + rgn, + this._style.headerHorizontalGridLineColor || this._style.headerGridLineColor, + this._style.headerVerticalGridLineColor || this._style.headerGridLineColor + ); } /** @@ -4497,6 +4455,15 @@ export class DataGrid extends Widget { // Draw the cell groups for the paint region this._drawMergedCells(cellGroups, rgn); + + // Draw grid lines close to merged cells + this._drawMergedCellsBorder( + cellGroups, + rgn, + this._style.headerHorizontalGridLineColor || + this._style.headerGridLineColor, + this._style.headerVerticalGridLineColor || this._style.headerGridLineColor + ); } /** @@ -4630,6 +4597,15 @@ export class DataGrid extends Widget { // Draw the cell groups for the paint region this._drawMergedCells(cellGroups, rgn); + + // Draw grid lines close to merged cells + this._drawMergedCellsBorder( + cellGroups, + rgn, + this._style.headerHorizontalGridLineColor || + this._style.headerGridLineColor, + this._style.headerVerticalGridLineColor || this._style.headerGridLineColor + ); } /** @@ -5131,6 +5107,23 @@ export class DataGrid extends Widget { this._bufferGC.restore(); } + /** + * Draw the cell groups for the given paint region. + */ + private _drawMergedCellsBorder( + cellGroups: CellGroup[], + rgn: Private.PaintRegion, + verticalColor: string | undefined, + horizontalColor: string | undefined + ): void { + // Bail if there is no data model. + if (!this._dataModel) { + return; + } + + + } + /** * Draw the horizontal grid lines for the given paint region. */ @@ -5204,19 +5197,9 @@ export class DataGrid extends Widget { // Draw the line if it's in range of the dirty rect. if (pos >= rgn.yMin && pos <= rgn.yMax) { - // Render entire grid if scrolling merged cells grid - const extendLines = Private.shouldPaintEverything(this._dataModel!); - if (extendLines) { - for (const line of lines) { - const [x1, x2] = line; - this._canvasGC.moveTo(x1, pos + 0.5); - this._canvasGC.lineTo(x2, pos + 0.5); - } - } else { - const x2 = Math.min(rgn.x + rgn.width, rgn.xMax + 1); - this._canvasGC.moveTo(x1, pos + 0.5); - this._canvasGC.lineTo(x2, pos + 0.5); - } + const x2 = Math.min(rgn.x + rgn.width, rgn.xMax + 1); + this._canvasGC.moveTo(x1, pos + 0.5); + this._canvasGC.lineTo(x2, pos + 0.5); } // Increment the running Y coordinate. @@ -5301,19 +5284,9 @@ export class DataGrid extends Widget { // Draw the line if it's in range of the dirty rect. if (pos >= rgn.xMin && pos <= rgn.xMax) { - // Render entire grid if scrolling merged cells grid - const extendLines = Private.shouldPaintEverything(this._dataModel!); - if (extendLines) { - for (const line of lines) { - // this._canvasGC.strokeStyle = color; - this._canvasGC.moveTo(pos + 0.5, line[0]); - this._canvasGC.lineTo(pos + 0.5, line[1]); - } - } else { - let y2 = Math.min(rgn.y + rgn.height, rgn.yMax + 1); - this._canvasGC.moveTo(pos + 0.5, y1); - this._canvasGC.lineTo(pos + 0.5, y2); - } + let y2 = Math.min(rgn.y + rgn.height, rgn.yMax + 1); + this._canvasGC.moveTo(pos + 0.5, y1); + this._canvasGC.lineTo(pos + 0.5, y2); } // Increment the running X coordinate. @@ -6606,34 +6579,6 @@ namespace Private { return canvas; } - /** - * A function to check whether the entire grid should be rendered - * when dealing with merged cell regions. - * @param dataModel grid's data model. - * @returns boolean. - */ - export function shouldPaintEverything(dataModel: DataModel): boolean { - const colGroups = CellGroup.getCellGroupsAtRegion( - dataModel!, - 'column-header' - ); - const rowHeaderGroups = CellGroup.getCellGroupsAtRegion( - dataModel!, - 'row-header' - ); - const cornerHeaderGroups = CellGroup.getCellGroupsAtRegion( - dataModel!, - 'corner-header' - ); - const bodyGroups = CellGroup.getCellGroupsAtRegion(dataModel!, 'body'); - return ( - colGroups.length > 0 || - rowHeaderGroups.length > 0 || - cornerHeaderGroups.length > 0 || - bodyGroups.length > 0 - ); - } - /** * Checks whether a given regions has merged cells in it. * @param dataModel grid's data model. From 5142c9229b0c2da7a5019975530b696c9d3ce9c1 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Wed, 7 Sep 2022 11:17:02 +0200 Subject: [PATCH 09/25] Implement drawing borders --- packages/datagrid/src/datagrid.ts | 66 +++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/packages/datagrid/src/datagrid.ts b/packages/datagrid/src/datagrid.ts index 427225d53..359e40b3a 100644 --- a/packages/datagrid/src/datagrid.ts +++ b/packages/datagrid/src/datagrid.ts @@ -5121,7 +5121,73 @@ export class DataGrid extends Widget { return; } + // Set the line width for the grid lines. + this._canvasGC.lineWidth = 1; + + for (const group of cellGroups) { + let width = 0; + for (let c = group.c1; c <= group.c2; c++) { + width += this._getColumnSize(rgn.region, c); + } + + let height = 0; + for (let r = group.r1; r <= group.r2; r++) { + height += this._getRowSize(rgn.region, r); + } + + let x = 0; + let y = 0; + switch (rgn.region) { + case 'body': + x = this._columnSections.offsetOf(group.c1) + this.headerWidth - this._scrollX; + y = this._rowSections.offsetOf(group.r1) + this.headerHeight - this._scrollY; + break; + case 'column-header': + x = this._columnSections.offsetOf(group.c1) + this.headerWidth - this._scrollX; + y = this._rowSections.offsetOf(group.r1) - this._scrollY; + break; + case 'row-header': + x = this._columnSections.offsetOf(group.c1) - this._scrollX; + y = this._rowSections.offsetOf(group.r1) + this.headerHeight - this._scrollY; + break; + case 'corner-header': + x = this._columnSections.offsetOf(group.c1); + y = this._rowSections.offsetOf(group.r1); + break; + } + + if (verticalColor) { + // Begin the path for the grid lines. + this._canvasGC.beginPath(); + + // Why do we not need this? + // this._canvasGC.moveTo(x, y); + // this._canvasGC.lineTo(x, y + height); + + this._canvasGC.moveTo(x + width - 0.5, y); + this._canvasGC.lineTo(x + width - 0.5, y + height); + + // Stroke the lines with the specified color. + this._canvasGC.strokeStyle = verticalColor; + this._canvasGC.stroke(); + } + if (horizontalColor) { + // Begin the path for the grid lines. + this._canvasGC.beginPath(); + + // Why do we not need this? + // this._canvasGC.moveTo(x, y); + // this._canvasGC.lineTo(x + width, y); + + this._canvasGC.moveTo(x, y + height - 0.5); + this._canvasGC.lineTo(x + width, y + height - 0.5); + + // Stroke the lines with the specified color. + this._canvasGC.strokeStyle = horizontalColor; + this._canvasGC.stroke(); + } + } } /** From 671d369742fd4ee0a8834164e9ab985557f561df Mon Sep 17 00:00:00 2001 From: martinRenou Date: Wed, 7 Sep 2022 11:28:55 +0200 Subject: [PATCH 10/25] Refactor drawing merged cells into one method --- packages/datagrid/src/datagrid.ts | 219 +++++++----------------------- 1 file changed, 47 insertions(+), 172 deletions(-) diff --git a/packages/datagrid/src/datagrid.ts b/packages/datagrid/src/datagrid.ts index 359e40b3a..91a95b596 100644 --- a/packages/datagrid/src/datagrid.ts +++ b/packages/datagrid/src/datagrid.ts @@ -3397,16 +3397,10 @@ export class DataGrid extends Widget { break; } - // Draw the background for merged cells - this._drawMergedCellsBackground(cellGroups, paintRgn as Private.PaintRegion, this._style.backgroundColor); - - // Draw the cell groups for the paint region - this._drawMergedCells(cellGroups, paintRgn as Private.PaintRegion); - - // Draw grid lines close to merged cells - this._drawMergedCellsBorder( + this._paintMergedCells( cellGroups, paintRgn as Private.PaintRegion, + this._style.backgroundColor, this._style.horizontalGridLineColor || this._style.gridLineColor, this._style.verticalGridLineColor || this._style.gridLineColor ); @@ -4136,16 +4130,11 @@ export class DataGrid extends Widget { return this.cellGroupInteresectsRegion(group, rgn); }); - // Draw the background for merged cells - this._drawMergedCellsBackground(cellGroups, rgn, this._style.backgroundColor); - - // Draw the cell groups for the paint region - this._drawMergedCells(cellGroups, rgn); - - // Draw grid lines close to merged cells - this._drawMergedCellsBorder( + // Draw merged cells + this._paintMergedCells( cellGroups, rgn, + this._style.backgroundColor, this._style.horizontalGridLineColor || this._style.gridLineColor, this._style.verticalGridLineColor || this._style.gridLineColor ); @@ -4293,16 +4282,11 @@ export class DataGrid extends Widget { return this.cellGroupInteresectsRegion(group, rgn); }); - // Draw the background for merged cells - this._drawMergedCellsBackground(cellGroups, rgn, this._style.headerBackgroundColor); - - // Draw the cell groups for the paint region - this._drawMergedCells(cellGroups, rgn); - - // Draw grid lines close to merged cells - this._drawMergedCellsBorder( + // Draw merged cells + this._paintMergedCells( cellGroups, rgn, + this._style.headerBackgroundColor, this._style.headerHorizontalGridLineColor || this._style.headerGridLineColor, this._style.headerVerticalGridLineColor || this._style.headerGridLineColor ); @@ -4450,18 +4434,12 @@ export class DataGrid extends Widget { return this.cellGroupInteresectsRegion(group, rgn); }); - // Draw the background for merged cells - this._drawMergedCellsBackground(cellGroups, rgn, this._style.headerBackgroundColor); - - // Draw the cell groups for the paint region - this._drawMergedCells(cellGroups, rgn); - - // Draw grid lines close to merged cells - this._drawMergedCellsBorder( + // Draw merged cells + this._paintMergedCells( cellGroups, rgn, - this._style.headerHorizontalGridLineColor || - this._style.headerGridLineColor, + this._style.headerBackgroundColor, + this._style.headerHorizontalGridLineColor || this._style.headerGridLineColor, this._style.headerVerticalGridLineColor || this._style.headerGridLineColor ); } @@ -4592,18 +4570,12 @@ export class DataGrid extends Widget { return this.cellGroupInteresectsRegion(group, rgn); }); - // Draw the background for merged cells - this._drawMergedCellsBackground(cellGroups, rgn, this._style.headerBackgroundColor); - - // Draw the cell groups for the paint region - this._drawMergedCells(cellGroups, rgn); - - // Draw grid lines close to merged cells - this._drawMergedCellsBorder( + // Draw merged cells + this._paintMergedCells( cellGroups, rgn, - this._style.headerHorizontalGridLineColor || - this._style.headerGridLineColor, + this._style.headerBackgroundColor, + this._style.headerHorizontalGridLineColor || this._style.headerGridLineColor, this._style.headerVerticalGridLineColor || this._style.headerGridLineColor ); } @@ -4908,77 +4880,15 @@ export class DataGrid extends Widget { } /** - * Draw the background for given group cells. + * Paint group cells. */ - private _drawMergedCellsBackground( + private _paintMergedCells( cellGroups: CellGroup[], rgn: Private.PaintRegion, - color: string | undefined + backgroundColor: string | undefined, + verticalColor: string | undefined, + horizontalColor: string | undefined ): void { - // Bail if there is no color to draw. - if (!color) { - return; - } - - // Unpack the region. - let { xMin, yMin, xMax, yMax } = rgn; - - this._canvasGC.fillStyle = color; - - for (const group of cellGroups) { - let width = 0; - for (let c = group.c1; c <= group.c2; c++) { - width += this._getColumnSize(rgn.region, c); - } - - let height = 0; - for (let r = group.r1; r <= group.r2; r++) { - height += this._getRowSize(rgn.region, r); - } - - let x = 0; - let y = 0; - switch (rgn.region) { - case 'body': - x = this._columnSections.offsetOf(group.c1) + this.headerWidth - this._scrollX; - y = this._rowSections.offsetOf(group.r1) + this.headerHeight - this._scrollY; - break; - case 'column-header': - x = this._columnSections.offsetOf(group.c1) + this.headerWidth - this._scrollX; - y = this._rowSections.offsetOf(group.r1) - this._scrollY; - break; - case 'row-header': - x = this._columnSections.offsetOf(group.c1) - this._scrollX; - y = this._rowSections.offsetOf(group.r1) + this.headerHeight - this._scrollY; - break; - case 'corner-header': - x = this._columnSections.offsetOf(group.c1); - y = this._rowSections.offsetOf(group.r1); - break; - } - - // Compute the actual X bounds for the cell. - let x1 = Math.max(xMin, x); - let x2 = Math.min(x + width - 1, xMax); - - // Compute the actual Y bounds for the cell. - let y1 = Math.max(yMin, y); - let y2 = Math.min(y + height - 1, yMax); - - // Fill the region with the specified color. - this._canvasGC.fillRect( - x1, - y1, - x2 - x1 + 1, - y2 - y1 + 1 - ); - } - } - - /** - * Draw the cell groups for the given paint region. - */ - private _drawMergedCells(cellGroups: CellGroup[], rgn: Private.PaintRegion): void { // Bail if there is no data model. if (!this._dataModel) { return; @@ -4997,6 +4907,12 @@ export class DataGrid extends Widget { metadata: DataModel.emptyMetadata }; + if (backgroundColor) { + this._canvasGC.fillStyle = backgroundColor; + } + // Set the line width for the grid lines. + this._canvasGC.lineWidth = 1; + // Save the buffer gc before wrapping. this._bufferGC.save(); @@ -5063,12 +4979,22 @@ export class DataGrid extends Widget { config.metadata = metadata; // Compute the actual X bounds for the cell. - let x1 = Math.max(rgn.xMin, config.x); - let x2 = Math.min(config.x + config.width - 1, rgn.xMax); + let x1 = Math.max(rgn.xMin, x); + let x2 = Math.min(x + width - 1, rgn.xMax); // Compute the actual Y bounds for the cell. - let y1 = Math.max(rgn.yMin, config.y); - let y2 = Math.min(config.y + config.height - 1, rgn.yMax); + let y1 = Math.max(rgn.yMin, y); + let y2 = Math.min(y + height - 1, rgn.yMax); + + // Draw the background. + if (backgroundColor) { + this._canvasGC.fillRect( + x1, + y1, + x2 - x1 + 1, + y2 - y1 + 1 + ); + } // Get the renderer for the cell. let renderer = this._cellRenderers.get(config); @@ -5098,63 +5024,6 @@ export class DataGrid extends Widget { x1, y1 ); - } - - // Dispose of the wrapped gc. - gc.dispose(); - - // Restore the final buffer gc state. - this._bufferGC.restore(); - } - - /** - * Draw the cell groups for the given paint region. - */ - private _drawMergedCellsBorder( - cellGroups: CellGroup[], - rgn: Private.PaintRegion, - verticalColor: string | undefined, - horizontalColor: string | undefined - ): void { - // Bail if there is no data model. - if (!this._dataModel) { - return; - } - - // Set the line width for the grid lines. - this._canvasGC.lineWidth = 1; - - for (const group of cellGroups) { - let width = 0; - for (let c = group.c1; c <= group.c2; c++) { - width += this._getColumnSize(rgn.region, c); - } - - let height = 0; - for (let r = group.r1; r <= group.r2; r++) { - height += this._getRowSize(rgn.region, r); - } - - let x = 0; - let y = 0; - switch (rgn.region) { - case 'body': - x = this._columnSections.offsetOf(group.c1) + this.headerWidth - this._scrollX; - y = this._rowSections.offsetOf(group.r1) + this.headerHeight - this._scrollY; - break; - case 'column-header': - x = this._columnSections.offsetOf(group.c1) + this.headerWidth - this._scrollX; - y = this._rowSections.offsetOf(group.r1) - this._scrollY; - break; - case 'row-header': - x = this._columnSections.offsetOf(group.c1) - this._scrollX; - y = this._rowSections.offsetOf(group.r1) + this.headerHeight - this._scrollY; - break; - case 'corner-header': - x = this._columnSections.offsetOf(group.c1); - y = this._rowSections.offsetOf(group.r1); - break; - } if (verticalColor) { // Begin the path for the grid lines. @@ -5188,6 +5057,12 @@ export class DataGrid extends Widget { this._canvasGC.stroke(); } } + + // Dispose of the wrapped gc. + gc.dispose(); + + // Restore the final buffer gc state. + this._bufferGC.restore(); } /** From c6ecd89988091deeb434561218d8819e5ceb717e Mon Sep 17 00:00:00 2001 From: martinRenou Date: Wed, 7 Sep 2022 11:32:58 +0200 Subject: [PATCH 11/25] Fix not drawing borders outside of the paintRegion --- packages/datagrid/src/datagrid.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/datagrid/src/datagrid.ts b/packages/datagrid/src/datagrid.ts index 91a95b596..301a5be4d 100644 --- a/packages/datagrid/src/datagrid.ts +++ b/packages/datagrid/src/datagrid.ts @@ -5030,11 +5030,11 @@ export class DataGrid extends Widget { this._canvasGC.beginPath(); // Why do we not need this? - // this._canvasGC.moveTo(x, y); - // this._canvasGC.lineTo(x, y + height); + // this._canvasGC.moveTo(x1, y1); + // this._canvasGC.lineTo(x1, y2); - this._canvasGC.moveTo(x + width - 0.5, y); - this._canvasGC.lineTo(x + width - 0.5, y + height); + this._canvasGC.moveTo(x2 + 0.5, y1); + this._canvasGC.lineTo(x2 + 0.5, y2); // Stroke the lines with the specified color. this._canvasGC.strokeStyle = verticalColor; @@ -5046,11 +5046,11 @@ export class DataGrid extends Widget { this._canvasGC.beginPath(); // Why do we not need this? - // this._canvasGC.moveTo(x, y); - // this._canvasGC.lineTo(x + width, y); + // this._canvasGC.moveTo(x1, y1); + // this._canvasGC.lineTo(x2, y1); - this._canvasGC.moveTo(x, y + height - 0.5); - this._canvasGC.lineTo(x + width, y + height - 0.5); + this._canvasGC.moveTo(x1, y2 + 0.5); + this._canvasGC.lineTo(x2, y2 + 0.5); // Stroke the lines with the specified color. this._canvasGC.strokeStyle = horizontalColor; From b85fdaa158167038a4f06dc529c125b88b6a9ec8 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Wed, 7 Sep 2022 11:36:58 +0200 Subject: [PATCH 12/25] Fix colors --- packages/datagrid/src/datagrid.ts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/packages/datagrid/src/datagrid.ts b/packages/datagrid/src/datagrid.ts index 301a5be4d..1da55aff3 100644 --- a/packages/datagrid/src/datagrid.ts +++ b/packages/datagrid/src/datagrid.ts @@ -3382,27 +3382,39 @@ export class DataGrid extends Widget { yMax: 0 }; + let backgroundColor = undefined; + let horizontalColor = undefined; + let verticalColor = undefined; + switch (rgn) { case 'body': paintRgn.xMin = this.headerWidth; paintRgn.xMax = this.headerWidth + this.bodyWidth; paintRgn.yMin = this.headerHeight; paintRgn.yMax = this.headerHeight + this.bodyHeight; + + backgroundColor = this._style.backgroundColor; + horizontalColor = this._style.horizontalGridLineColor || this._style.gridLineColor; + verticalColor = this._style.verticalGridLineColor || this._style.gridLineColor; break; case 'column-header': paintRgn.xMin = this.headerWidth; paintRgn.xMax = this.headerWidth + this.bodyWidth; paintRgn.yMin = 0; paintRgn.yMax = this.headerHeight; + + backgroundColor = this._style.headerBackgroundColor; + horizontalColor = this._style.headerHorizontalGridLineColor || this._style.headerGridLineColor; + verticalColor = this._style.headerVerticalGridLineColor || this._style.headerGridLineColor; break; } this._paintMergedCells( cellGroups, paintRgn as Private.PaintRegion, - this._style.backgroundColor, - this._style.horizontalGridLineColor || this._style.gridLineColor, - this._style.verticalGridLineColor || this._style.gridLineColor + backgroundColor, + horizontalColor, + verticalColor ); } From 073dee120c8d44aa3304c88f4ae93a9afd0605f8 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Wed, 7 Sep 2022 12:24:15 +0200 Subject: [PATCH 13/25] Implement drawing merged cells for resize(Column|Row|ColumnHeader|RowHeader) --- packages/datagrid/src/datagrid.ts | 129 ++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/packages/datagrid/src/datagrid.ts b/packages/datagrid/src/datagrid.ts index 1da55aff3..a62121448 100644 --- a/packages/datagrid/src/datagrid.ts +++ b/packages/datagrid/src/datagrid.ts @@ -3255,6 +3255,57 @@ export class DataGrid extends Widget { this.paintContent(0, vh + delta, vw, -delta); } + // Repaint merged cells that are intersected by the resized row + // Otherwise it will be cut in two by the valid content, and drawn incorrectly + for (const rgn of ['body', 'row-header'] as DataModel.CellRegion[]) { + const cellGroups = CellGroup.getCellGroupsAtRow(this.dataModel!, rgn, index); + + // TODO We're not creating a fully implemented paint-region, + // We probably need another type + let paintRgn = { + region: rgn, + xMin: 0, + xMax: 0, + yMin: 0, + yMax: 0 + }; + + let backgroundColor = undefined; + let horizontalColor = undefined; + let verticalColor = undefined; + + switch (rgn) { + case 'body': + paintRgn.xMin = this.headerWidth; + paintRgn.xMax = this.headerWidth + this.bodyWidth; + paintRgn.yMin = this.headerHeight; + paintRgn.yMax = this.headerHeight + this.bodyHeight; + + backgroundColor = this._style.backgroundColor; + horizontalColor = this._style.horizontalGridLineColor || this._style.gridLineColor; + verticalColor = this._style.verticalGridLineColor || this._style.gridLineColor; + break; + case 'row-header': + paintRgn.xMin = 0; + paintRgn.xMax = this.headerWidth; + paintRgn.yMin = this.headerHeight; + paintRgn.yMax = this.headerHeight + this.bodyHeight; + + backgroundColor = this._style.headerBackgroundColor; + horizontalColor = this._style.headerHorizontalGridLineColor || this._style.headerGridLineColor; + verticalColor = this._style.headerVerticalGridLineColor || this._style.headerGridLineColor; + break; + } + + this._paintMergedCells( + cellGroups, + paintRgn as Private.PaintRegion, + backgroundColor, + horizontalColor, + verticalColor + ); + } + // Paint the overlay. this._paintOverlay(); @@ -3506,6 +3557,45 @@ export class DataGrid extends Widget { this.paintContent(vw + delta, 0, -delta, vh); } + // Repaint merged cells that are intersected by the resized row + // Otherwise it will be cut in two by the valid content, and drawn incorrectly + for (const rgn of ['corner-header', 'row-header'] as DataModel.CellRegion[]) { + const cellGroups = CellGroup.getCellGroupsAtColumn(this.dataModel!, rgn, index); + + // TODO We're not creating a fully implemented paint-region, + // We probably need another type + let paintRgn = { + region: rgn, + xMin: 0, + xMax: 0, + yMin: 0, + yMax: 0 + }; + + switch (rgn) { + case 'corner-header': + paintRgn.xMin = 0; + paintRgn.xMax = this.headerWidth; + paintRgn.yMin = 0; + paintRgn.yMax = this.headerHeight; + break; + case 'row-header': + paintRgn.xMin = 0; + paintRgn.xMax = this.headerWidth; + paintRgn.yMin = this.headerHeight; + paintRgn.yMax = this.headerHeight + this.bodyHeight; + break; + } + + this._paintMergedCells( + cellGroups, + paintRgn as Private.PaintRegion, + this._style.headerBackgroundColor, + this._style.headerHorizontalGridLineColor || this._style.headerGridLineColor, + this._style.headerVerticalGridLineColor || this._style.headerGridLineColor + ); + } + // Paint the overlay. this._paintOverlay(); @@ -3597,6 +3687,45 @@ export class DataGrid extends Widget { this.paintContent(0, vh + delta, vw, -delta); } + // Repaint merged cells that are intersected by the resized row + // Otherwise it will be cut in two by the valid content, and drawn incorrectly + for (const rgn of ['corner-header', 'column-header'] as DataModel.CellRegion[]) { + const cellGroups = CellGroup.getCellGroupsAtRow(this.dataModel!, rgn, index); + + // TODO We're not creating a fully implemented paint-region, + // We probably need another type + let paintRgn = { + region: rgn, + xMin: 0, + xMax: 0, + yMin: 0, + yMax: 0 + }; + + switch (rgn) { + case 'corner-header': + paintRgn.xMin = 0; + paintRgn.xMax = this.headerWidth; + paintRgn.yMin = 0; + paintRgn.yMax = this.headerHeight; + break; + case 'column-header': + paintRgn.xMin = this.headerWidth; + paintRgn.xMax = this.headerWidth + this.bodyWidth; + paintRgn.yMin = 0; + paintRgn.yMax = this.headerHeight; + break; + } + + this._paintMergedCells( + cellGroups, + paintRgn as Private.PaintRegion, + this._style.headerBackgroundColor, + this._style.headerHorizontalGridLineColor || this._style.headerGridLineColor, + this._style.headerVerticalGridLineColor || this._style.headerGridLineColor + ); + } + // Paint the overlay. this._paintOverlay(); From 31de83bcda675203bc56cc907914de917df3bff7 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Wed, 7 Sep 2022 13:43:59 +0200 Subject: [PATCH 14/25] Linter --- packages/datagrid/src/datagrid.ts | 125 ++++++++++++++++++++---------- 1 file changed, 84 insertions(+), 41 deletions(-) diff --git a/packages/datagrid/src/datagrid.ts b/packages/datagrid/src/datagrid.ts index a62121448..400770bbc 100644 --- a/packages/datagrid/src/datagrid.ts +++ b/packages/datagrid/src/datagrid.ts @@ -3258,7 +3258,11 @@ export class DataGrid extends Widget { // Repaint merged cells that are intersected by the resized row // Otherwise it will be cut in two by the valid content, and drawn incorrectly for (const rgn of ['body', 'row-header'] as DataModel.CellRegion[]) { - const cellGroups = CellGroup.getCellGroupsAtRow(this.dataModel!, rgn, index); + const cellGroups = CellGroup.getCellGroupsAtRow( + this.dataModel!, + rgn, + index + ); // TODO We're not creating a fully implemented paint-region, // We probably need another type @@ -3282,8 +3286,10 @@ export class DataGrid extends Widget { paintRgn.yMax = this.headerHeight + this.bodyHeight; backgroundColor = this._style.backgroundColor; - horizontalColor = this._style.horizontalGridLineColor || this._style.gridLineColor; - verticalColor = this._style.verticalGridLineColor || this._style.gridLineColor; + horizontalColor = + this._style.horizontalGridLineColor || this._style.gridLineColor; + verticalColor = + this._style.verticalGridLineColor || this._style.gridLineColor; break; case 'row-header': paintRgn.xMin = 0; @@ -3292,8 +3298,12 @@ export class DataGrid extends Widget { paintRgn.yMax = this.headerHeight + this.bodyHeight; backgroundColor = this._style.headerBackgroundColor; - horizontalColor = this._style.headerHorizontalGridLineColor || this._style.headerGridLineColor; - verticalColor = this._style.headerVerticalGridLineColor || this._style.headerGridLineColor; + horizontalColor = + this._style.headerHorizontalGridLineColor || + this._style.headerGridLineColor; + verticalColor = + this._style.headerVerticalGridLineColor || + this._style.headerGridLineColor; break; } @@ -3421,7 +3431,11 @@ export class DataGrid extends Widget { // Repaint merged cells that are intersected by the resized column // Otherwise it will be cut in two by the valid content, and drawn incorrectly for (const rgn of ['body', 'column-header'] as DataModel.CellRegion[]) { - const cellGroups = CellGroup.getCellGroupsAtColumn(this.dataModel!, rgn, index); + const cellGroups = CellGroup.getCellGroupsAtColumn( + this.dataModel!, + rgn, + index + ); // TODO We're not creating a fully implemented paint-region, // We probably need another type @@ -3445,8 +3459,10 @@ export class DataGrid extends Widget { paintRgn.yMax = this.headerHeight + this.bodyHeight; backgroundColor = this._style.backgroundColor; - horizontalColor = this._style.horizontalGridLineColor || this._style.gridLineColor; - verticalColor = this._style.verticalGridLineColor || this._style.gridLineColor; + horizontalColor = + this._style.horizontalGridLineColor || this._style.gridLineColor; + verticalColor = + this._style.verticalGridLineColor || this._style.gridLineColor; break; case 'column-header': paintRgn.xMin = this.headerWidth; @@ -3455,8 +3471,12 @@ export class DataGrid extends Widget { paintRgn.yMax = this.headerHeight; backgroundColor = this._style.headerBackgroundColor; - horizontalColor = this._style.headerHorizontalGridLineColor || this._style.headerGridLineColor; - verticalColor = this._style.headerVerticalGridLineColor || this._style.headerGridLineColor; + horizontalColor = + this._style.headerHorizontalGridLineColor || + this._style.headerGridLineColor; + verticalColor = + this._style.headerVerticalGridLineColor || + this._style.headerGridLineColor; break; } @@ -3559,8 +3579,15 @@ export class DataGrid extends Widget { // Repaint merged cells that are intersected by the resized row // Otherwise it will be cut in two by the valid content, and drawn incorrectly - for (const rgn of ['corner-header', 'row-header'] as DataModel.CellRegion[]) { - const cellGroups = CellGroup.getCellGroupsAtColumn(this.dataModel!, rgn, index); + for (const rgn of [ + 'corner-header', + 'row-header' + ] as DataModel.CellRegion[]) { + const cellGroups = CellGroup.getCellGroupsAtColumn( + this.dataModel!, + rgn, + index + ); // TODO We're not creating a fully implemented paint-region, // We probably need another type @@ -3591,8 +3618,10 @@ export class DataGrid extends Widget { cellGroups, paintRgn as Private.PaintRegion, this._style.headerBackgroundColor, - this._style.headerHorizontalGridLineColor || this._style.headerGridLineColor, - this._style.headerVerticalGridLineColor || this._style.headerGridLineColor + this._style.headerHorizontalGridLineColor || + this._style.headerGridLineColor, + this._style.headerVerticalGridLineColor || + this._style.headerGridLineColor ); } @@ -3689,8 +3718,15 @@ export class DataGrid extends Widget { // Repaint merged cells that are intersected by the resized row // Otherwise it will be cut in two by the valid content, and drawn incorrectly - for (const rgn of ['corner-header', 'column-header'] as DataModel.CellRegion[]) { - const cellGroups = CellGroup.getCellGroupsAtRow(this.dataModel!, rgn, index); + for (const rgn of [ + 'corner-header', + 'column-header' + ] as DataModel.CellRegion[]) { + const cellGroups = CellGroup.getCellGroupsAtRow( + this.dataModel!, + rgn, + index + ); // TODO We're not creating a fully implemented paint-region, // We probably need another type @@ -3721,8 +3757,10 @@ export class DataGrid extends Widget { cellGroups, paintRgn as Private.PaintRegion, this._style.headerBackgroundColor, - this._style.headerHorizontalGridLineColor || this._style.headerGridLineColor, - this._style.headerVerticalGridLineColor || this._style.headerGridLineColor + this._style.headerHorizontalGridLineColor || + this._style.headerGridLineColor, + this._style.headerVerticalGridLineColor || + this._style.headerGridLineColor ); } @@ -4428,7 +4466,8 @@ export class DataGrid extends Widget { cellGroups, rgn, this._style.headerBackgroundColor, - this._style.headerHorizontalGridLineColor || this._style.headerGridLineColor, + this._style.headerHorizontalGridLineColor || + this._style.headerGridLineColor, this._style.headerVerticalGridLineColor || this._style.headerGridLineColor ); } @@ -4580,7 +4619,8 @@ export class DataGrid extends Widget { cellGroups, rgn, this._style.headerBackgroundColor, - this._style.headerHorizontalGridLineColor || this._style.headerGridLineColor, + this._style.headerHorizontalGridLineColor || + this._style.headerGridLineColor, this._style.headerVerticalGridLineColor || this._style.headerGridLineColor ); } @@ -4716,7 +4756,8 @@ export class DataGrid extends Widget { cellGroups, rgn, this._style.headerBackgroundColor, - this._style.headerHorizontalGridLineColor || this._style.headerGridLineColor, + this._style.headerHorizontalGridLineColor || + this._style.headerGridLineColor, this._style.headerVerticalGridLineColor || this._style.headerGridLineColor ); } @@ -5007,7 +5048,10 @@ export class DataGrid extends Widget { } // TODO Move this in the utils file (but we need the PaintRegion typing) - private cellGroupInteresectsRegion(group: CellGroup, rgn: Private.PaintRegion) { + private cellGroupInteresectsRegion( + group: CellGroup, + rgn: Private.PaintRegion + ) { const rgnR1 = rgn.row; const rgnR2 = rgn.row + rgn.rowSizes.length; @@ -5092,16 +5136,28 @@ export class DataGrid extends Widget { let y = 0; switch (rgn.region) { case 'body': - x = this._columnSections.offsetOf(group.c1) + this.headerWidth - this._scrollX; - y = this._rowSections.offsetOf(group.r1) + this.headerHeight - this._scrollY; + x = + this._columnSections.offsetOf(group.c1) + + this.headerWidth - + this._scrollX; + y = + this._rowSections.offsetOf(group.r1) + + this.headerHeight - + this._scrollY; break; case 'column-header': - x = this._columnSections.offsetOf(group.c1) + this.headerWidth - this._scrollX; + x = + this._columnSections.offsetOf(group.c1) + + this.headerWidth - + this._scrollX; y = this._rowSections.offsetOf(group.r1) - this._scrollY; break; case 'row-header': x = this._columnSections.offsetOf(group.c1) - this._scrollX; - y = this._rowSections.offsetOf(group.r1) + this.headerHeight - this._scrollY; + y = + this._rowSections.offsetOf(group.r1) + + this.headerHeight - + this._scrollY; break; case 'corner-header': x = this._columnSections.offsetOf(group.c1); @@ -5129,12 +5185,7 @@ export class DataGrid extends Widget { // Draw the background. if (backgroundColor) { - this._canvasGC.fillRect( - x1, - y1, - x2 - x1 + 1, - y2 - y1 + 1 - ); + this._canvasGC.fillRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1); } // Get the renderer for the cell. @@ -5156,15 +5207,7 @@ export class DataGrid extends Widget { // Restore the GC state. gc.restore(); - this._blitContent( - this._buffer, - x1, - y1, - x2 - x1 + 1, - y2 - y1 + 1, - x1, - y1 - ); + this._blitContent(this._buffer, x1, y1, x2 - x1 + 1, y2 - y1 + 1, x1, y1); if (verticalColor) { // Begin the path for the grid lines. From 03cde663520a1e422c593638aa9e32cce8f49117 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Wed, 7 Sep 2022 16:55:27 +0200 Subject: [PATCH 15/25] Update API file --- review/api/datagrid.api.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/review/api/datagrid.api.md b/review/api/datagrid.api.md index 9197a5041..ebd1c1c39 100644 --- a/review/api/datagrid.api.md +++ b/review/api/datagrid.api.md @@ -131,16 +131,11 @@ export interface CellGroup { export namespace CellGroup { export function areCellGroupsIntersecting(group1: CellGroup, group2: CellGroup): boolean; export function areCellGroupsIntersectingAtAxis(group1: CellGroup, group2: CellGroup, axis: 'row' | 'column'): boolean; - // (undocumented) - export function areCellsMerged(dataModel: DataModel, rgn: DataModel.CellRegion, cell1: number[], cell2: number[]): boolean; - export function calculateMergeOffsets(dataModel: DataModel, regions: DataModel.CellRegion[], axis: 'row' | 'column', sectionList: SectionList, index: number): [number, number, CellGroup]; export function getCellGroupsAtColumn(dataModel: DataModel, rgn: DataModel.CellRegion, column: number): CellGroup[]; export function getCellGroupsAtRegion(dataModel: DataModel, rgn: DataModel.CellRegion): CellGroup[]; export function getCellGroupsAtRow(dataModel: DataModel, rgn: DataModel.CellRegion, row: number): CellGroup[]; export function getGroup(dataModel: DataModel, rgn: DataModel.CellRegion, row: number, column: number): CellGroup | null; export function getGroupIndex(dataModel: DataModel, rgn: DataModel.CellRegion, row: number, column: number): number; - export function isCellGroupAbove(group1: CellGroup, group2: CellGroup): boolean; - export function isCellGroupBelow(group1: CellGroup, group2: CellGroup): boolean; export function joinCellGroups(groups: CellGroup[]): CellGroup; export function joinCellGroupsIntersectingAtAxis(dataModel: DataModel, regions: DataModel.CellRegion[], axis: 'row' | 'column', group: CellGroup): CellGroup; export function joinCellGroupWithMergedCellGroups(dataModel: DataModel, group: CellGroup, region: DataModel.CellRegion): CellGroup; From bc2795648bcd89d7fc006e7d5e8d5d408849be83 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Mon, 19 Sep 2022 11:40:40 +0200 Subject: [PATCH 16/25] Missing pixel --- packages/datagrid/src/datagrid.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/datagrid/src/datagrid.ts b/packages/datagrid/src/datagrid.ts index 400770bbc..2d75fa627 100644 --- a/packages/datagrid/src/datagrid.ts +++ b/packages/datagrid/src/datagrid.ts @@ -5218,7 +5218,7 @@ export class DataGrid extends Widget { // this._canvasGC.lineTo(x1, y2); this._canvasGC.moveTo(x2 + 0.5, y1); - this._canvasGC.lineTo(x2 + 0.5, y2); + this._canvasGC.lineTo(x2 + 0.5, y2 + 1); // Stroke the lines with the specified color. this._canvasGC.strokeStyle = verticalColor; @@ -5234,7 +5234,7 @@ export class DataGrid extends Widget { // this._canvasGC.lineTo(x2, y1); this._canvasGC.moveTo(x1, y2 + 0.5); - this._canvasGC.lineTo(x2, y2 + 0.5); + this._canvasGC.lineTo(x2 + 1, y2 + 0.5); // Stroke the lines with the specified color. this._canvasGC.strokeStyle = horizontalColor; From 64312ce6938089237b1765bd7403e6f4d5db0f6e Mon Sep 17 00:00:00 2001 From: martinRenou Date: Mon, 19 Sep 2022 12:04:19 +0200 Subject: [PATCH 17/25] More optimization --- packages/datagrid/src/datagrid.ts | 46 ------------------------------- 1 file changed, 46 deletions(-) diff --git a/packages/datagrid/src/datagrid.ts b/packages/datagrid/src/datagrid.ts index 2d75fa627..5ea513741 100644 --- a/packages/datagrid/src/datagrid.ts +++ b/packages/datagrid/src/datagrid.ts @@ -5294,29 +5294,6 @@ export class DataGrid extends Widget { continue; } - let xStart = 0; - let lineStarted = false; - let lines = []; - let leftCurrent = x1; - - for (let c = rgn.column; c < rgn.column + rgn.columnSizes.length; c++) { - const cIndex = c - rgn.column; - - if (!lineStarted) { - lineStarted = true; - xStart = leftCurrent; - } - - leftCurrent += rgn.columnSizes[cIndex]; - if (c === rgn.column) { - leftCurrent -= rgn.xMin - rgn.x; - } - } - - if (lineStarted) { - lines.push([xStart, rgn.xMax + 1]); - } - // Compute the Y position of the line. let pos = y + size - 1; @@ -5381,29 +5358,6 @@ export class DataGrid extends Widget { continue; } - let yStart = 0; - let lineStarted = false; - let lines = []; - let topCurrent = y1; - - for (let r = rgn.row; r < rgn.row + rgn.rowSizes.length; r++) { - const rIndex = r - rgn.row; - - if (!lineStarted) { - lineStarted = true; - yStart = topCurrent; - } - - topCurrent += rgn.rowSizes[rIndex]; - if (r === rgn.row) { - topCurrent -= rgn.yMin - rgn.y; - } - } - - if (lineStarted) { - lines.push([yStart, rgn.yMax + 1]); - } - // Compute the X position of the line. let pos = x + size - 1; From fc7acd4081b425a0b822e5f7e2255d3b020270c0 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Mon, 19 Sep 2022 16:53:23 +0200 Subject: [PATCH 18/25] Simplify code --- packages/datagrid/src/datagrid.ts | 127 ++++++------------------------ 1 file changed, 25 insertions(+), 102 deletions(-) diff --git a/packages/datagrid/src/datagrid.ts b/packages/datagrid/src/datagrid.ts index 5ea513741..d43f790d3 100644 --- a/packages/datagrid/src/datagrid.ts +++ b/packages/datagrid/src/datagrid.ts @@ -3275,8 +3275,6 @@ export class DataGrid extends Widget { }; let backgroundColor = undefined; - let horizontalColor = undefined; - let verticalColor = undefined; switch (rgn) { case 'body': @@ -3286,10 +3284,6 @@ export class DataGrid extends Widget { paintRgn.yMax = this.headerHeight + this.bodyHeight; backgroundColor = this._style.backgroundColor; - horizontalColor = - this._style.horizontalGridLineColor || this._style.gridLineColor; - verticalColor = - this._style.verticalGridLineColor || this._style.gridLineColor; break; case 'row-header': paintRgn.xMin = 0; @@ -3298,21 +3292,13 @@ export class DataGrid extends Widget { paintRgn.yMax = this.headerHeight + this.bodyHeight; backgroundColor = this._style.headerBackgroundColor; - horizontalColor = - this._style.headerHorizontalGridLineColor || - this._style.headerGridLineColor; - verticalColor = - this._style.headerVerticalGridLineColor || - this._style.headerGridLineColor; break; } this._paintMergedCells( cellGroups, paintRgn as Private.PaintRegion, - backgroundColor, - horizontalColor, - verticalColor + backgroundColor ); } @@ -3448,8 +3434,6 @@ export class DataGrid extends Widget { }; let backgroundColor = undefined; - let horizontalColor = undefined; - let verticalColor = undefined; switch (rgn) { case 'body': @@ -3459,10 +3443,6 @@ export class DataGrid extends Widget { paintRgn.yMax = this.headerHeight + this.bodyHeight; backgroundColor = this._style.backgroundColor; - horizontalColor = - this._style.horizontalGridLineColor || this._style.gridLineColor; - verticalColor = - this._style.verticalGridLineColor || this._style.gridLineColor; break; case 'column-header': paintRgn.xMin = this.headerWidth; @@ -3471,21 +3451,13 @@ export class DataGrid extends Widget { paintRgn.yMax = this.headerHeight; backgroundColor = this._style.headerBackgroundColor; - horizontalColor = - this._style.headerHorizontalGridLineColor || - this._style.headerGridLineColor; - verticalColor = - this._style.headerVerticalGridLineColor || - this._style.headerGridLineColor; break; } this._paintMergedCells( cellGroups, paintRgn as Private.PaintRegion, - backgroundColor, - horizontalColor, - verticalColor + backgroundColor ); } @@ -3617,11 +3589,7 @@ export class DataGrid extends Widget { this._paintMergedCells( cellGroups, paintRgn as Private.PaintRegion, - this._style.headerBackgroundColor, - this._style.headerHorizontalGridLineColor || - this._style.headerGridLineColor, - this._style.headerVerticalGridLineColor || - this._style.headerGridLineColor + this._style.headerBackgroundColor ); } @@ -3756,11 +3724,7 @@ export class DataGrid extends Widget { this._paintMergedCells( cellGroups, paintRgn as Private.PaintRegion, - this._style.headerBackgroundColor, - this._style.headerHorizontalGridLineColor || - this._style.headerGridLineColor, - this._style.headerVerticalGridLineColor || - this._style.headerGridLineColor + this._style.headerBackgroundColor ); } @@ -4313,9 +4277,7 @@ export class DataGrid extends Widget { this._paintMergedCells( cellGroups, rgn, - this._style.backgroundColor, - this._style.horizontalGridLineColor || this._style.gridLineColor, - this._style.verticalGridLineColor || this._style.gridLineColor + this._style.backgroundColor ); } @@ -4465,10 +4427,7 @@ export class DataGrid extends Widget { this._paintMergedCells( cellGroups, rgn, - this._style.headerBackgroundColor, - this._style.headerHorizontalGridLineColor || - this._style.headerGridLineColor, - this._style.headerVerticalGridLineColor || this._style.headerGridLineColor + this._style.headerBackgroundColor ); } @@ -4618,10 +4577,7 @@ export class DataGrid extends Widget { this._paintMergedCells( cellGroups, rgn, - this._style.headerBackgroundColor, - this._style.headerHorizontalGridLineColor || - this._style.headerGridLineColor, - this._style.headerVerticalGridLineColor || this._style.headerGridLineColor + this._style.headerBackgroundColor ); } @@ -4755,10 +4711,7 @@ export class DataGrid extends Widget { this._paintMergedCells( cellGroups, rgn, - this._style.headerBackgroundColor, - this._style.headerHorizontalGridLineColor || - this._style.headerGridLineColor, - this._style.headerVerticalGridLineColor || this._style.headerGridLineColor + this._style.headerBackgroundColor ); } @@ -5070,9 +5023,7 @@ export class DataGrid extends Widget { private _paintMergedCells( cellGroups: CellGroup[], rgn: Private.PaintRegion, - backgroundColor: string | undefined, - verticalColor: string | undefined, - horizontalColor: string | undefined + backgroundColor: string | undefined ): void { // Bail if there is no data model. if (!this._dataModel) { @@ -5176,12 +5127,16 @@ export class DataGrid extends Widget { config.metadata = metadata; // Compute the actual X bounds for the cell. - let x1 = Math.max(rgn.xMin, x); - let x2 = Math.min(x + width - 1, rgn.xMax); + const x1 = Math.max(rgn.xMin, x); + const x2 = Math.min(x + width - 2, rgn.xMax); // Compute the actual Y bounds for the cell. - let y1 = Math.max(rgn.yMin, y); - let y2 = Math.min(y + height - 1, rgn.yMax); + const y1 = Math.max(rgn.yMin, y); + const y2 = Math.min(y + height - 2, rgn.yMax); + + if (x2 <= x1 || y2 <= y1) { + continue; + } // Draw the background. if (backgroundColor) { @@ -5208,38 +5163,6 @@ export class DataGrid extends Widget { gc.restore(); this._blitContent(this._buffer, x1, y1, x2 - x1 + 1, y2 - y1 + 1, x1, y1); - - if (verticalColor) { - // Begin the path for the grid lines. - this._canvasGC.beginPath(); - - // Why do we not need this? - // this._canvasGC.moveTo(x1, y1); - // this._canvasGC.lineTo(x1, y2); - - this._canvasGC.moveTo(x2 + 0.5, y1); - this._canvasGC.lineTo(x2 + 0.5, y2 + 1); - - // Stroke the lines with the specified color. - this._canvasGC.strokeStyle = verticalColor; - this._canvasGC.stroke(); - } - - if (horizontalColor) { - // Begin the path for the grid lines. - this._canvasGC.beginPath(); - - // Why do we not need this? - // this._canvasGC.moveTo(x1, y1); - // this._canvasGC.lineTo(x2, y1); - - this._canvasGC.moveTo(x1, y2 + 0.5); - this._canvasGC.lineTo(x2 + 1, y2 + 0.5); - - // Stroke the lines with the specified color. - this._canvasGC.strokeStyle = horizontalColor; - this._canvasGC.stroke(); - } } // Dispose of the wrapped gc. @@ -5262,7 +5185,8 @@ export class DataGrid extends Widget { } // Compute the X bounds for the horizontal lines. - let x1 = Math.max(rgn.xMin, rgn.x); + const x1 = Math.max(rgn.xMin, rgn.x); + const x2 = Math.min(rgn.x + rgn.width, rgn.xMax + 1); // Begin the path for the grid lines. this._canvasGC.beginPath(); @@ -5271,8 +5195,8 @@ export class DataGrid extends Widget { this._canvasGC.lineWidth = 1; // Fetch the geometry. - let bh = this.bodyHeight; - let ph = this.pageHeight; + const bh = this.bodyHeight; + const ph = this.pageHeight; // Fetch the number of grid lines to be drawn. let n = rgn.rowSizes.length; @@ -5299,7 +5223,6 @@ export class DataGrid extends Widget { // Draw the line if it's in range of the dirty rect. if (pos >= rgn.yMin && pos <= rgn.yMax) { - const x2 = Math.min(rgn.x + rgn.width, rgn.xMax + 1); this._canvasGC.moveTo(x1, pos + 0.5); this._canvasGC.lineTo(x2, pos + 0.5); } @@ -5326,7 +5249,8 @@ export class DataGrid extends Widget { } // Compute the Y bounds for the vertical lines. - let y1 = Math.max(rgn.yMin, rgn.y); + const y1 = Math.max(rgn.yMin, rgn.y); + const y2 = Math.min(rgn.y + rgn.height, rgn.yMax + 1); // Begin the path for the grid lines this._canvasGC.beginPath(); @@ -5335,8 +5259,8 @@ export class DataGrid extends Widget { this._canvasGC.lineWidth = 1; // Fetch the geometry. - let bw = this.bodyWidth; - let pw = this.pageWidth; + const bw = this.bodyWidth; + const pw = this.pageWidth; // Fetch the number of grid lines to be drawn. let n = rgn.columnSizes.length; @@ -5363,7 +5287,6 @@ export class DataGrid extends Widget { // Draw the line if it's in range of the dirty rect. if (pos >= rgn.xMin && pos <= rgn.xMax) { - let y2 = Math.min(rgn.y + rgn.height, rgn.yMax + 1); this._canvasGC.moveTo(pos + 0.5, y1); this._canvasGC.lineTo(pos + 0.5, y2); } From e0fd7af2d201bb4e9f94049f2cbdf653171a7082 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Mon, 19 Sep 2022 17:02:06 +0200 Subject: [PATCH 19/25] Linter --- packages/datagrid/src/datagrid.ts | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/packages/datagrid/src/datagrid.ts b/packages/datagrid/src/datagrid.ts index d43f790d3..29641b862 100644 --- a/packages/datagrid/src/datagrid.ts +++ b/packages/datagrid/src/datagrid.ts @@ -4274,11 +4274,7 @@ export class DataGrid extends Widget { }); // Draw merged cells - this._paintMergedCells( - cellGroups, - rgn, - this._style.backgroundColor - ); + this._paintMergedCells(cellGroups, rgn, this._style.backgroundColor); } /** @@ -4424,11 +4420,7 @@ export class DataGrid extends Widget { }); // Draw merged cells - this._paintMergedCells( - cellGroups, - rgn, - this._style.headerBackgroundColor - ); + this._paintMergedCells(cellGroups, rgn, this._style.headerBackgroundColor); } /** @@ -4574,11 +4566,7 @@ export class DataGrid extends Widget { }); // Draw merged cells - this._paintMergedCells( - cellGroups, - rgn, - this._style.headerBackgroundColor - ); + this._paintMergedCells(cellGroups, rgn, this._style.headerBackgroundColor); } /** @@ -4708,11 +4696,7 @@ export class DataGrid extends Widget { }); // Draw merged cells - this._paintMergedCells( - cellGroups, - rgn, - this._style.headerBackgroundColor - ); + this._paintMergedCells(cellGroups, rgn, this._style.headerBackgroundColor); } /** From 32952d7bc4cc6380582a1a8eb7ac107399ab0fd2 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Mon, 19 Sep 2022 17:09:10 +0200 Subject: [PATCH 20/25] Fix headers positioning --- packages/datagrid/src/datagrid.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/datagrid/src/datagrid.ts b/packages/datagrid/src/datagrid.ts index 29641b862..06397c43b 100644 --- a/packages/datagrid/src/datagrid.ts +++ b/packages/datagrid/src/datagrid.ts @@ -5085,10 +5085,10 @@ export class DataGrid extends Widget { this._columnSections.offsetOf(group.c1) + this.headerWidth - this._scrollX; - y = this._rowSections.offsetOf(group.r1) - this._scrollY; + y = this._rowSections.offsetOf(group.r1); break; case 'row-header': - x = this._columnSections.offsetOf(group.c1) - this._scrollX; + x = this._columnSections.offsetOf(group.c1); y = this._rowSections.offsetOf(group.r1) + this.headerHeight - From e8caef5c309b8ce832504d0e66af593976108d50 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Mon, 19 Sep 2022 17:42:55 +0200 Subject: [PATCH 21/25] Introduce a PixelRegion type --- packages/datagrid/src/datagrid.ts | 37 ++++++++++++++----------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/packages/datagrid/src/datagrid.ts b/packages/datagrid/src/datagrid.ts index 06397c43b..f53dfaafb 100644 --- a/packages/datagrid/src/datagrid.ts +++ b/packages/datagrid/src/datagrid.ts @@ -3264,8 +3264,6 @@ export class DataGrid extends Widget { index ); - // TODO We're not creating a fully implemented paint-region, - // We probably need another type let paintRgn = { region: rgn, xMin: 0, @@ -3297,7 +3295,7 @@ export class DataGrid extends Widget { this._paintMergedCells( cellGroups, - paintRgn as Private.PaintRegion, + paintRgn, backgroundColor ); } @@ -3423,8 +3421,6 @@ export class DataGrid extends Widget { index ); - // TODO We're not creating a fully implemented paint-region, - // We probably need another type let paintRgn = { region: rgn, xMin: 0, @@ -3456,7 +3452,7 @@ export class DataGrid extends Widget { this._paintMergedCells( cellGroups, - paintRgn as Private.PaintRegion, + paintRgn, backgroundColor ); } @@ -3561,8 +3557,6 @@ export class DataGrid extends Widget { index ); - // TODO We're not creating a fully implemented paint-region, - // We probably need another type let paintRgn = { region: rgn, xMin: 0, @@ -3588,7 +3582,7 @@ export class DataGrid extends Widget { this._paintMergedCells( cellGroups, - paintRgn as Private.PaintRegion, + paintRgn, this._style.headerBackgroundColor ); } @@ -3696,8 +3690,6 @@ export class DataGrid extends Widget { index ); - // TODO We're not creating a fully implemented paint-region, - // We probably need another type let paintRgn = { region: rgn, xMin: 0, @@ -3723,7 +3715,7 @@ export class DataGrid extends Widget { this._paintMergedCells( cellGroups, - paintRgn as Private.PaintRegion, + paintRgn, this._style.headerBackgroundColor ); } @@ -5006,7 +4998,7 @@ export class DataGrid extends Widget { */ private _paintMergedCells( cellGroups: CellGroup[], - rgn: Private.PaintRegion, + rgn: Private.PixelRegion, backgroundColor: string | undefined ): void { // Bail if there is no data model. @@ -6580,9 +6572,9 @@ namespace Private { } /** - * An object which represents a region to be painted. + * An object which represents a canvas region in pixels. */ - export type PaintRegion = { + export type PixelRegion = { /** * The min X coordinate the of the dirty viewport rect. * @@ -6615,6 +6607,16 @@ namespace Private { */ yMax: number; + /** + * The cell region. + */ + region: DataModel.CellRegion; + }; + + /** + * An object which represents a region to be painted. + */ + export type PaintRegion = PixelRegion & { /** * The X coordinate the of the region, in viewport coordinates. * @@ -6647,11 +6649,6 @@ namespace Private { */ height: number; - /** - * The cell region being painted. - */ - region: DataModel.CellRegion; - /** * The row index of the first cell in the region. */ From 68e222306bd4cfea69911a912f9831409f14e5b6 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Mon, 19 Sep 2022 17:44:03 +0200 Subject: [PATCH 22/25] Linters --- packages/datagrid/src/datagrid.ts | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/packages/datagrid/src/datagrid.ts b/packages/datagrid/src/datagrid.ts index f53dfaafb..c7bc2f52a 100644 --- a/packages/datagrid/src/datagrid.ts +++ b/packages/datagrid/src/datagrid.ts @@ -3293,11 +3293,7 @@ export class DataGrid extends Widget { break; } - this._paintMergedCells( - cellGroups, - paintRgn, - backgroundColor - ); + this._paintMergedCells(cellGroups, paintRgn, backgroundColor); } // Paint the overlay. @@ -3450,11 +3446,7 @@ export class DataGrid extends Widget { break; } - this._paintMergedCells( - cellGroups, - paintRgn, - backgroundColor - ); + this._paintMergedCells(cellGroups, paintRgn, backgroundColor); } // Paint the overlay. From 830e0948996add44c2a8b69602151d7bea6088f5 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Tue, 20 Sep 2022 10:27:11 +0200 Subject: [PATCH 23/25] Fix issue when "slowly" scrolling merged cells It appears that when slowly scrolling merged cells, the area considered "clean" is actually not really clean if a merged group is intersected by that area. Redrawing those groups fixes it. --- packages/datagrid/src/datagrid.ts | 79 +++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/packages/datagrid/src/datagrid.ts b/packages/datagrid/src/datagrid.ts index c7bc2f52a..da880de3e 100644 --- a/packages/datagrid/src/datagrid.ts +++ b/packages/datagrid/src/datagrid.ts @@ -3828,6 +3828,45 @@ export class DataGrid extends Widget { width, Math.abs(dy) ); + + // Repaint merged cells that are intersected by the scroll level + // Otherwise it will be cut in two by the valid content, and drawn incorrectly + for (const rgn of ['body', 'row-header'] as DataModel.CellRegion[]) { + const cellgroups = CellGroup.getCellGroupsAtRegion( + this.dataModel, rgn + ); + + let paintRgn = { + region: rgn, + xMin: 0, + xMax: 0, + yMin: 0, + yMax: 0 + }; + + let backgroundColor = undefined; + + switch (rgn) { + case 'body': + paintRgn.xMin = this.headerWidth; + paintRgn.xMax = this.headerWidth + this.bodyWidth; + paintRgn.yMin = this.headerHeight; + paintRgn.yMax = this.headerHeight + this.bodyHeight; + + backgroundColor = this._style.backgroundColor; + break; + case 'row-header': + paintRgn.xMin = 0; + paintRgn.xMax = this.headerWidth; + paintRgn.yMin = this.headerHeight; + paintRgn.yMax = this.headerHeight + this.bodyHeight; + + backgroundColor = this._style.headerBackgroundColor; + break; + } + + this._paintMergedCells(cellgroups, paintRgn, backgroundColor); + } } } @@ -3852,6 +3891,46 @@ export class DataGrid extends Widget { Math.abs(dx), height ); + + // Repaint merged cells that are intersected by the scroll level + // Otherwise it will be cut in two by the valid content, and drawn incorrectly + for (const rgn of ['body', 'column-header'] as DataModel.CellRegion[]) { + const cellGroups = CellGroup.getCellGroupsAtRegion( + this.dataModel, + rgn + ); + + let paintRgn = { + region: rgn, + xMin: 0, + xMax: 0, + yMin: 0, + yMax: 0 + }; + + let backgroundColor = undefined; + + switch (rgn) { + case 'body': + paintRgn.xMin = this.headerWidth; + paintRgn.xMax = this.headerWidth + this.bodyWidth; + paintRgn.yMin = this.headerHeight; + paintRgn.yMax = this.headerHeight + this.bodyHeight; + + backgroundColor = this._style.backgroundColor; + break; + case 'column-header': + paintRgn.xMin = this.headerWidth; + paintRgn.xMax = this.headerWidth + this.bodyWidth; + paintRgn.yMin = 0; + paintRgn.yMax = this.headerHeight; + + backgroundColor = this._style.headerBackgroundColor; + break; + } + + this._paintMergedCells(cellGroups, paintRgn, backgroundColor); + } } } From dbe9ce9e3d310cb9f92cb7b0086bcb5c2b0a19aa Mon Sep 17 00:00:00 2001 From: martinRenou Date: Tue, 20 Sep 2022 10:45:58 +0200 Subject: [PATCH 24/25] Linters --- packages/datagrid/src/datagrid.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/datagrid/src/datagrid.ts b/packages/datagrid/src/datagrid.ts index da880de3e..0159e8a86 100644 --- a/packages/datagrid/src/datagrid.ts +++ b/packages/datagrid/src/datagrid.ts @@ -3833,7 +3833,8 @@ export class DataGrid extends Widget { // Otherwise it will be cut in two by the valid content, and drawn incorrectly for (const rgn of ['body', 'row-header'] as DataModel.CellRegion[]) { const cellgroups = CellGroup.getCellGroupsAtRegion( - this.dataModel, rgn + this.dataModel, + rgn ); let paintRgn = { From 479075b9b83fe21fafbe2e0239af4f6fb324ad52 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Tue, 20 Sep 2022 10:46:17 +0200 Subject: [PATCH 25/25] Battle testing --- examples/example-datagrid/src/index.ts | 40 +++++++++++++++++--------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/examples/example-datagrid/src/index.ts b/examples/example-datagrid/src/index.ts index 114a743fa..5707c5688 100644 --- a/examples/example-datagrid/src/index.ts +++ b/examples/example-datagrid/src/index.ts @@ -30,12 +30,30 @@ import { getKeyboardLayout } from '@lumino/keyboard'; import '../style/index.css'; class MergedCellModel extends DataModel { + constructor() { + super(); + + // Initializing the body groups + for ( + let r = 0, c = 0; + r < this.rowCount('body') && c < this.columnCount('body'); + r += 3, c += 3 + ) { + this.bodyGroups.push({ r1: r, c1: c, r2: r + 2, c2: c + 2 }); + } + + // Initializing the row-header groups + for (let r = 0; r < this.rowCount('body'); r += 2) { + this.rowHeaderGroups.push({ r1: r, c1: 0, r2: r + 1, c2: 1 }); + } + } + rowCount(region: DataModel.RowRegion): number { - return region === 'body' ? 20 : 3; + return region === 'body' ? 500 : 3; } columnCount(region: DataModel.ColumnRegion): number { - return region === 'body' ? 6 : 3; + return region === 'body' ? 500 : 3; } data(region: DataModel.CellRegion, row: number, column: number): any { @@ -53,11 +71,11 @@ class MergedCellModel extends DataModel { groupCount(region: DataModel.RowRegion): number { if (region === 'body') { - return 3; + return this.bodyGroups.length; } else if (region === 'column-header') { return 1; } else if (region === 'row-header') { - return 2; + return this.rowHeaderGroups.length; } else if (region === 'corner-header') { return 1; } @@ -66,11 +84,7 @@ class MergedCellModel extends DataModel { group(region: DataModel.CellRegion, groupIndex: number): CellGroup | null { if (region === 'body') { - return [ - { r1: 1, c1: 1, r2: 2, c2: 2 }, - { r1: 5, c1: 1, r2: 5, c2: 2 }, - { r1: 3, c1: 5, r2: 4, c2: 5 } - ][groupIndex]; + return this.bodyGroups[groupIndex]; } if (region === 'column-header') { @@ -78,10 +92,7 @@ class MergedCellModel extends DataModel { } if (region === 'row-header') { - return [ - { r1: 0, c1: 0, r2: 1, c2: 1 }, - { r1: 4, c1: 0, r2: 5, c2: 0 } - ][groupIndex]; + return this.rowHeaderGroups[groupIndex]; } if (region === 'corner-header') { @@ -90,6 +101,9 @@ class MergedCellModel extends DataModel { return null; } + + rowHeaderGroups: CellGroup[] = []; + bodyGroups: CellGroup[] = []; } class LargeDataModel extends DataModel {