javanattable

How to sort various data types in one column in NatTables


I do have all values in Nattable as strings. I used IConfigLabelAccumulator and added labels DataTypeStringLabel = "String" and DataTypeNumberLabel = "Number" to cells. In one column can be values with both types of labels:

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

    // this.filterList = new FilterList<>(rowObjectsGlazedList); //changed to:
    // use the SortedList constructor with 'null' for the Comparator
    // because the Comparator will be set by configuration
    sortedList = new SortedList<>(rowObjectsGlazedList, null);
    // wrap the SortedList with the FilterList
    filterList = new FilterList<>(sortedList);
    
    bodyDataProvider = new ListDataProvider<TableLine>(filterList, getColumnAccessor(columnCount));
    bodyDataLayer = new DataLayer(bodyDataProvider);

    IConfigLabelAccumulator cellLabelAccumulator = new IConfigLabelAccumulator() {
      
      @Override
      public void accumulateConfigLabels(LabelStack configLabels, int columnPosition, int rowPosition) {
        int columnIndex = bodyDataLayer.getColumnIndexByPosition(columnPosition);
        int rowIndex = bodyDataLayer.getRowIndexByPosition(rowPosition);
        if( isRowHeader(columnIndicesForRowHeaders, columnIndex) ) {
          configLabels.addLabel(NatTableFactory.RowHeaderLabel);
        } else {
          // get dataTypes at actual positions and add/refresh labels 
          configLabels.addLabel(filterList.get(rowIndex).getObjectTypeByColumn(columnIndex));
          if(configLabels.getLabels().get(0) != null && configLabels.getLabels().get(0)=="Number") {
            System.out.println("Number");                
          }
        }
      }
    };
    bodyDataLayer.setConfigLabelAccumulator(cellLabelAccumulator);
    
    GlazedListsEventLayer<TableLine> glazedListsEventLayer = new GlazedListsEventLayer<>(bodyDataLayer, filterList);
    
    selectionLayer = new SelectionLayer(glazedListsEventLayer, false);
    selectionLayer.setSelectionModel(getSelectionModel());
    selectionLayer.addConfiguration(getSelectionConfiguration());
    
    setUnderlyingLayer(new ViewportLayer(selectionLayer));
  }

For now, all values are sorted as strings (as expected). But I need to sort values with label Number as numbers.

What would be better: convert data to numbers, or use custom comparator?

I was trying:

  public static IConfiguration getCustomComparatorConfiguration(final AbstractLayer columnHeaderDataLayer) {
    return new AbstractRegistryConfiguration() {

      @Override
      public void configureRegistry(IConfigRegistry configRegistry) {
        
        // Register labels
        BodyLayerStack.super.getConfigLabelAccumulator().registerOverride( //ERROR
            4, //here should come index of sorted column?
                NatTableFactory.DataTypeNumberLabel);

        // Register custom comparator
        configRegistry.registerConfigAttribute(
                SortConfigAttributes.SORT_COMPARATOR,
                NatTableLayerConfigurations.getCustomComparator(),
                DisplayMode.NORMAL,
                NatTableFactory.DataTypeNumberLabel);
      }
    };
  }

but I get The method registerOverride(int, String) is undefined for the type IConfigLabelAccumulator.


Solution

  • You get an IConfigLabelAccumulator which does not provide the registerOverride(int, String) method. Not sure which subclass defines that method. The ColumnOverrideLabelAccumulator provides the method registerColumnOverride(int, String)

    I would suggest to use a custom Comparator if the sorting based on String representations is not sufficient.

    https://www.eclipse.org/nattable/documentation.php?page=sorting