I created an Eclipse application where I implemented the row selection for the NatTable with a single column header. The row selection works correctly. Later I added a NatTable with a column group header to the application. Here comes problem, after clicking on cell the row selection doesn’t work. Only clicked cell is selected.
I define the row selection in RowSelectionAction extends AbstractSelectionAction
class. RowSelectionAction
object is created in overrided configureBodyMouseClickBindings()
method of class extends DefaultSelectionBindings
. This method is called during NatTable.configure()
method. But it seems configureBodyMouseClickBindings()
method isn’t called at NatTable created with column groupd headers.
Here is code for creating NatTable with simple column header:
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 content:
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; }
}
Here is code for creating column group 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; }
Eventually, the problem may be in nat table layer implementation at nat table with two-row column headers creation.
Advertisement
Answer
The issue is in your code. In the version with the ColumnGroupHeader
you create two body layer stacks. First the BodyLayerStack
that you also show. But that one is not used with the column group example. There you use the second one named ColumnGroupBodyLayerStack
. As that one is not shown I can’t tell if that class is missing the row selection configuration. But probably it is, as there is no issue in the NatTable layer implementation with regards to that feature.
BTW, I would suggest to use the performance column grouping introduced with NatTable 1.6 instead of the old ColumnGroupModel
based implementation.