blob: cea3f536e0c69b70143b16290de68f6685fa183d [file] [log] [blame]
<div id="midcolumn">
<h3>Layers</h3>
<div id="introText">
<p>A layer is a rectangular region of grid cells. A layer has methods to access its columns, rows, width and height.
All layers implement the ILayer interface. A layer can be stacked on top of another layer in order to expose a transformed
view of its underlying layer's grid cell structure. Layers are used in this way to encapsulate grid transformation behavior
such as hiding and reordering columns.</p>
<p>Columns and rows in a layer are referenced either by <b>position</b> or <b>index</b>:
<ul>
<li>The <b>position</b> of a column/row in a layer corresponds to the physical <b>location of the column/row in the current layer</b>.
Positions always start from 0 and increase sequentially.</li>
<li>The <b>index</b> of a column/row in a layer corresponds to the <b>location of the column/row in the lowest level layer in the layer stack</b>.
Usually the lowest layer in the layer stack will be the DataLayer. Indexes are not necessarily ordered, and in some cases may not even be unique within a layer.</li>
</ul>
</p>
<p>These concepts are illustrated by the following example:</p>
<pre>
ColumnHideShowLayer C
0 1 2 3 4 &lt;- column positions
1 0 3 4 5 &lt;- column indexes
<br/>
ColumnReorderLayer B
0 1 2 3 4 5 &lt;- column positions
2 1 0 3 4 5 &lt;- column indexes
<br/>
DataLayer A
0 1 2 3 4 5 &lt;- column positions
0 1 2 3 4 5 &lt;- column indexes
</pre>
<p>In the above example, ColumnHideShowLayer C is stacked on top of ColumnReorderLayer B, which is in turn stacked on top of DataLayer A.
The positions in DataLayer A are the same as its indexes, because it is the lowest level layer in the stack. ColumnReorderLayer B
reorders column 0 of its underlying layer (DataLayer A) after column 2 of its underlying layer. ColumnHideShowLayer C hides the first
column of its underlying layer (ColumnReorderLayer B).</p>
<p>Layers can also be laterally composed into larger layers. For instance, the <a href="#gridlayer">GridLayer</a> is composed of several
layers/layer stacks for every region.</p>
<a href="images/NatTable_Architecture.png" title="NatTable Architecture">
<img align="middle" src="images/NatTable_Architecture.png" border="0" alt="NatTable Architecture" width="320"/>
</a>
<p>Following you will find the existing layers in NatTable:</p>
</div>
<div id="doccontent">
<div class="chapter">
<a name="blinklayer"></a><h5>BlinkLayer</h5>
<div class="content">
Enables the blink cell functionality i.e the cell blinks when the data in it is updated. This layer listens for the update
events and caches them locally. During rendering it uses this cache to check if data in a cell has been updated.
</div>
</div>
<div class="chapter">
<h5>ColumnGroupExpandCollapseLayer</h5>
<div class="content">
...
</div>
</div>
<div class="chapter">
<h5>ColumnGroupGroupHeaderLayer</h5>
<div class="content">
...
</div>
</div>
<div class="chapter">
<h5>ColumnGroupHeaderLayer</h5>
<div class="content">
...
</div>
</div>
<div class="chapter">
<h5>ColumnGroupReorderLayer</h5>
<div class="content">
...
</div>
</div>
<div class="chapter">
<h5>ColumnHeaderLayer</h5>
<div class="content">
...<br>
type: DimensionallyDependentLayer
</div>
</div>
<div class="chapter">
<a name="columnhideshowlayer"></a><h5>ColumnHideShowLayer</h5>
<div class="content">
Enables the hiding of columns. The layers underneath are not aware of hidden columns. When requests pass through this layer
it manipulates them to return the columns positioned after the hidden columns.
</div>
</div>
<div class="chapter">
<a name="columnreorderlayer"></a><h5>ColumnReorderLayer</h5>
<div class="content">
Tracks the reordered columns. Similar to the <a href="columnhideshowlayer">ColumnHideShowLayer</a>, the other layers are
unaware of column reordering.
</div>
</div>
<div class="chapter">
<h5>CompositeFreezeLayer</h5>
<div class="content">
...<br>
type: CompositeLayer
</div>
</div>
<div class="chapter">
<a name="cornerlayer"></a><h5>CornerLayer</h5>
<div class="content">
The CornerLayer is a layer that is used for the corner region of a grid. It is a DimensionallyDependentLayer which means
its horizontal and vertical dimensions are dependent on the horizontal and vertical dimensions of other layers. Usually it
will have a horizontal dependency to the row header layer (stack) and a vertical dependency to the column header layer
(stack). As the CornerLayer is usually rendered as an empty cell, the base layer is a DataLayer which is created by using
the DefaultCornerDataProvider.
</div>
</div>
<div class="chapter">
<a name="datalayer"></a><h5>DataLayer</h5>
<div class="content">
<p>The primary purpose of the DataLayer is to attach the IDataProvider to the table and supply data for the cells.
It also handles resize commands and tracks column/row sizes via SizeConfig objects. This layer always works with column/row indexes
i.e the position of the cell in the underlying data source. It is usually the lowermost layer in a layer stack.</p>
<p>The following specializations of the DataLayer exist:
<ul>
<li>DefaultColumnHeaderDataLayer<br/>
Specialization of a DataLayer for the column header of a grid. Sets the size of the cells to width 100 and height 20
by default.</li>
<li>DefaultRowHeaderDataLayer<br/>
Specialization of a DataLayer for the row header of a grid. Sets the size of the cells to height 40 and width 40
by default.</li>
<li>FilterRowDataLayer<br/>
Needed for the filter row of a NatTable. Will handle filter commands, adds special filter row labels to filter row
cells and provides constants that are needed to customize the filter row. It is not intended to use the FilterRowDataLayer
itself.</li>
<li>GroupByDataLayer<br/>
...</li>
<li>SpanningDataLayer<br/>
...</li>
</ul>
</p>
</div>
</div>
<div class="chapter">
<h5>FilterRowHeaderComposite</h5>
<div class="content">
...<br>
...<br>
type: CompositeLayer
uses FilterRowDataLayer
</div>
</div>
<div class="chapter">
<h5>FreezeLayer</h5>
<div class="content">
...
</div>
</div>
<div class="chapter">
<a name="glazedlistseventlayer"></a><h5>GlazedListsEventLayer</h5>
<div class="content">
This layer is meant to be used if the backing data source is a GlazedLists instance. Its acts as a listener for the
list insert/delete/update events and fires corresponding NatTable events. Hence, the table knows to repaint itself
when the underlying data changes.
</div>
</div>
<div class="chapter">
<a name="gridlayer"></a><h5>GridLayer</h5>
<div class="content">
<p>This is a top level layer used to divide up the table into grid regions. A layer or layer stack can then be assigned to each
of these regions. This layer mostly serves to delegate functions to its lower layers.</p>
<p>There is a default implementation <i>DefaultGridLayer</i> that uses DefaultBodyLayerStack, ColumnHeaderLayer, RowHeaderLayer
and <a href="#cornerlayer">CornerLayer</a> which are created out of the data information given to one of the constructors.</p>
</div>
</div>
<div class="chapter">
<h5>GroupByHeaderLayer</h5>
<div class="content">
...<br>
type: DimensionallyDependentLayer
</div>
</div>
<div class="chapter">
<h5>RowGroupHeaderLayer</h5>
<div class="content">
...
</div>
</div>
<div class="chapter">
<h5>RowHeaderLayer</h5>
<div class="content">
...<br>
type: DimensionallyDependentLayer
</div>
</div>
<div class="chapter">
<a name="selectionlayer"></a><h5>SelectionLayer</h5>
<div class="content">
<p>
Enables selection of rows, columns or cells on the table. Adds keyboard / mouse configuration used to trigger selection
and style configuration for special rendering of selection. Also hooks in the search and the tick
update features. Uses the <span class="code">SelectionModel</span> internally to track the selection state.
</p>
<p>
The <span class="code">SelectionLayer</span> is part of the body region layer stack of a grid, but will be referenced
by all other regions layer stacks. You can find further information on the <span class="code">SelectionLayer </span>
<a href="/nattable/documentation.php?page=selection">here</a>.
</div>
</div>
<div class="chapter">
<h5>SortHeaderLayer</h5>
<div class="content">
...
</div>
</div>
<div class="chapter">
<a name="summaryrowlayer"></a><h5>SummaryRowLayer</h5>
<div class="content">
<p>
NatTable supports adding a summary row to the table composition. For this the <span class="code">SummaryRowLayer</span>
needs to be added to the layer stack. Typically it should be set on top of the <span class="code">DataLayer</span> or at
least before other layers are added to the layer stack that are able to transform indexes and positions.
</p>
<div class="codeBlock">...
bodyDataLayer = new DataLayer(dataProvider);
glazedListsEventLayer =
new GlazedListsEventLayer&lt;NumberValues&gt;(bodyDataLayer, valuesToShow);
summaryRowLayer = new SummaryRowLayer(glazedListsEventLayer, configRegistry, false);
summaryRowLayer.addConfiguration(
new CalculatingSummaryRowConfiguration(bodyDataLayer.getDataProvider()));
columnReorderLayer = new ColumnReorderLayer(summaryRowLayer);
columnHideShowLayer = new ColumnHideShowLayer(columnReorderLayer);
selectionLayer = new SelectionLayer(columnHideShowLayer);
viewportLayer = new ViewportLayer(selectionLayer);
...</div>
<p class="subline">Adding the SummaryRowLayer to the body layer stack</p>
<p>
If your NatTable is composed as a grid you should also consider using the
<span class="code">DefaultSummaryRowHeaderDataProvider</span> for your row header layer stack.
This is necessary because the <span class="code">SummaryRowLayer</span> adds a row to the body,
therefore the row header also needs to add an additional row.
</p>
<p>
As you can see in the example above, it is necessary to provide a configuration for the <span class="code">SummaryRowLayer</span>.
There is a default configuration available, but using it without modification will simply show ...
instead of a calculated summary row value. This is because the <span class="code">SummaryRowLayer</span> does not know about the
data model structure and the values that are shown.
</p>
<p>
To configure the <span class="code">SummaryRowLayer</span> contents, you need to create an
<span class="code">ISummaryProvider</span> that knows about the data structure and how to
calculate the summary to show. NatTable comes with the <span class="code">SummationSummaryProvider</span>
that sums the values in a column if they are of type <span class="code">Number</span>.
</p>
<p>
Implementing a custom <span class="code">ISummaryProvider</span> is quite straight forward. You simply
need to implement the <span class="code">summarize(int)</span> method the way that fits your needs.
Usually you need to provide access to the data in some kind of way, either by giving access to the
<span class="code">DataLayer</span> or the <span class="code">IDataProvider</span> to your
<span class="code">ISummaryProvider</span>.
</p>
<div class="codeBlock">public class AverageSummaryProvider implements ISummaryProvider {
private final IDataProvider dataProvider;
public AverageSummaryProvider(IDataProvider dataProvider) {
this.dataProvider = dataProvider;
}
@Override
public Object summarize(int columnIndex) {
double total = 0;
int rowCount = dataProvider.getRowCount();
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) {
Object dataValue =
dataProvider.getDataValue(columnIndex, rowIndex);
total = total + Double.parseDouble(dataValue.toString());
}
return total / rowCount;
}
}</div>
<p class="subline">Implementing a custom ISummaryProvider that calculates the average value in a column</p>
<p>
The <span class="code">ISummaryProvider</span> needs to be registered for the
<span class="code">SummaryRowConfigAttribute.SUMMARY_PROVIDER</span> config attribute. You can
either register the same <span class="code">ISummaryProvider</span> for the whole summary row by
using the <span class="code">SummaryRowLayer.DEFAULT_SUMMARY_ROW_CONFIG_LABEL</span> or register
a special <span class="code">ISummaryProvider</span> per column by using the
<span class="code">SummaryRowLayer.DEFAULT_SUMMARY_COLUMN_CONFIG_LABEL_PREFIX</span> + &lt;column index&gt;
</p>
<h6>Labels</h6>
<p>The <span class="code">SummaryRowLayer</span> automatically adds the following labels to the label stack of the cells in the summary row:</p>
<table>
<tr>
<th>Label</th>
<th>Description</th>
</tr>
<tr>
<td>SummaryRowLayer.DEFAULT_SUMMARY_ROW_CONFIG_LABEL</td>
<td>Added to every cell of the summary row.</td>
</tr>
<tr>
<td>SummaryRowLayer.DEFAULT_SUMMARY_COLUMN_CONFIG_LABEL_PREFIX + &lt;column index&gt;</td>
<td>Added to the summary row cells per column to configure every column cell in the summary row differently.</td>
</tr>
</table>
<h6>Configuration attributes</h6>
<p>The following <span class="code">ConfigAttribute</span>s are interpreted by the <span class="code">SummaryRowLayer</span> and need to be set in order to make it work correctly:</p>
<table>
<tr>
<th>ConfigAttribute</th>
<th>Type</th>
<th>Description</th>
</tr>
<tr>
<td>SummaryRowConfigAttributes.SUMMARY_PROVIDER</td>
<td>ISummaryProvider</td>
<td>Configure the ISummaryProvider that should be used to calculate the sum of a column.</td>
</tr>
</table>
<h6>Bindings</h6>
<p>The <span class="code">SummaryRowLayer</span> does not add bindings to the NatTable.</p>
<p>Have a look at the <span class="code">DefaultSummaryRowConfiguration</span> for an example summary row configuration.</p>
<h6>Commands</h6>
<table>
<tr>
<th>ILayerCommand</th>
<th>Description</th>
</tr>
<tr>
<td>RowResizeCommand</td>
<td>Executing this command for the summary row index allows resizing the summary row programmatically.</td>
</tr>
<tr>
<td>CalculateSummaryRowValuesCommand</td>
<td>Executing this command will trigger the synchronous calculation of all summary row values.
By default the values will be calculated asynchronously when they are requested the first time. This command is used internally to calculate the values before printing or exporting a NatTable to ensure the values are calculated correctly.</td>
</tr>
</table>
<p><b>Note that the <span class="code">CalculateSummaryRowValuesCommand</span> will be introduced with the next NatTable release
and is currently only available in the latest development SNAPSHOTs.</b></p>
<h6>Events</h6>
<table>
<tr>
<th>ILayerEvent</th>
<th>Action</th>
<th>Description</th>
</tr>
<tr>
<td>IVisualChangeEvent</td>
<td>handle</td>
<td>For performance reasons the calculated sum values are cached in the SummaryRowLayer. Receiving an IVisualChangeEvent will clear the cache and trigger recalculating the sum values.</td>
</tr>
<tr>
<td>RowUpdateEvent</td>
<td>fire</td>
<td>As the sum calculation is performed in a separate thread, a RowUpdateEvent is fired when the calculation is done.</td>
</tr>
</table>
</div>
</div>
<div class="chapter">
<a name="viewportlayer"></a><h5>ViewportLayer</h5>
<div class="content">
Places a 'viewport' over the table. Introduces scroll bars over the table and keeps them in sync with the data being displayed.
This is typically placed over the <a href="#selectionlayer">SelectionLayer</a>.
</div>
</div>
<div class="chapter">
<h5>ZoomLayer</h5>
<div class="content">
...
</div>
</div>
<div class="chapter">
<h5>DefaultBodyLayerStack</h5>
<div class="content">
...
</div>
</div>
<div class="chapter">
<h5>ColumnGroupBodyLayerStack</h5>
<div class="content">
...
</div>
</div>
</div>
</div>