new Renderer()
fin-hypergrid-renderer is the canvas enabled top level sub component that handles the renderering of the Grid.
It relies on two other external subprojects
- fin-canvas: a wrapper to provide a simpler interface to the HTML5 canvas component
- rectangular: a small npm module providing Point and Rectangle objects
The fin-hypergrid-renderer is in a unique position to provide critical functionality to the fin-hypergrid in a hightly performant manner. Because it MUST iterate over all the visible cells it can store various bits of information that can be encapsulated as a service for consumption by the fin-hypergrid component.
Instances of this object have basically four main functions.
- render fixed row headers
- render fixed col headers
- render main data cells
- render grid lines
Same parameters as initialize
, which is called by this constructor.
Members
properties
CAUTION: Keep in place! Used by Canvas
.
Methods
getBoundsOfCell(x, yopt) → {Rectangle}
Parameters:
Name | Type | Attributes | Description |
---|---|---|---|
x |
CellEvent | number | CellEvent object or grid column coordinate. |
|
y |
number |
<optional> |
Grid row coordinate. Omit if |
Returns:
Bounding rect of cell with the given coordinates.
- Type
- Rectangle
getColumnFromPixelX(pixelX) → {number}
answer the column index under the coordinate at pixelX
Parameters:
Name | Type | Description |
---|---|---|
pixelX |
number | The horizontal coordinate. |
Returns:
The column index under the coordinate at pixelX.
- Type
- number
getFinalVisibleColumnBoundary() → {number}
Returns:
The width x coordinate of the last rendered column
- Type
- number
getGridCellFromMousePoint(point) → {Object}
Answer specific data cell coordinates given mouse coordinates in pixels.
Parameters:
Name | Type | Description |
---|---|---|
point |
Point |
Returns:
Cell coordinates
- Type
- Object
getPageDownRow() → {number}
Returns:
The row to goto for a page down.
- Type
- number
getPageUpRow() → {number}
Returns:
The row to go to for a page up.
- Type
- number
getRenderedHeight() → {number}
Returns:
The rendered row height at index
- Type
- number
getRenderedWidth() → {number}
Returns:
The rendered column width at index
- Type
- number
getScrollLeft() → {number}
Returns:
Current horizontal scroll value.
- Type
- number
getScrollTop() → {number}
Returns:
Current vertical scroll value.
- Type
- number
getVisibleColumn(columnIndex) → {object|undefined}
Find a visible column object.
Requested column may not be visible due to being scrolled out of view.
Parameters:
Name | Type | Description |
---|---|---|
columnIndex |
number | The grid column index. |
Returns:
The given column if visible or undefined
if not.
- Type
- object | undefined
getVisibleColumnsCount() → {number}
Returns:
Number of columns we just rendered.
- Type
- number
getVisibleDataColumn(columnIndex) → {object|undefined}
Find a visible column object.
Requested column may not be visible due to being scrolled out of view or if the column is inactive.
Parameters:
Name | Type | Description |
---|---|---|
columnIndex |
number | The grid column index. |
Returns:
The given column if visible or undefined
if not.
- Type
- object | undefined
getVisibleDataRow(rowIndex, subgridopt) → {object|undefined}
Find a visible row object.
Requested row may not be visible due to being scrolled out of view.
Parameters:
Name | Type | Attributes | Default | Description |
---|---|---|---|---|
rowIndex |
number | The data row index within the given subgrid. |
||
subgrid |
DataModel |
<optional> |
this.behavior.subgrids.data |
Returns:
The given row if visible or undefined
if not.
- Type
- object | undefined
getVisibleRow(rowIndex) → {object|undefined}
Find a visible row object.
Requested row may not be visible due to being outside the bounds of the rendered grid.
Parameters:
Name | Type | Description |
---|---|---|
rowIndex |
number | The grid row index. |
Returns:
The given row if visible or undefined
if not.
- Type
- object | undefined
getVisibleRowsCount() → {number}
Returns:
Answer how many rows we rendered
- Type
- number
initialize()
Constructor logic
This method will be called upon instantiation of this class or of any class that extends from this class.
All
initialize()
methods in the inheritance chain are called, in turn, each with the same parameters that were passed to the constructor, beginning with that of the most "senior" class through that of the class of the new instance.
isColumnVisible(columnIndex) → {boolean}
Determines if a column is visible.
Requested column may not be visible due to being scrolled out of view.
Parameters:
Name | Type | Description |
---|---|---|
columnIndex |
number | the column index |
Returns:
The given column is visible.
- Type
- boolean
isDataColumnVisible(columnIndex) → {boolean}
Determines if a column is visible.
Requested column may not be visible due to being scrolled out of view or if the column is inactive.
Parameters:
Name | Type | Description |
---|---|---|
columnIndex |
number | the column index |
Returns:
The given column is visible.
- Type
- boolean
isDataRowVisible(rowIndex, subgridopt) → {boolean}
Determines visibility of a row.
Requested row may not be visible due to being scrolled out of view.
Parameters:
Name | Type | Attributes | Default | Description |
---|---|---|---|---|
rowIndex |
number | The data row index. |
||
subgrid |
DataModel |
<optional> |
this.behavior.subgrids.data |
Returns:
The given row is visible.
- Type
- boolean
isDraggingColumn() → {boolean}
Returns:
User is currently dragging a column for reordering.
- Type
- boolean
isLastColumnVisible() → {boolean}
Returns:
The last col was rendered (is visible)
- Type
- boolean
isRowVisible(rowIndex) → {boolean}
Determines visibility of a row.
Requested row may not be visible due to being outside the bounds of the rendered grid.
Parameters:
Name | Type | Description |
---|---|---|
rowIndex |
number | The grid row index. |
Returns:
The given row is visible.
- Type
- boolean
isSelected(x, y) → {boolean}
Determines if a cell is selected.
Parameters:
Name | Type | Description |
---|---|---|
x |
number | the x cell coordinate |
y |
number | the y cell coordinate* |
Returns:
The given cell is fully visible.
- Type
- boolean
paint(gc)
Notify the fin-hypergrid every time we've repainted.
This is the entry point from fin-canvas.
Parameters:
Name | Type | Description |
---|---|---|
gc |
CanvasRenderingContext2D |
paintCellsAsNeeded(gc)
Render the grid only as needed ("partial render").
Paints all the cells of a grid, one column at a time, but only as needed.
Partial render is supported only by those cells whose cell renderer supports it by returning before rendering (based on config.snapshot
).
On reset
Defers to paintCellsByColumnsAndRows
, which clears the canvas, draws the grid, and draws the grid lines.
On the next call (after reset)
Each cell is drawn redrawn only when its appearance changes. This determination is made by the cell renderer by comparing with (and maintaining) config.snapshot
. See SimpleCell
for a sample implementation.
try...catch
surrounds each cell paint in case a cell renderer throws an error.
The error message is error-logged to console AND displayed in cell.
On subsequent calls
Iterates through each cell, calling _paintCell
with undefined
prefill color. This signifies partial render to the SimpleCell
cell renderer, which only renders the cell when it's text, font, or colors have changed.
Each cell to be rendered is described by a CellEvent
object. For performance reasons, to avoid constantly instantiating these objects, we maintain a pool of these. When the grid shape changes, we reset their coordinates by setting reset
on each.
See also the discussion of clipping in paintCellsByColumns
.
This:
- {Renderer}
Parameters:
Name | Type | Description |
---|---|---|
gc |
CanvasRenderingContext2D |
paintCellsByColumns(gc)
Render the grid with consolidated column rects.
Paints all the cells of a grid, one column at a time.
First, a background rect is drawn using the grid background color.
Then, if there are any columns with their own background color that differs from the grid background color, these are consolidated and the consolidated groups of column backgrounds are all drawn before iterating through cells. Note that these column rects are not suitable for clipping overflow text from previous columns. If you have overflow text, either turn on clipping (grid.properties.columnClip = true
but big performance hit) or turn on one of the truncateTextWithEllipsis
options.
try...catch
surrounds each cell paint in case a cell renderer throws an error.
The error message is error-logged to console AND displayed in cell.
Each cell to be rendered is described by a CellEvent
object. For performance reasons, to avoid constantly instantiating these objects, we maintain a pool of these. When the grid shape changes, we reset their coordinates by setting reset
on each.
Regading clipping. The reason for clipping is to prevent text from overflowing into the next column. However there is a serious performance cost.
For performance reasons _paintCell
does not set up a clipping region for each cell. However, iff grid property columnClip
is truthy, this grid renderer will set up a clipping region to prevent text overflow to right. If columnClip
is null
, a clipping region will only be set up on the last column. Otherwise, there will be no clipping region.
The idea of clipping just the last column is because in addition to the optional graphics clipping, we also clip ("truncate") text. Text can be truncated conservatively so it will never overflow. The problem with this is that characters vanish as they hit the right cell boundary, which may or may be obvious depending on font size. Alternatively, text can be truncated so that the overflow will be a maximum of 1 character. This allows partial characters to be rendered. But this is where graphics clipping is required.
When renderering column by column as this particular renderer does, and when the background color of the next cell to the right is opaque (alpha = 1), clipping can be turned off because each column will overpaint any text that overflowed from the one before. However, any text that overflows the last column will paint into unused canvas region to the right of the grid. This is the raison d'ĂȘtre for "clip last column only" option mentioned above (when columnClip
is set to null
). To avoid even this performance cost (of clipping just the last column), column widths can be set to fill the available canvas.
Note that text never overflows to left because text starting point is never < 0. The reason we don't clip to the left is for cell renderers that need to re-render to the left to produce a merged cell effect, such as grouped column header.
This:
- {Renderer}
Parameters:
Name | Type | Description |
---|---|---|
gc |
CanvasRenderingContext2D |
paintCellsByColumnsAndRows(gc)
Render the grid with consolidated row OR column rects.
Paints all the cells of a grid, one column at a time.
First, a background rect is drawn using the grid background color.
Then, if there are any rows with their own background color that differs from the grid background color, these are consolidated and the consolidated groups of row backgrounds are all drawn before iterating through cells. These row backgrounds get priority over column backgrounds.
If there are no such row background rects to draw, the column rects are consolidated and drawn instead (again, before the cells). Note that these column rects are not suitable for clipping overflow text from previous columns. If you have overflow text, either turn on clipping (big performance hit) or turn on one of the truncateTextWithEllipsis
options.
try...catch
surrounds each cell paint in case a cell renderer throws an error.
The error message is error-logged to console AND displayed in cell.
Each cell to be rendered is described by a CellEvent
object. For performance reasons, to avoid constantly instantiating these objects, we maintain a pool of these. When the grid shape changes, we reset their coordinates by setting reset
on each.
See also the discussion of clipping in paintCellsByColumns
.
This:
- {Renderer}
Parameters:
Name | Type | Description |
---|---|---|
gc |
CanvasRenderingContext2D |
paintCellsByColumnsDiscrete(gc)
Render the grid with discrete column rects.
Paints all the cells of a grid, one column at a time.
In this grid renderer, a background rect is not drawn using the grid background color.
Rather, all columns paint their own background rects, with color defaulting to grid background color.
The idea of painting each column rect is to "clip" text that might have overflowed from the previous column by painting over it with the background from this column. Only the last column will show overflowing text, and only if the canvas width exceeds the grid width. If this is the case, you can turn on clipping for the last column only by setting columnClip
to true
for the last column.
NOTE: As a convenience feature, setting columnClip
to null
will clip only the last column, so simply setting it on the grid (rather than the last column) will have the same effect. This is much more convenient because you don't have to worry about the last column being redefined (moved, hidden, etc).
try...catch
surrounds each cell paint in case a cell renderer throws an error.
The error message is error-logged to console AND displayed in cell.
Each cell to be rendered is described by a CellEvent
object. For performance reasons, to avoid constantly instantiating these objects, we maintain a pool of these. When the grid shape changes, we reset their coordinates by setting reset
on each.
See also the discussion of clipping in paintCellsByColumnsDiscrete
.
This:
- {Renderer}
Parameters:
Name | Type | Description |
---|---|---|
gc |
CanvasRenderingContext2D |
paintCellsByRows(gc)
Render the grid.
NOTE: This grid renderer is not as performant as the others and it's use is not recommended if you care about performance. The reasons for the wanting performance are unclear, possibly having to do with the way Chrome optimizes access to the column objects?
Paints all the cells of a grid, one row at a time.
First, a background rect is drawn using the grid background color.
Then, if there are any rows with their own background color that differs from the grid background color, these are consolidated and the consolidated groups of row backgrounds are all drawn before iterating through cells.
try...catch
surrounds each cell paint in case a cell renderer throws an error.
The error message is error-logged to console AND displayed in cell.
Each cell to be rendered is described by a CellEvent
object. For performance reasons, to avoid constantly instantiating these objects, we maintain a pool of these. When the grid shape changes, we reset their coordinates by setting reset
on each.
See also the discussion of clipping in paintCellsByColumns
.
This:
- {Renderer}
Parameters:
Name | Type | Description |
---|---|---|
gc |
CanvasRenderingContext2D |
paintGridlines(gc)
We opted to not paint borders for each cell as that was extremely expensive. Instead we draw grid lines here.
Parameters:
Name | Type | Description |
---|---|---|
gc |
CanvasRenderingContext2D |
renderGrid(gc)
This is the main forking of the renderering task.
dataModel.fetchData
callback renders the grid. Note however that this is not critical when the clock is
running as it will be rendered on the next tick. We let it call it anyway in case (1) fetch returns quickly
enough to be rendered on this tick rather than next or (2) clock isn't running (for debugging purposes).
Parameters:
Name | Type | Description |
---|---|---|
gc |
CanvasRenderingContext2D |
renderOverride(gc, override)
copy each overrides specified area to it's target and blank out the source area
Parameters:
Name | Type | Description |
---|---|---|
gc |
CanvasRenderingContext2D | |
override |
OverrideObject | an object with details contain an area and a target context |
renderOverrides(gc)
iterate the renderering overrides and manifest each
Parameters:
Name | Type | Description |
---|---|---|
gc |
CanvasRenderingContext2D |