-
Notifications
You must be signed in to change notification settings - Fork 143
Grid Properties
When we speak collectively of grid properties (a.k.a. look & feel or LnF properties), we are actually referring to a stack of JavaScript objects that describe the appearance and behavior of the grid as well as individual columns, rows and cells.
This stack of properties collections (as we call them) takes full advantage of JavaScript's prototype chain.
Advisory: Before continuing, make sure you have a firm grasp of prototypal inheritance, specifically as pertains to plain objects: How the prototype chain works at a basic level, without regard to object constructors and methods, and what it means for an object to have been "extended from" or "created from" another object.
The semantics of the properties stack are laid out in the next section, but before we get to that let's define the various types of LnF properties collections.
Given a grid instance that models (represents) the grid,, for example var grid = new Hypergrid
, the grid's properties collection is referenced as grid.properties
.
Columns are also backed by column objects. For example var column = grid.getColumn(i)
models a given column i
whose properties collection is referenced as column.properties
. All column properties
collections have their prototype set to grid.properties
. In this way, a column LnF property overrides the grid LnF property of the same name — but only when the column has such a property; otherwise the grid property applies to that column.
For performance reasons, individual cells in Hypergrid are not modeled. They can however have a properties collection. Hypergrid only creates a cell properties collection when needed; cells with no LnF properties to override do not have a properties collection because they do not require one. Many methods exist for setting and getting cell LnF properties and cell properties collections, for example column.setCellProperty(y, key, value)
, which sets a property key
on the cell in row y
to value
. Setting even a single LnF property on a cell creates a properties collection for that cell (with column.prototype
as its prototype, and so forth, recalling that the column's prototype is in turn set to grid.properties
). When an application tries to get a cell's LnF property but the cell doesn't actually have a properties collection, the column's LnF property with the same name is referenced instead. (There are also methods to explicitly reference a cell LnF property or property collection, returning results iff the collection exists.)
Rows, like cells, are not modeled and only have LnF properties collections created for them as needed.
Implementation note: Unlike cell (and column) properties collections, row properties collections do not participate in the prototype chain. Row LnF properties must be explicitly copied to the LnF
config
object handed to the cell renderer for each and every cell. Furthermore, when cell LnF props are applied after row LnF props, the cells' props must be copied as well. None of this is necessary when row properties are disabled.
Row stripes can be thought of as global row LnF properties, on top of which regular row LNF properties can be layered. Row properties objects exist in an array in the rowStripes
property, which is provided modulo (cyclically). When rowStripes
is falsy, there are no row stripes properties collections, and hence no row striping.
Each cell in a grid has a stack of properties collections objects, implemented as a JavaScript prototype chain.
This properties stack effects a cascade, somewhat like a web page's Cascading Style Sheets (CSS), which is to say that each cell of the grid is rendered according to a reduction of each of the layers described above. Properties defined in upper layers of the stack supersede those of the same name defined in lower layers. The bottom layer contains a complete set of defaults, fallback values for the required properties.
For each grid cell, the stack consists of the following layers, listed here from the bottom up:
At the root of the properties stack is the defaults
object, containing the default definitions for all properties. All succeeding layer are instance layers (owned by a specific grid instance).
This layer is common to all grid instances. Applying a global theme actually overwrites properties in this layer.
Synonym: Hypergrid.properties
.
Each grid instance starts with it's own theme
layer, which is where skin adjustments are applied.
Each grid instance continues with this properties
layer, which contains the grid's "own" properties, including its dynamic grid property setters/getters.
Each column object has its own properties
object, extended from grid.properties
.
Each cell may potentially have its own properties
object, extended from the cell's column.properties
object. Cell properties objects differ from the other properties objects, however, in that they are only created as needed. See Accessing cell properties below for more info.
This layer is only available at render time. This is the configuration object passed through the application's optional getCell
function, which may freely mutate it, before it is then passed to the cell renderer.
The properties stack effects a cascade, somewhat like a web page's Cascading Style Sheets (CSS), which is to say that each cell of the grid is rendered according to a reduction of each of the layers described above.
For example, consider a specific property, color
. This property accepts a CSS color spec for rendering text. To set the text color for the entire grid (i.e., all cells of all columns) to red, simply set it on the grid properties object:
grid.properties.color = 'red';
To set only one column to red, set it on the column properties object:
var column = grid.behavior.getColumn(3);
column.properties.color = 'red';
To set all but one column to red:
grid.properties.color = 'red';
var column = grid.behavior.getColumn(3);
column.properties.color = grid.theme.color;
To set a particular cell to red, set it on the cell properties object:
grid.behavior.setCellProperty(99, 3, 'color', 'red');
which sets the color of only the cell on the 100th row in column 3 to red. Be careful when using the row index, which is subject to change if rows are added or deleted above it!
It is also possible to control grid properties programmatically. See Dynamic Grid Properties for more information.
Accessing cell properties is not as straight-forward as accessing column and grid properties because cell properties objects are only created as needed. This is because Hypergrid does not model individual cells; there are no objects so you cannot simply say cell
.cell.properties
Rather, individual cell properties are accessed via the various getCellProperty()
and setCellProperty()
methods, which is the recommended approach. (See above example.)
That said, if you prefer to work with a cell properties object directly, you can call getCellProperties()
. However, if the cell does not have a properties object, this method will return its column's properties object instead, which is fine if you only intend to reference properties read-only. But if you wish to add a new property to a cell properties object, you must call addCellProperties()
instead. If the cell had no properties object before, it will create an empty one and Object.assign
new new properties to it. Both of the following do the same thing:
var column = grid.behavior.getColumn(3);
column.setCellProperty(99, 'color', 'red');
var cellProps = grid.behavior.addCellProperties(99, 3, { color: 'red' });
Only call this method when you intend to create a new cell property because otherwise you will end up littering your grid with empty cell properties objects which will eventually fill memory and are also non-performant.
Finally, to attach an entire properties object to a cell, you can call setCellProperties()
:
grid.behavior.setCellProperties(99, 3, { color: 'red' });
CellEvent
objects are used extensively internally. These objects are created when cells are laid out for rendering. They contain many internal properties (mostly getters, actually) as well as access to the cell's properties
object similar to the above. See the Working with CellEvent objects wiki for more information.