- Login or register to post comments
- Older polls
NatTable user cell painters to paint each cell. These painters implement the ICellPainter interface. The default painter is the TextPainter. As the name suggests, it paints its content as text and reads the relevant style attributes from the
config registry. It takes into account font, colors and alignment when it paints.
Fortunately NatTable has several cell painters already implemented for you.
CellPainterDecorator
Paints using a base painter and then decorates it using a second painter. For example, in the following snippet
new CellPainterDecorator(new TextPainter(), CellEdgeEnum.RIGHT, new ImagePainter(myImage))
Snippet from the ButtonCellExample
Will paint something like this

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:
You can mix and match the above painters to create your own variations without needing to write much code.
For example the following snippet
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));
Snippet from the StyledGridExample (StyledColumnHeaderConfiguration)
will paint something like this

In order to use a custom cell painter you need to:
CellConfigAttributes.CELL_PAINTER attributes.
We will go through the PercentageBarExample so that you can see it in action. In the example code we setup the BODY region to use the PercentageBarCellPainter. This is done by registering the new painter as shown the following snippet
configRegistry.registerConfigAttribute(CellConfigAttributes.CELL_PAINTER, new PercentageBarCellPainter(),
DisplayMode.NORMAL, GridRegion.BODY.toString());
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

Comments
Painting CellPainters next to each other
The example using the CellPainterDecorator has the problem that the icon may hide the text. The following CellPainter solves that problem (I release it under the Eclipse Public License):
package org.acoveo.nattable.views;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import net.sourceforge.nattable.config.IConfigRegistry;
import net.sourceforge.nattable.layer.cell.LayerCell;
import net.sourceforge.nattable.painter.cell.ICellPainter;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Rectangle;
public class HorizontalPainterWrapper implements ICellPainter {
List painters = new LinkedList();
public HorizontalPainterWrapper(Collection cellPainters) {
painters.addAll(cellPainters);
}
public HorizontalPainterWrapper(ICellPainter[] iCellPainters) {
painters.addAll(Arrays.asList(iCellPainters));
}
public int getPreferredWidth(LayerCell cell, GC gc, IConfigRegistry configRegistry) {
int width = 0;
for(ICellPainter painter : painters) {
width += painter.getPreferredWidth(cell, gc, configRegistry);
}
return width;
}
public int getPreferredHeight(LayerCell cell, GC gc, IConfigRegistry configRegistry) {
int height = 0;
for(ICellPainter painter : painters) {
height += painter.getPreferredHeight(cell, gc, configRegistry);
}
return height;
}
public void paintCell(LayerCell cell, GC gc, Rectangle bounds, IConfigRegistry configRegistry) {
Rectangle remainingBounds = new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height);
for(Iterator iter = painters.iterator(); iter.hasNext();) {
ICellPainter painter = iter.next();
int width = painter.getPreferredWidth(cell, gc, configRegistry);
Rectangle interiorBounds =
new Rectangle(
remainingBounds.x,
remainingBounds.y,
iter.hasNext() ? width : remainingBounds.width,
remainingBounds.height
);
painter.paintCell(cell, gc, interiorBounds, configRegistry);
remainingBounds.x += width;
remainingBounds.width -= width;
if(bounds.x + bounds.width < remainingBounds.x) {
break;
}
}
}
}