NatTable 2.5.0 - New & Noteworthy
The NatTable 2.5.0 release was made possible by several companies that provided and sponsored ideas, bug reports, discussions and new features you can find in the following sections. We would like to thank everyone involved for their commitment and support on developing the 2.5.0 release.
Of course we would also like to thank our contributors for adding new functions and fixing issues.
Almost every change in code is tracked via GitHub Issues, so if you are curious about the details and all the bugs that are fixed and enhancements that were added with the 2.5.0 release, have a look there.
API changes
The following modifications to the API were made. Several new classes and interfaces were introduced to support new features. The details can be found in the Enhancements and new features section.
Below is the list of new classes and interfaces
- DefaultGlazedListsFilterStrategy#ColumnSetMatcherEditor
- FillHandleActionHelper
- FillHandleBoundsProvider
- FillHandleColumnAction
- FillHandleCompositeFreezeLayerPainter
- FillHandleLayerPainterHelper
- FormulaFillHandleActionHelper
- FormulaFillHandleColumnAction
- GlazedListsLockHelper
- GroupByModelListener
- IDragModeWithKeySupport
- XSSFExcelExporter
Below is the list of new constructors
- DefaultFormulaConfiguration(FormulaDataProvider, SelectionLayer, InternalCellClipboard, FillHandleBoundsProvider)
- FillHandleConfiguration(SelectionLayer, FillHandleBoundsProvider)
- FillHandleEventMatcher(FillHandleBoundsProvider)
Below is the list of new constants
- FillHandleConfigAttributes#FILL_HANDLE_SIZE
Below is the list of new fields
- FillHandleEventMatcher#fillHandleBoundsProvider
Below is the list of new methods
- CompositeLayer#processLayerPainterInformation(ILayerPainter)
- DefaultGlazedListsFilterStrategy#getSetMatcherEditor(Integer, Set<String>, IDisplayConverter)
- FillHandleLayerPainter#getHandleSize(IConfigRegistry)
- GraphicsUtils#getInternalBounds(Rectangle, BorderStyle)
- NatCombo#getItemIndex(String)
- GroupByModel#addGroupByModelListener(GroupByModelListener)
- GroupByModel#fireGroupByModelChange()
- GroupByModel#removeGroupByModelListener(GroupByModelListener)
Below is the list of deprecated constructors
- FillHandleEventMatcher(FillHandleLayerPainter)
Enhancements and new features
- 
Fill handle improvements There are several improvements for the fill handle: - 
Make it work correctly in combination with the freeze functionality 
 To support the combination of the fill handle and the freeze functionality, the following changes were introduced:- Added a new interface FillHandleBoundsProvider
- Added a new helper class FillHandleLayerPainterHelperto retrieve fill handle configurations
- Extended CompositeLayer#CompositeLayerPainterand added the methodprocessLayerPainterInformation(ILayerPainterpainter)which is called after each sub layer painter
- Added a new class FillHandleCompositeFreezeLayerPainterthat makes use of the newprocessLayerPainterInformation()method to store the fill handle bounds from all 4 freeze regions once, and to paint the fill handle over the freeze border
- Added new constructors inDefaultFormulaConfigurationandFillHandleConfigurationthat additionally takes aFillHandleBoundsProviderthat should be used with the matcher
 To make the combination of freeze and fill handle work correctly, the FillHandleCompositeFreezeLayerPainterneeds to be used and configured:this.compositeFreezeLayerPainter = new FillHandleCompositeFreezeLayerPainter(this.compositeFreezeLayer); this.compositeFreezeLayer.setLayerPainter(this.compositeFreezeLayerPainter); ... natTable.addConfiguration( new FillHandleConfiguration( bodyLayer.getSelectionLayer(), bodyLayer.getCompositeFreezeLayerPainter())); natTable.addConfiguration( new DefaultFormulaConfiguration( bodyLayer.getFormulaDataProvider(), bodyLayer.getSelectionLayer(), natTable.getInternalCellClipboard(), bodyLayer.getCompositeFreezeLayerPainter()));
- Added a new interface 
- 
Add option to configure the fill handle size 
 Added the newConfigAttribute<Point> FillHandleConfigAttributes#FILL_HANDLE_SIZEto be able to configure the size of the fill handle.
- 
Added an option to configure a double click action 
 In Excel a double click on the fill handle triggers an automatic fill process for the whole column. To support this also in NatTable, the following changes were introduced:- Added a new helper classes FillHandleActionHelperandFormulaFillHandleActionHelperfor the fill handle menu
- Added a new classes FillHandleColumnActionandFormulaFillHandleColumnActionthat can be registered on double clicks on the fill handle to trigger an automatic fill operation.
- Updated the FillHandleDragModeto use theFillHandleActionHelper
- Updated the FormulaFillHandleDragModeto use theFormulaFillHandleActionHelper
- Updated the FillHandleConfigurationto register theFillHandleColumnActionon double click by default
- Updated the DefaultFormulaConfigurationto register theFormulaFillHandleColumnActionon double click by default
 
- Added a new helper classes 
 
- 
- 
Key interactions in drag mode When an IDragModeis active, it was not possible to interact via key press. The following modifications where introduced to solve this:- The DragModeEventHandlernow implementskeyPressed(KeyEvent)andkeyReleased(KeyEvent)
- Pressing ESC will now in general cancel an active IDragMode
- The IDragModeWithKeySupportinterface is introduced. Using this interface it is possible to create a custom drag mode that is able to react on key interactions.
 The _5084_StructuralRowReorderWithoutRowHeaderExample contains an IDragModeWithKeySupportthat lets you switch from reorder to copy while dragging in item if you press the CTRL modifier key.
- The 
- 
Add support for exporting to XLSX The NatTable Apache POI Extension now supports exporting to XSSF, which is the POI Project’s pure Java implementation of the Excel 2007 OOXML (.xlsx) file format. The following Plug-ins were added to the org.eclipse.nebula.widgets.nattable.extension.poi.feature to add this: - org.apache.poi.ooxml
- org.apache.poi.ooxml.schemas
- org.apache.commons.commons-compress
- org.apache.xmlbeans
 To export to the Excel 2007 OOXML format, you simply need to use the new XSSFExcelExporter:PoiExcelExporter exporter = new XSSFExcelExporter(); exporter.setApplyVerticalTextConfiguration(true); exporter.setApplyBackgroundColor(false); natTable.doCommand( new ExportCommand( natTable.getConfigRegistry(), natTable.getShell(), false, false, exporter));
There is a new example _819_FormulaDataWithFreezeExample that shows the combination of formula support, fill handle, freeze, the export to XLSX and showing the JFace ProgressDialog on export.
- Performance updates for Excel-like filter row
Several improvements for the Excel-like filter row where introduced to improve the performance when opening a filter combobox.
Doing this also uncovered a possible deadlock situation when updating the content of the underlying GlazedLists datamodel.
To solve this, the Lock#lock() calls in NatTable code are replaced with Lock#tryLock() in a loop.
To make it easier for NatTable users to adopt the same approach, the GlazedListsLockHelper was introduced.
If you have code in your project that looks like this:
bodyLayerStack.getSortedList().getReadWriteLock().writeLock().lock();
try {
    // deactivate
    bodyLayerStack.getGlazedListsEventLayer().deactivate();
    // clear
    bodyLayerStack.getSortedList().clear();
    // addall
    bodyLayerStack.getSortedList().addAll(PersonService.getExtendedPersonsWithAddress(1000));
} finally {
    bodyLayerStack.getSortedList().getReadWriteLock().writeLock().unlock();
    // activate
    bodyLayerStack.getGlazedListsEventLayer().activate();
}
You can replace it by using the GlazedListsLockHelper like this:
GlazedListsLockHelper.performWriteOperation(
    bodyLayerStack.getSortedList().getReadWriteLock(),
    () -> {
        // deactivate
        bodyLayerStack.getGlazedListsEventLayer().deactivate();
        // clear
        bodyLayerStack.getSortedList().clear();
        // addall
        bodyLayerStack.getSortedList().addAll(PersonService.getExtendedPersonsWithAddress(1000));
    },
    () -> {
        // activate
        bodyLayerStack.getGlazedListsEventLayer().activate();
    });