Painting of Figures

Figures are painted using a Graphics. The Graphics abstraction allows Draw2d to wrapper an SWT GC for extended functionality as well as performance optimizations. For example, Graphics supports pushing and popping of the current state. A figure paints using the following process:

  • Figure#paint(Graphics) - This method is declared on the interface, and kicks off the painting process. First, properties are set on the Graphics that would be inherited by children, including Font, background, and foreground Color. Then the Graphics state is pushed so that just these inherited settings can be restored when painting children. Next, the following methods are called:

    • Figure#paintFigure(Graphics) - The figure paints itself. Figures are not required to paint at all. A simple form of painting would be to fill in the bounding box with the figure’s background color.

    • Figure#paintClientArea(Graphics) - The client area is where children appear. This method should apply any changes to the Graphics which affect only children, such as coordinate system modifications like translating the graphics to the client area. This method also clips the graphics two the region where children are allowed to appear.

      • Figure#paintChildren(Graphics) - Now that the client area is setup, children are painted. After each child paints, the graphics state is restored to the incoming state so that children do not overwrite the inherited graphics settings from the parent.

    • Figure#paintBorder(Graphics) - Finally, the figure paints decorations which should appear on top of the children. If a Border has been set on the figure, it paints now.

Z-Order

The result of this process is that a figure composition (which structurally is a tree) paints in a pre-order, depth-first manner. The exception being the borders which are painted post-order. Using push and pop, changes made to the Graphics by one branch of figures have no affect on other branches. The order in which figures paint is often referred to as z-order. This term comes from the fact that the paint order creates the illusion of depth, and the z-axis would be perpendicular to the display’s x and y axes. Z-order or paint order is also manifested in the way hit testing is done.

image

Clipping

When a figure paints its children, it first clips the Graphics to its client area. As each child is painted, the graphics is also clipped to the child’s bounds. This prevents the child from painting outside of its bounds or the client area of the parent. Clipping is cumulative based on the entire parent chain. Below, Figure 3 is parented by Figure 2, which is parented by Figure 1.

image

Painting on a Swing JComponent

Painting on a Swing component is possible via the AWTGraphics class. Similar to SWT, the instances of this class require a Graphics2D object, which has to be derived from e.g. a JComponent or BufferedImage.

Unlike SWT, the Graphics2D object is generally initialized with a null clip. When painting a figure, this clip must be explicitly set.

Example:

IFigure figure = ...;
BufferedImage image = ...;

Graphics2D g2d = image.createGraphics();
g2d.setClip(0, 0, image.getWidth(), image.getHeight());

AWTGraphics g = new AWTGraphics(g2d);
figure.paint(g);
g.dispose();

g2d.dispose();

Note that Draw2D is built on top of SWT and thus support for other GUI toolkits is limited. For example, event handling requires a custom implementation of the EventDispatcher and is currently not supported.

Warning
All methods of the AWTGraphics class which expect SWT arguments are fundamentally unsupported, as the Swing paint operations are generally done within the Event Dispatcher thread and not the SWT UI thread.

Painting on an SVG document

In addition to the SWT Composite and Swing JComponent, it is also possible to paint directly into an SVG document by using the SVGGraphics class. Because this class requires Batik for updating the DOM structure, it is only available via the org.eclipse.draw2d.svg plug-in.

Instances of this class can be created similarly to the AWTGraphics class, except that they now require an SVGGraphics2D object as constructor argument.

The created document can be exported to a string or the file system using the SVGGraphics#stream(Writer) method.

Example:

try (Writer writer = ...) {
	SVGGraphics g = new SVGGraphics();
	g.setViewport(...);
	g.setClip(...);
	paint(g);
	g.stream(writer);
	g.dispose();
} catch (IOException e) {
	...
}
Note
The SVGGraphics class is based on the AWTGraphics class. It is therefore also necessary to explicitly set the initial clip. In addition, an SVG document also requires a viewport, which can be set via the SVGGraphics#setViewport(Dimension) method.

See Also