Search code examples
eclipse-rcpnattable

PopupMenuBuilder.withColumnRenameDialog doesn't change header model data


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?


Solution

  • 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;
      }