NatTable – dynamic scaling enhancements

The last weeks I worked on harmonizing the scaling capabilities of NatTable. The first goal was to provide scaled versions of all internal NatTable images. This caused an update of several NatTable images like the checkbox, that you will notice in the next major release. To test the changes I implemented a basic dynamic scaling, which by accident and some additional modification became the new zoom feature in NatTable. I will give a short introduction to the new feature here, so early adaptors have a chance to test it in different scenarios before the next major release is published.

To enable the UI bindings for dynamic scaling / zooming the newly introduced ScalingUiBindingConfiguration needs to be added to the NatTable.

natTable.addConfiguration(
    new ScalingUiBindingConfiguration(natTable));

This will add a MouseWheelListener and some key bindings to zoom in/out:

  • CTRL + mousewheel up = zoom in
  • CTRL + mousewheel down = zoom out
  • CTRL + ‘+’ = zoom in
  • CTRL + ‘-‘ = zoom out
  • CTRL + ‘0’ = reset zoom

The dynamic scaling can be triggered programmatically by executing the ConfigureScalingCommand on the NatTable instance. This command already exists for quite a while, but it was mainly used internally to align the NatTable scaling with the display scaling. I have introduced new default IDpiConverter to make it easier to trigger dynamic scaling:

  • DefaultHorizontalDpiConverter
    Provides the horizontal dots per inch of the default display.
  • DefaultVerticalDpiConverter
    Provides the vertical dots per inch of the default display.
  • FixedScalingDpiConverter
    Can be created with a DPI value to set a custom scaling.

At initialization time, NatTable internally fires a ConfigureScalingCommand with the default IDpiConverter to align the scaling with the display settings.

As long as only text is included in the table, registering the ScalingUiBindingConfigurationis all you have to do. Once ICellPainter are used that render images, some additional work has to be done. The reason for this is that for performance and memory reasons the images are referenced in the painter and not requested for every rendering operation. As painters are not part of the event handling, they can not be simply updated. Also for several reasons there are mechanisms that avoid applying the registered configurations multiple times.

There are three ways to style a NatTable, and as of now this requires three different ways to handle dynamic scaling updates for image painters.

  1. AbstractRegistryConfiguration
    This is the default way that exists for a long time. Most of the default configurations provide the styling configuration this way. As there is no way to identify which configuration registers ICellPainter and how the instances are created, the ScalingUiBindingConfiguration needs to be initialized with an updater that knows which steps to perform.

    natTable.addConfiguration(
      new ScalingUiBindingConfiguration(natTable, configRegistry -> {
    
        // we need to re-create the CheckBoxPainter
        // to reflect the scaling factor on the checkboxes
        configRegistry.registerConfigAttribute(
            CellConfigAttributes.CELL_PAINTER,
            new CheckBoxPainter(),
            DisplayMode.NORMAL,
            "MARRIED");
    
      }));
  2. Theme styling
    In a ThemeConfiguration the styling options for a NatTable are collected in one place. In the previous state the ICellPainter instance creation was done on the member initialization which was quite static. Therefore the ICellPainter instance creation was moved to a new method named createPainterInstances(), so the painter update on scaling can be performed without any additional effort. For custom painter configurations this means that they should be added to a theme via IThemeExtension.

    natTable.addConfiguration(
        new ScalingUiBindingConfiguration(natTable));
    
    // additional configurations
    
    natTable.configure();
    
    ...
    
    IThemeExtension customThemeExtension = new IThemeExtension() {
    
        @Override
        public void registerStyles(IConfigRegistry configRegistry) {
            configRegistry.registerConfigAttribute(
                CellConfigAttributes.CELL_PAINTER,
                new CheckBoxPainter(),
                DisplayMode.NORMAL,
                "MARRIED");
        }
    
        @Override
        public void unregisterStyles(IConfigRegistry configRegistry) {
            configRegistry.unregisterConfigAttribute(
                CellConfigAttributes.CELL_PAINTER,
                DisplayMode.NORMAL,
                "MARRIED");
        }
    };
    
    ThemeConfiguration modernTheme = 
        new ModernNatTableThemeConfiguration();
    modernTheme.addThemeExtension(customThemeExtension);
    
    natTable.setTheme(modernTheme);
  3. CSS styling
    The CSS styling support in NatTable already manages the painter instance creation. The only thing to do here is to register a command handler that triggers the CSS apply operation actively. Otherwise the images will scale only on interactions with the UI.

    natTable.registerCommandHandler(
        new CSSConfigureScalingCommandHandler(natTable));

I have tested several scenarios, and the current state of development looks quite good. But of course I am not sure if I tested everything and found every possible edge case. Therefore it would be nice to get some feedback from early adopters if the new zoom feature is stable or not. The p2 update site with the current development snapshot can be found on the NatTable SNAPSHOTS page. From build number 900 on the feature is included. Any issues found can be reported on the corresponding Bugzilla ticket 560802.

Please also note that with the newly introduced zooming capability I have dropped the ZoomLayer. It did only increase the cell dimensions but not the font or the images. Therefore it was not functional (maybe never finished) IMHO and to avoid confusions in the future I have deleted it now.

About Dirk Fauth

Dirk Fauth is a Software Architect for Rich Client Systems working for the Robert Bosch GmbH in Stuttgart and a lecturer in Java basics for the Baden-Wuerttemberg Cooperative State University (DHBW). He is active in developing, teaching and talking about OSGi, Eclipse RCP applications and Eclipse related technologies. He is project lead of the Nebula NatTable project, Eclipse Platform committer and also a committer and contributor to several other Eclipse projects. (Twitter: @fipro78)
This entry was posted in Dirk Fauth, Eclipse, Java and tagged , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *