Skip to content

05_Styling

Dirk Fauth edited this page Sep 11, 2024 · 1 revision

Styling

Every layer that has effect on visualization has it's own style configuration. For example, the SelectionLayer has it's own style configuration telling how to render selected cells, the ColumnHeaderLayer has it's own style configuration telling how to render the column header cells, while the NatTable itself knows the style configuration on how to render all other cells (mainly the cells in the body region of a grid). To customize the visualization of the NatTable you have to override and register your own style configuration on the specific layer itself.

Style

The styling is configured by creating and registering Style objects. There are several ConfigAttributes that can be set to define a Style:

  • BACKGROUND_COLOR
  • FOREGROUND_COLOR
  • HORIZONTAL_ALIGNMENT
  • VERTICAL_ALIGNMENT
  • FONT
  • BORDER_STYLE
  • IMAGE (only used by the ImagePainter)
  • GRADIENT_BACKGROUND_COLOR (only used by the GradientBackgroundPainter)
  • GRADIENT_FOREGROUND_COLOR (only used by the GradientBackgroundPainter)
  • PASSWORD_ECHO_CHAR (only used by the PasswordTextPainter and PasswordCellEditor)

Theses ConfigAttributes are defined in the CellStyleAttributes interface and can be used like this (snippet from DefaultNatTableStyleConfiguration):

Style cellStyle = new Style(); 
cellStyle.setAttributeValue(CellStyleAttributes.BACKGROUND_COLOR, bgColor); 
cellStyle.setAttributeValue(CellStyleAttributes.FOREGROUND_COLOR, fgColor); 
cellStyle.setAttributeValue(CellStyleAttributes.GRADIENT_BACKGROUND_COLOR, gradientBgColor); 
cellStyle.setAttributeValue(CellStyleAttributes.GRADIENT_FOREGROUND_COLOR, gradientFgColor); 
cellStyle.setAttributeValue(CellStyleAttributes.FONT, font); 
cellStyle.setAttributeValue(CellStyleAttributes.HORIZONTAL_ALIGNMENT, hAlign); 
cellStyle.setAttributeValue(CellStyleAttributes.VERTICAL_ALIGNMENT, vAlign); 
cellStyle.setAttributeValue(CellStyleAttributes.BORDER_STYLE, borderStyle); 
configRegistry.registerConfigAttribute(CellConfigAttributes.CELL_STYLE, cellStyle);

Cell painters

NatTable user cell painters to paint each cell. These painters implement the ICellPainter interface. The default painter is the TextPainter. NatTable comes with a bunch of painters that can be used and mixed so the NatTable gets painted the way you want.

CellPainterWrapper

Paints the interior of the cell using a given painter. It then goes on put some decorations around/behind the cell.

Implementing classes are:

  • TextPainter - paints its content as text
  • VerticalTextPainter - paints its content as text vertically
  • PasswordTextPainter - specialized TextPainter that paints echo chars for every character
  • LineBorderDecorator - paints a border around the cell
  • PaddingDecorator - puts a padding around the cell contents
  • BeveledBorderDecorator - Gives the cell a button like look by drawing a beveled border
  • ImagePainter - Paints an image into the cell.
  • BackgroundImagePainter - Paints the background of the cell it wraps using the given image
  • GradientBackgroundPainter - Paints the background of a cell in a gradient way.

You can mix and match the above painters to create your own variations without needing to write much code.

For example the following snippet from StyledColumnHeaderConfiguration of StyledGridExample

Image bgImage = 
    new Image(Display.getDefault(), getClass().getResourceAsStream("column_header_bg.png"));
TextPainter txtPainter = 
    new TextPainter(false, false); 
ICellPainter bgImagePainter = 
    new BackgroundImagePainter(txtPainter, bgImage, GUIHelper.getColor(192, 192, 192));

will paint something like this

Cell painter example for BackGroundImagePainter

TextPainter

As the name suggests, it paints its content as text and reads the relevant style attributes out of the IConfigRegistry. It takes into account font, colors and alignment when it paints. There are several constructors that allow modifications to the default behaviour. So it is possible to tell the TextPainter to wrap the text, paint the background, add spacing and/or calculate the cell size (row height, column width) dependent on the text that should be rendered and if the text should be rendered underlined and/or strikethrough.

All of the listed configurations to the TextPainter also apply to the VerticalTextPainter. To get familiar with the various possibilities of TextPainter configuration, you should have a look at the TextPainter_Examples.

ImagePainter

The ImagePainter can be used to render an image to a cell. There are two ways to configure it:

  • constructor - the ImagePainter is created with an image and will only render this image.
  • style configuration - the ImagePainter is created with no image, so on rendering it checks the style configuration for the IMAGE attribute to know which image to render

CellPainterDecorator

Paints using a base painter and then decorates it using a second painter. For example, in the following snippet from the ButtonCellExample

new CellPainterDecorator(new TextPainter(), CellEdgeEnum.RIGHT, new ImagePainter(myImage))

will paint something like this

CellPainterDecorator example

Using a custom cell painter

In order to use a custom cell painter you need to:

  1. Create a custom implementation of the ICellPainter. Normally you would be able to reuse one of the existing ones.
  2. Apply a custom label to the cells which should use your painter.
  3. Register your painter in the config registry against the cell labels you applied in step 2. Custom painters are registered as CellConfigAttributes.CELL_PAINTER attributes.

The PercentageBarExample shows how to use the PercentageBarCellPainter instead of the TextPainter in the body region of the grid. This is done by registering the new painter as shown the following snippet

configRegistry.registerConfigAttribute( 
    CellConfigAttributes.CELL_PAINTER, 
    new PercentageBarCellPainter(), 
    DisplayMode.NORMAL, 
    GridRegion.BODY);

The painter itself looks like this

public PercentageBarCellPainter() { 
    super(new PaddingDecorator( 
        new LineBorderDecorator( 
            new PercentageBarDecorator(new TextPainter()), 
            new BorderStyle()))); 
}

The diagram below illustrates the various parts of the cell these painters paint Percentage bar example

Conditional styling

NatTable supports conditional configurations by using cell labels. This way it is also possible to add conditional styling. To use conditional styling the first step is to register a label to a cell.

The following snippet from the CellConfigurationExample shows how to register labels to certain conditions like a special value, column or row index.

//add custom cell label to cells that contain value AAA in column 2 
CellOverrideLabelAccumulator cellLabelAccumulator = 
    new CellOverrideLabelAccumulator(gridLayer.getBodyDataProvider()); 
cellLabelAccumulator.registerOverride("AAA", 2, CELL_LABEL); 

// Register label accumulator with the data layer 
bodyDataLayer.setConfigLabelAccumulator(cellLabelAccumulator);

The snippet below shows how to implement a custom IConfigLabelAccumulator that can be used on a NatTable that shows persons and highlight rows that show females:

@Override 
public void accumulateConfigLabels( 
    LabelStack configLabels, int columnPosition, int rowPosition) { 
    
    Person rowObject = dataProvider.getRowObject(rowPosition); 
    if (rowObject.getGender().equals(Person.Gender.FEMALE)) { 
        configLabels.addLabel(FEMALE_LABEL); 
    } 
}

Note:
To make this work the IConfigLabelAccumulator needs to know the IDataProvider.

To enable conditional styling, the custom style needs to be registered in the IConfigRegistry against the label defined before.

Style style = new Style(); 
// You can set other attributes here 
style.setAttributeValue(
    CellStyleAttributes.BACKGROUND_COLOR, 
    GUIHelper.COLOR_RED); 
    
configRegistry.registerConfigAttribute( 
    CellConfigAttributes.CELL_STYLE,    // attribute to apply 
    style,                              // value of the attribute 
    DisplayMode.NORMAL,                 // apply during normal rendering 
    CELL_LABEL);                        // apply for all cells with this label

NatTable cell painting considering labels