-
Notifications
You must be signed in to change notification settings - Fork 12
Persistence
NatTable supports persisting and restoring its state. For this, the IPersistable interface was introduced. Every class that implements this interface needs to provide methods for saving and loading its states. These methods are:
void saveState(String, Properties)
void loadState(String, Properties)By looking at the method parameters you will realize that the persistence mechanism is realized using java.util.Properties. So every state needs to be persisted as a key-value-pair.
All the layers that support to save their states, implement the IPersistable interface by default. Additionally, you can register your own persistable with any layer using the registerPersistable() on the ILayer interface. These persistables will then also be handled on saving and loading NatTable states.

Settings that can be persisted using the persistence mechanism in NatTable include, but are not limited to the following:
- Visible state of columns (
ColumnHideShowLayer) - Column order (
ColumnReorderLayer) - Column/Row size (
DataLayer) - Sorting state (
SortHeaderLayer) - Freeze state (
CompositeFreezeLayer) - Column group state (
GroupModel) - Filter row state (
FilterRowDataProvider) - GroupBy state (
GroupByModel) - Styles that are applied using the
DisplayColumnStyleEditor
The persistence mechanism will only gather the states in memory. This means, if you like to persist these settings in the file system or a database, you need to implement that yourself. A typical code block for saving your state to a file would look like this:
Properties myState = new Properties();
natTable.saveState("", myState);
try (FileOutputStream tableStateStream = new FileOutputStream("myState.properties")) {
myState.store(tableStateStream, null);
} catch (IOException e) {
e.printStackTrace();
}If you like to support multiple state sets that can be changed at runtime, you have two options. You can either create a new Properties object for every state you want to persist, or you make use of the prefix mechanism. The first approach supports a clean separation of state sets, leaving you to deal with the state management yourself. The second approach will manage all state sets within one Properties object. This is implemented using the state prefix. The state prefix will be prepended to every key that is stored by calling saveState(String, Properties) or loaded via loadState(String, Properties).
If you like to add your own states by implementing the IPersistable interface, you have to ensure that your keys start with a dot, otherwise there may be some issues in further processing.
Since Nebula NatTable 1.0.0 there is a convenience dialog for managing multiple state sets. In this context, state sets are called view configurations, which is a more user friendly notation, rather than the more technical state set. This dialog mainly supports creating and loading view configurations and can be added to a NatTable by adding the appropriate menu item and command handler to a menu. The following code will add the menu item to the column header menu and the command handler for opening the dialog to the grid layer of the NatTable instance.
//add the necessary action to the column header menu of the default HeaderMenuConfiguration
natTable.addConfiguration(
new HeaderMenuConfiguration(natTable) {
@Override
protected PopupMenuBuilder createColumnHeader-Menu(NatTable natTable) {
return super.createColumnHeaderMenu(natTable)
.withStateManagerMenuItemProvider();
}
});
//register the necessary command handler to the grid layer of the NatTable instance
DisplayPersistenceDialogCommandHandler handler =
new DisplayPersistenceDialogCommandHandler();
gridLayer.registerCommandHandler(handler);After selecting the menu item out of the column header menu, a dialog will show up, giving the user the opportunity to save the current active state set as a new view configuration with a custom name. This view configuration can be reloaded afterwards or even deleted, to give a user the flexibility to change the view of a table on simple clicks. The list of view configuration will also indicate the current active view configuration with a leading *. This is especially useful for large tables where you want to check only sub-sets at once.

The dialog doesn`t support choosing an empty name for a view configuration. This is related to the prefixing and a supported convenience functionality. If you create your command handler with the NatTable instance it should be attached to, the initial view configuration without any user modifications will be stored as default configuration. This configuration is not editable by the user.
Note:
If you like to make use of storing the default configuration in the view configuration management, you need to register the DisplayPersistenceDialogCommand with the current NatTable instance after calling configure() on the NatTable instance. This is because otherwise some state information might be missing and it could cause some unexpected behavior then.
If you like to open the dialog in another way than by a menu, you can also call the DisplayPersistenceDialogCommand on the NatTable directly. This enables you for example to add a command to the toolbar of your application that opens the dialog, rather than a popup menu on the table itself. Note that you still need to register the DisplayPersistenceDialogCommandHandler to be able to use the PersistenceDialog.
Button viewConfigButton = new Button(buttonPanel, SWT.PUSH);
viewConfigButton.setText("View Configuration");
viewConfigButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
natTable.doCommand(new DisplayPersistenceDialogCommand(natTable));
}
});It is also possible to listen for changes on view configurations within the PersistenceDialog, like adding, removing or changing a view configuration. To do this you need to register listeners of the IStateChangeListener type to the DisplayPersistenceDialogCommandHandler. On opening a new dialog, the listeners will be registered to the dialog, so you can be informed about view configuration changes outside the dialog.
DisplayPersistenceDialogCommandHandler handler =
new DisplayPersistenceDialogCommandHandler(natTable);
handler.addStateChangeListener(new IStateChangedListener() {
@Override
public void handleStateChange(StateChangeEvent event) {
//do something on state change
}
});If you need to implement some custom components for view configurations of the NatTable, like for example a widget with a combobox giving the opportunity to switch the view configurations without the dialog, you can make use of the PersistenceHelper, which at least helps on retrieving the view configuration names and deleting a view configuration out of a Properties instance.
There are several examples that include the persistence feature. Below are only some examples listed as a reference:
- Tutorial Examples - Integration - SortableGroupByWithFilterExample
- Tutorial Examples - Integration - EditableSortableGroupByWithFilterExample
- Tutorial Examples - Integration - SortableGroupByFilterPerformanceColumnGroupAndFreezeExample
You can also have a look at the PersistentNatExampleWrapper to see how saving and loading states via file persistence can be implemented.