Skip to content

Commit

Permalink
MultiGrid ensures correct row/column indices are passed to ellMeasure…
Browse files Browse the repository at this point in the history
…rCache for top-right and bottom Grids. (Resolves #670)
  • Loading branch information
Brian Vaughn committed May 8, 2017
1 parent 726b81e commit d88ad4c
Show file tree
Hide file tree
Showing 4 changed files with 224 additions and 1 deletion.
2 changes: 1 addition & 1 deletion source/Grid/Grid.jest.js
Original file line number Diff line number Diff line change
Expand Up @@ -1232,7 +1232,7 @@ describe('Grid', () => {

it('should pass the cellRenderer an :isScrolling flag based on props override', () => {
const cellRenderer = jest.fn()
cellRenderer.mockImplementation(({ key }) => <div key={key} />)
cellRenderer.mockImplementation(({ key, style }) => <div key={key} style={style} />)
render(getMarkup({
cellRenderer,
isScrolling: true
Expand Down
119 changes: 119 additions & 0 deletions source/MultiGrid/CellMeasurerCacheDecorator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/** @flow */
import { CellMeasurerCache } from '../CellMeasurer'

type CellMeasurerCacheDecoratorParams = {
cellMeasurerCache: CellMeasurerCache,
columnIndexOffset: number,
rowIndexOffset: number
};

type IndexParam = {
index: number
};

/**
* Caches measurements for a given cell.
*/
export default class CellMeasurerCacheDecorator {
_cellMeasurerCache: CellMeasurerCache;
_columnIndexOffset: number;
_rowIndexOffset: number;

constructor (params : CellMeasurerCacheDecoratorParams = {}) {
const {
cellMeasurerCache,
columnIndexOffset = 0,
rowIndexOffset = 0
} = params

this._cellMeasurerCache = cellMeasurerCache
this._columnIndexOffset = columnIndexOffset
this._rowIndexOffset = rowIndexOffset
}

clear (
rowIndex: number,
columnIndex: number
) : void {
this._cellMeasurerCache.clear(
rowIndex + this._rowIndexOffset,
columnIndex + this._columnIndexOffset
)
}

clearAll () : void {
this._cellMeasurerCache.clearAll()
}

columnWidth = ({ index } : IndexParam) => {
this._cellMeasurerCache.columnWidth({
index: index + this._columnIndexOffset
})
}

get defaultHeight () : number {
return this._cellMeasurerCache.defaultHeight
}

get defaultWidth () : number {
return this._cellMeasurerCache.defaultWidth
}

hasFixedHeight () : boolean {
return this._cellMeasurerCache.hasFixedHeight()
}

hasFixedWidth () : boolean {
return this._cellMeasurerCache.hasFixedWidth()
}

getHeight (
rowIndex: number,
columnIndex: ?number = 0
) : ?number {
return this._cellMeasurerCache.getHeight(
rowIndex + this._rowIndexOffset,
columnIndex + this._columnIndexOffset
)
}

getWidth (
rowIndex: number,
columnIndex: ?number = 0
) : ?number {
return this._cellMeasurerCache.getWidth(
rowIndex + this._rowIndexOffset,
columnIndex + this._columnIndexOffset
)
}

has (
rowIndex: number,
columnIndex: ?number = 0
) : boolean {
return this._cellMeasurerCache.has(
rowIndex + this._rowIndexOffset,
columnIndex + this._columnIndexOffset
)
}

rowHeight = ({ index } : IndexParam) => {
this._cellMeasurerCache.rowHeight({
index: index + this._rowIndexOffset
})
}

set (
rowIndex: number,
columnIndex: number,
width: number,
height: number
) : void {
this._cellMeasurerCache.set(
rowIndex + this._rowIndexOffset,
columnIndex + this._columnIndexOffset,
width: number,
height: number
)
}
}
72 changes: 72 additions & 0 deletions source/MultiGrid/MultiGrid.jest.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react'
import { findDOMNode } from 'react-dom'
import { render } from '../TestUtils'
import MultiGrid from './MultiGrid'
import { CellMeasurerCache } from '../CellMeasurer'

// These tests only focus on what MultiGrid does specifically.
// The inner Grid component is tested in depth elsewhere.
Expand Down Expand Up @@ -343,4 +344,75 @@ describe('MultiGrid', () => {
expect(bottomRightGrid.scrollTop).toEqual(750)
})
})

describe('deferredMeasurementCache', (props = {}) => {
function getDeferredMeasurementCache () {
const deferredMeasurementCache = new CellMeasurerCache({
fixedHeight: true,
fixedWidth: true
})

deferredMeasurementCache._columnIndices = {}
deferredMeasurementCache._rowIndices = {}
deferredMeasurementCache.has = (rowIndex, columnIndex) => {
deferredMeasurementCache._columnIndices[columnIndex] = columnIndex
deferredMeasurementCache._rowIndices[rowIndex] = rowIndex
return true
}

return deferredMeasurementCache
}

it('should wrap top-right and bottom-right deferredMeasurementCache if fixedColumnCount is > 0', () => {
const deferredMeasurementCache = getDeferredMeasurementCache()
render(getMarkup({
deferredMeasurementCache: deferredMeasurementCache,
columnCount: 3,
fixedColumnCount: 1,
fixedRowCount: 0,
rowCount: 1
}))

expect(Object.keys(deferredMeasurementCache._columnIndices)).toEqual(['0', '1', '2'])
})

it('should not wrap top-right and bottom-right deferredMeasurementCache if fixedColumnCount is 0', () => {
const deferredMeasurementCache = getDeferredMeasurementCache()
render(getMarkup({
deferredMeasurementCache: deferredMeasurementCache,
columnCount: 2,
fixedColumnCount: 0,
fixedRowCount: 0,
rowCount: 1
}))

expect(Object.keys(deferredMeasurementCache._columnIndices)).toEqual(['0', '1'])
})

it('should wrap bottom-left and bottom-right deferredMeasurementCache if fixedRowCount is > 0', () => {
const deferredMeasurementCache = getDeferredMeasurementCache()
render(getMarkup({
deferredMeasurementCache: deferredMeasurementCache,
columnCount: 1,
fixedColumnCount: 0,
fixedRowCount: 1,
rowCount: 3
}))

expect(Object.keys(deferredMeasurementCache._rowIndices)).toEqual(['0', '1', '2'])
})

it('should not wrap bottom-left and bottom-right deferredMeasurementCache if fixedRowCount is 0', () => {
const deferredMeasurementCache = getDeferredMeasurementCache()
render(getMarkup({
deferredMeasurementCache: deferredMeasurementCache,
columnCount: 1,
fixedColumnCount: 0,
fixedRowCount: 0,
rowCount: 2
}))

expect(Object.keys(deferredMeasurementCache._rowIndices)).toEqual(['0', '1'])
})
})
})
32 changes: 32 additions & 0 deletions source/MultiGrid/MultiGrid.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/** @flow */
import PropTypes from 'prop-types'
import React, { PureComponent } from 'react'
import CellMeasurerCacheDecorator from './CellMeasurerCacheDecorator'
import Grid from '../Grid'

const SCROLLBAR_SIZE_BUFFER = 20
Expand Down Expand Up @@ -140,7 +141,35 @@ export default class MultiGrid extends PureComponent {
}

componentWillMount () {
const { deferredMeasurementCache, fixedColumnCount, fixedRowCount } = this.props

this._maybeCalculateCachedStyles(null, this.props, null, this.state)

if (deferredMeasurementCache) {
this._deferredMeasurementCacheBottomLeftGrid = fixedRowCount > 0
? new CellMeasurerCacheDecorator({
cellMeasurerCache: deferredMeasurementCache,
columnIndexOffset: 0,
rowIndexOffset: fixedRowCount
})
: deferredMeasurementCache

this._deferredMeasurementCacheBottomRightGrid = fixedColumnCount > 0 || fixedRowCount > 0
? new CellMeasurerCacheDecorator({
cellMeasurerCache: deferredMeasurementCache,
columnIndexOffset: fixedColumnCount,
rowIndexOffset: fixedRowCount
})
: deferredMeasurementCache

this._deferredMeasurementCacheTopRightGrid = fixedColumnCount > 0
? new CellMeasurerCacheDecorator({
cellMeasurerCache: deferredMeasurementCache,
columnIndexOffset: fixedColumnCount,
rowIndexOffset: 0
})
: deferredMeasurementCache
}
}

componentWillReceiveProps (nextProps, nextState) {
Expand Down Expand Up @@ -550,6 +579,7 @@ export default class MultiGrid extends PureComponent {
{...props}
cellRenderer={this._cellRendererBottomLeftGrid}
columnCount={fixedColumnCount}
deferredMeasurementCache={this._deferredMeasurementCacheBottomLeftGrid}
height={this._getBottomGridHeight(props)}
ref={this._bottomLeftGridRef}
rowCount={Math.max(0, rowCount - fixedRowCount) + 1/* See _rowHeightBottomGrid */}
Expand Down Expand Up @@ -578,6 +608,7 @@ export default class MultiGrid extends PureComponent {
cellRenderer={this._cellRendererBottomRightGrid}
columnCount={Math.max(0, columnCount - fixedColumnCount)}
columnWidth={this._columnWidthRightGrid}
deferredMeasurementCache={this._deferredMeasurementCacheBottomRightGrid}
height={this._getBottomGridHeight(props)}
onScroll={this._onScroll}
ref={this._bottomRightGridRef}
Expand Down Expand Up @@ -633,6 +664,7 @@ export default class MultiGrid extends PureComponent {
cellRenderer={this._cellRendererTopRightGrid}
columnCount={Math.max(0, columnCount - fixedColumnCount) + 1/* See _columnWidthRightGrid */}
columnWidth={this._columnWidthRightGrid}
deferredMeasurementCache={this._deferredMeasurementCacheTopRightGrid}
height={this._getTopGridHeight(props)}
ref={this._topRightGridRef}
rowCount={fixedRowCount}
Expand Down

0 comments on commit d88ad4c

Please sign in to comment.