# 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`): ```java 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` ```java 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](images/backgroundImgPainter.png) ## 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` ```java new CellPainterDecorator(new TextPainter(), CellEdgeEnum.RIGHT, new ImagePainter(myImage)) ``` will paint something like this ![CellPainterDecorator example](images/cellPainterDecorator.png) ## 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 ```java configRegistry.registerConfigAttribute( CellConfigAttributes.CELL_PAINTER, new PercentageBarCellPainter(), DisplayMode.NORMAL, GridRegion.BODY); ``` The painter itself looks like this ```java 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](images/percentageBarCell.png) ## Conditional styling NatTable supports conditional configurations by using [cell labels](04_Configuration.md#cell-labels "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. ```java //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: ```java @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. ```java 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](images/configLabels_0.gif)