| <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 <- column positions |
| 1 0 3 4 5 <- column indexes |
| <br/> |
| ColumnReorderLayer B |
| 0 1 2 3 4 5 <- column positions |
| 2 1 0 3 4 5 <- column indexes |
| <br/> |
| DataLayer A |
| 0 1 2 3 4 5 <- column positions |
| 0 1 2 3 4 5 <- 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<NumberValues>(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> + <column index> |
| </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 + <column index></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> |