• Listening for sorting events
  • Create additional user filters
  • Using dates on the filters
  • Avoiding sudden row vanishing while editing
 
  • Listening for sorting events

    Listening for sorting events require adding a listener to the table itself. For example, it is possible to add a tooltip that shows the current number of rows -or how many have been filtered out-:

    header.getTable().getRowSorter().addRowSorterListener(new RowSorterListener() {
                @Override
                public void sorterChanged(RowSorterEvent e) {
                    System.out.println(e.getPreviousRowCount());
                }
             });
  •  
  • Create additional user filters

    It is easy to define additional filters outside the header filter, using the UserFilter class

    For example (as taken from test file AppUserFilter.java):

        
    final UserFilter userFilter = new UserFilter(filterHeader){
    	@Override
    	public boolean include(Entry entry) {
    		return -1!=entry.getStringValue(nameColumn).indexOf('e');
    	}
    };
    JCheckBox check = new JCheckBox("Filter out any row where the "+
                                    "name does not contain a lower case 'e'");		
    check.addItemListener(new ItemListener() {			
    	@Override
    	public void itemStateChanged(ItemEvent e) {				
    		userFilter.setEnabled(e.getStateChange()==ItemEvent.SELECTED);
    	}
    });
        
  •  
  • Using dates on the filters

    Note: starting on version 2.0, dates are automatically handled in the library.

    By default, the TableFilterHeader has no built-in functionality to support directly dates: this should eventually change, to simplify the usual cases (where the date format can be implied). On the meantime, it is still possible to match specific dates, but the relational operators will most likely fail; for example, if dates are expressed as dd-mm-yyyy, it will evaluate as true that 06-01-2008 > 02-12-2009, as it converts the dates into strings.

    The easiest way to solve this is to instruct the text parser to understand the format used on the dates; this solution requires that the table model associates a Date.class to the specific column. That is, if the table model automatically converts dates into strings, a second solution, displayed later, is needed. This second solution is also needed if the table uses more than one date format.

    The simples solution requires four steps:

    1. Define a ITypeBuilder to handle dates. For example:
      ITypeBuilder dateTypeBuilder = new ITypeBuilder() {
         public Object parse(String text) throws FilterTextParsingException {
            SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy");
            try {
               return df.parse(text);
            } catch (ParseException ex) {
               throw new FilterTextParsingException("Invalid date", pex2.getErrorOffset());
            }
         }
      }; 
    2. Create a specific TextParser instance:
      FilterTextParser textParser = TableFilterHelper.createTextFilterParser(TableModel);
    3. On this parser, associate the created builder to the Date.class:
      textParser.setFactory(Date.class, dateTypeBuilder);
    4. Finally, associate the filter header to the text parser:
      filterHeader.setTextParser(textParser);

    This solution assumes that the table model only supports one date format. If this is not the case, it is needed to specify a different text parser for each column. It also assumes that the table model returns the elements on the given column as dates. If the model preformats these dates and just returns strings, the new text parser must define a comparator for strings, using this constructor. In any case, a more complicated solution!

  •  
  • Avoiding sudden row vanishing while editing

    When a user edits a given table's row, it could happen that the row does not match anymore the filters that the user specified. Being this the case, the row should dissapear from the current view, but this can be, at the very least, quite confusing for the user: modifying a column makes the row vanish!

    The solution -if needed-, is quite straightforward: modify the applying filter so that the updated rows are not filtered out.

    headerFilter.setTableFilter(
               new TableFilter() {
                   @Override
                   public boolean include(Entry rowEntry) {
                       return isModelRowChanged((Integer) rowEntry.getIdentifier())
                           || super.include(rowEntry);
                   }
    }); 

    It is needed here to program the isModelRowChanged method, returning true when the associated (model) row is changed.