I have a NatTable (table
) with a custom header menu configuration, set up like this:
table.addConfiguration(new CustomHeaderMenuConfiguration(table, columnHeaderLayer));
The configuration class builds the menu like this:
@Override
protected PopupMenuBuilder createColumnHeaderMenu(NatTable natTable) {
return super.createColumnHeaderMenu(natTable).withHideColumnMenuItem("Hide column(s)")
.withColumnRenameDialog("Change annotation name").withVisibleState(
PopupMenuBuilder.COLUMN_RENAME_MENU_ITEM_ID, new ValidRenamableHeaderState());
}
The visible state triggers as expected. In the configuration, I also configure the layer to register the command with my specific column header layer:
@Override
public void configureLayer(ILayer layer) {
layer.registerCommandHandler(
new DisplayColumnRenameDialogCommandHandler(this.columnHeaderLayer));
}
Now from crawling through the API of DisplayColumnRenameDialogCommandHandler
, etc., I would expect that at some point, the new value would reach the column header data provider via the column header layer.
The column header layer itself is set up like this in the editor class:
final IDataProvider columnHeaderDataProvider = new ColumnHeaderDataProvider(bodyDataProvider);
final ColumnHeaderLayer columnHeaderLayer =
new ColumnHeaderLayer(new DefaultColumnHeaderDataLayer(columnHeaderDataProvider),
compositeFreezeLayer, selectionLayer);
ColumnHeaderDataProvider
implements IDataProvider
, and getDataValue(int, int)
works just fine.
The issue I struggle with is that ColumnHeaderDataProvider.setData(int, int, newValue)
is never called, and hence the model data is never updated, although the label on the column header changes.
What am I missing?
The generic ColumnHeaderLayer
is not bound to the actual column header data, but to an internal Map provided by a helper class. This is (probably) because in usual use cases, columns aren't tied to the body data provider (as in my case), but rather to just a bunch of strings.
To actually change data in the column header data provider, you have to override ColumnHeaderLayer
's renameColumnPosition(int, String)
to address the actual data provider's setData(int, int, Object)
, rather than the internal map.
Here is an example:
@Override
public boolean renameColumnPosition(int columnPosition, String customColumnName) {
IDataProvider dataProvider =
((DefaultColumnHeaderDataLayer) this.getBaseLayer()).getDataProvider();
Object oldData = dataProvider.getDataValue(columnPosition, 0);
boolean renamed = (!oldData.equals(customColumnName));
if (renamed) {
dataProvider.setDataValue(columnPosition, 0, customColumnName);
fireLayerEvent(new RenameColumnHeaderEvent(this, columnPosition));
}
return renamed;
}