NatTable 中带有列组 header 的 RowSelection

RowSelection in NatTable with column group header

我创建了一个 Eclipse 应用程序,我在其中使用单列 header 实现了 NatTable 的行选择。行选择工作正常。后来我在应用程序中添加了一个带有列组 header 的 NatTable。问题来了,单击单元格后,行选择不起作用。仅选中单击的单元格。

我在RowSelectionAction extends AbstractSelectionActionclass中定义行选择。 RowSelectionAction object 是在 class extends DefaultSelectionBindings 的重写 configureBodyMouseClickBindings() 方法中创建的。此方法在 NatTable.configure() 方法期间调用。但似乎 configureBodyMouseClickBindings() 方法未在使用列分组 headers.

创建的 NatTable 中调用

这是使用简单列 header:

创建 NatTable 的代码
private NatTable createTable(Composite parent, List<TableLine> tLines, String[][] propertyNames,
  PropertyToLabels[] propToLabels, TableParams params, TextMatcherEditor<TableLine>editor) {

BodyLayerStack bodyLayerStack =
    new BodyLayerStack(
            tLines,
            new LineDataProviderColumnAccessor(propertyNames[0].length),
            params.getColumnIndicesForRowHeaders());

DataLayer bodyDataLayer = bodyLayerStack.getBodyDataLayer();
Integer[] rowHeights = params.getRowHeights();

if( rowHeights != null && rowHeights.length > 0 ) {
  for( int i = 0; i < rowHeights.length; i++ ) {
    if( rowHeights[i] != null )
      bodyDataLayer.setRowHeightByPosition(i, rowHeights[i]);
  }
}

Integer[] colWidths = params.getColumnWidths();
if( colWidths != null && colWidths.length > 0 ) {
  for( int i = 0; i < colWidths.length; i++ )
    if( colWidths[i] != null )
      bodyDataLayer.setColumnWidthByPosition(i, colWidths[i]);
}

IDataProvider columnHeaderDataProvider =
    new DefaultColumnHeaderDataProvider(propertyNames[0], propToLabels[0].getPropertyToLabels());
DataLayer columnHeaderDataLayer =
    new DefaultColumnHeaderDataLayer(columnHeaderDataProvider);

ILayer columnHeaderLayer =
    new ColumnHeaderLayer(
        columnHeaderDataLayer,
        bodyLayerStack,
        (SelectionLayer)null);

Integer[] hrHeights = params.getHeaderRowHeights();
if( hrHeights != null && hrHeights.length > 0 )
  columnHeaderDataLayer.setRowHeightByPosition(0, hrHeights[0]);

CompositeLayer composite = new CompositeLayer(1, 2);
composite.setChildLayer(GridRegion.COLUMN_HEADER, columnHeaderLayer, 0, 0);
composite.setChildLayer(GridRegion.BODY, bodyLayerStack, 0, 1);

NatTable natTable = new NatTable(parent, composite, false);
natTable.addConfiguration(new DefaultNatTableStyleConfiguration());
natTable.addConfiguration(new ContextMenuConfiguration(natTable));
natTable.addConfiguration(new AbstractRegistryConfiguration() {
  
  @Override
  public void configureRegistry(IConfigRegistry configRegistry) {
    Style cellStyle = new Style();
    cellStyle.setAttributeValue(
            CellStyleAttributes.BACKGROUND_COLOR,
            GUIHelper.COLOR_WIDGET_BACKGROUND);
    configRegistry.registerConfigAttribute(
            CellConfigAttributes.CELL_STYLE, cellStyle,
            DisplayMode.NORMAL, RowHeaderLabel);
  }
});
natTable.configure();

editor.setFilterator(new TextFilterator<TableLine>() {
  @Override
  public void getFilterStrings(List<String> baseList, TableLine element) {
    for( int i = 0; i < element.getLength(); i++ )
      baseList.add("" + element.getObjectByColumn(i));
  }
});
editor.setMode(TextMatcherEditor.REGULAR_EXPRESSION);
bodyLayerStack.getFilterList().setMatcherEditor(editor);

return natTable;}

BodyLayerStack.class内容:

class BodyLayerStack extends AbstractLayerTransform {

private final FilterList<TableLine> filterList;
private final SelectionLayer selectionLayer;
private final DataLayer bodyDataLayer;
private final IRowDataProvider<TableLine> bodyDataProvider;

public DataLayer getBodyDataLayer() {
  return bodyDataLayer;
}

public SelectionLayer getSelectionLayer() {
  return selectionLayer;
}

public IRowDataProvider<TableLine> getBodyDataProvider() {
  return bodyDataProvider;
}

public BodyLayerStack(List<TableLine> values, IColumnAccessor<TableLine> columnAccessor, Integer[] columnIndicesForRowHeaders) {
    EventList<TableLine> eventList = GlazedLists.eventList(values);
    TransformedList<TableLine, TableLine> rowObjectsGlazedList = GlazedLists.threadSafeList(eventList);

    this.filterList = new FilterList<>(rowObjectsGlazedList);

    this.bodyDataProvider = new ListDataProvider<TableLine>(this.filterList, columnAccessor);
    bodyDataLayer = new DataLayer(this.bodyDataProvider);
    
    ColumnOverrideLabelAccumulator bodyLabelAccumulator = new ColumnOverrideLabelAccumulator(bodyDataLayer);
    bodyDataLayer.setConfigLabelAccumulator(bodyLabelAccumulator);

    if( columnIndicesForRowHeaders != null ) {
      for ( int i = 0; i < columnIndicesForRowHeaders.length; i++ ) {
        bodyLabelAccumulator.registerColumnOverrides(
            columnIndicesForRowHeaders[i],
            RowHeaderLabel);
      }
    }

    GlazedListsEventLayer<TableLine> glazedListsEventLayer =
            new GlazedListsEventLayer<>(bodyDataLayer, this.filterList);

    this.selectionLayer = new SelectionLayer(glazedListsEventLayer, false);
    selectionLayer.setSelectionModel(new RowSelectionModel<TableLine>(selectionLayer, this.bodyDataProvider, new IRowIdAccessor<TableLine>()
    {
      @Override
      public Serializable getRowId(TableLine line)
      {
        return line.getId();
      }
    }));

    selectionLayer.addConfiguration(new DefaultSelectionLayerConfiguration()
    {
      @Override
      protected void addSelectionUIBindings()
      {
        addConfiguration(new SelectionBindings());
      }

      @SuppressWarnings("rawtypes")
      @Override
      protected void addMoveSelectionConfig()
      {
        addConfiguration(new RowOnlySelectionConfiguration());
      }
    });

    ViewportLayer viewportLayer = new ViewportLayer(selectionLayer);
    setUnderlyingLayer(viewportLayer);
}

public FilterList<TableLine> getFilterList() {
    return this.filterList;
}

}

这是创建列组的代码 header NatTable:

private NatTable createTableWithColumnHeaderGroups(Composite parent, List<TableLine> tLines, TableParams params,
  TextMatcherEditor<TableLine> editor) {
String[][] columnHeaders = params.getColumnHeaders();
if( columnHeaders == null || columnHeaders.length != 2 )
  return null;
String[] propertyNames = new String[columnHeaders[1].length];
PropertyToLabels propToLabels = new PropertyToLabels();
for( int i = 0; i < propertyNames.length; i++ ) {
  propertyNames[i] = String.valueOf(i+1) + "_" + columnHeaders[1][i];
  propToLabels.add(propertyNames[i], columnHeaders[1][i]);
}

BodyLayerStack bodyLayerStack =
    new BodyLayerStack(
            tLines,
            new LineDataProviderColumnAccessor(propertyNames.length),
            params.getColumnIndicesForRowHeaders());

ColumnGroupModel columnGroupModel = new ColumnGroupModel();

IRowDataProvider<TableLine> bodyDataProvider =
    new ListDataProvider<TableLine>(tLines, new LineDataProviderColumnAccessor(propertyNames.length));
ColumnGroupBodyLayerStack bodyLayer =
    new ColumnGroupBodyLayerStack(bodyLayerStack.getBodyDataLayer(), columnGroupModel);

Integer[] rowHeights = params.getRowHeights();
if( rowHeights != null && rowHeights.length > 0 ) {
  for( int i = 0; i < rowHeights.length; i++ ) {
    if( rowHeights[i] != null )
      bodyLayer.doCommand(new RowResizeCommand(bodyLayer, i, rowHeights[i]));
  }
}
Integer[] colWidths = params.getColumnWidths();
if( colWidths != null && colWidths.length > 0 ) {
  for( int i = 0; i < colWidths.length; i++ )
    if( colWidths[i] != null )
      bodyLayer.doCommand(new ColumnResizeCommand(bodyLayer, i, colWidths[i]));
}

// Column header
DefaultColumnHeaderDataProvider defaultColumnHeaderDataProvider =
    new DefaultColumnHeaderDataProvider(propertyNames, propToLabels.getPropertyToLabels());
DefaultColumnHeaderDataLayer columnHeaderDataLayer =
    new DefaultColumnHeaderDataLayer(defaultColumnHeaderDataProvider);
ColumnHeaderLayer columnHeaderLayer =
    new ColumnHeaderLayer(columnHeaderDataLayer, bodyLayer, bodyLayer.getSelectionLayer());
ColumnGroupHeaderLayer columnGroupHeaderLayer =
    new ColumnGroupHeaderLayer(
        columnHeaderLayer,
        bodyLayer.getSelectionLayer(),
        columnGroupModel);

Integer[] hrHeights = params.getHeaderRowHeights();
if( hrHeights != null && hrHeights.length > 0 )
  for( int i = 0; i < hrHeights.length; i++ )
    if( hrHeights[i] != null )
      columnGroupHeaderLayer.doCommand(new RowResizeCommand(columnGroupHeaderLayer, i, hrHeights[i]));

List<ColumnHeaderGroup> groups = params.getColumnHeaderGroups();
for( ColumnHeaderGroup group : groups ) {
  List<Integer> indices = group.getIndices();
  int[] indicesArray = new int[indices.size()];
  for( int i = 0; i < indices.size(); i++ )
    indicesArray[i] = indices.get(i);
  columnGroupHeaderLayer.addColumnsIndexesToGroup(group.getName(), indicesArray);
}

// Row header
final DefaultRowHeaderDataProvider rowHeaderDataProvider =
    new DefaultRowHeaderDataProvider(bodyDataProvider);
DefaultRowHeaderDataLayer rowHeaderDataLayer =
    new DefaultRowHeaderDataLayer(rowHeaderDataProvider);
ILayer rowHeaderLayer =
    new RowHeaderLayer(rowHeaderDataLayer, bodyLayer, bodyLayer.getSelectionLayer());

// Corner
final DefaultCornerDataProvider cornerDataProvider =
    new DefaultCornerDataProvider(defaultColumnHeaderDataProvider, rowHeaderDataProvider);
DataLayer cornerDataLayer =
    new DataLayer(cornerDataProvider);
ILayer cornerLayer =
    new CornerLayer(cornerDataLayer, rowHeaderLayer, columnGroupHeaderLayer);

// Grid
GridLayer gridLayer =
    new GridLayer(bodyLayer, columnGroupHeaderLayer, rowHeaderLayer, cornerLayer);

NatTable natTable = new NatTable(parent, gridLayer, false);

editor.setFilterator(new TextFilterator<TableLine>() {

  @Override
  public void getFilterStrings(List<String> baseList, TableLine element) {
    for( int i = 0; i < element.getLength(); i++ )
      baseList.add("" + element.getObjectByColumn(i));
  }
});
editor.setMode(TextMatcherEditor.REGULAR_EXPRESSION);
bodyLayerStack.getFilterList().setMatcherEditor(editor);

natTable.addConfiguration(new DefaultNatTableStyleConfiguration());
natTable.addConfiguration(new ContextMenuConfiguration(natTable));
natTable.addConfiguration(new AbstractRegistryConfiguration() {
  
  @Override
  public void configureRegistry(IConfigRegistry configRegistry) {
    Style cellStyle = new Style();
    cellStyle.setAttributeValue(
            CellStyleAttributes.BACKGROUND_COLOR,
            GUIHelper.COLOR_WIDGET_BACKGROUND);
    configRegistry.registerConfigAttribute(
            CellConfigAttributes.CELL_STYLE, cellStyle,
            DisplayMode.NORMAL, RowHeaderLabel);
  }
});
natTable.configure();
return natTable;  }

最终,问题可能出在 nat table 层的实现中,nat table 具有 two-row 列 header 的创建。

问题出在您的代码中。在带有 ColumnGroupHeader 的版本中,您创建了两个主体层堆栈。首先是您还显示的 BodyLayerStack 。但是那个不与列组示例一起使用。在那里,您使用名为 ColumnGroupBodyLayerStack 的第二个。由于未显示,我无法判断 class 是否缺少行选择配置。但可能是这样,因为在 NatTable 层实现中没有关于该功能的问题。

顺便说一句,我建议使用 NatTable 1.6 引入的性能列分组,而不是旧的基于 ColumnGroupModel 的实现。