Developer's Documentation

Principles

Do get some benefits of the Java2D support for Draw2d and GEF you must have installed the Java2D for SWT 2.0 framework.

Because the new classes are delivered as fragments of the Draw2d and GEF plugins, you will not need to modifiy or update your project classpath: once installed, the new classes will be automatically added to the plugin classpath.
Because the new classes are defined in the same package as their original counterpart it is easy to guess which class to use.

Converting Draw2d applications

The key change in your code is to create a J2DLightweightSystem instead of the regular LightweightSystem. Let see at an example:

Regular Draw2d example Java2D enhanced
public class Demo {
    public static void main(String args[]){
        Shell shell = new Shell();
        shell.open();
        shell.setText("Draw2d");
        LightweightSystem lws = new J2DLightweightSystem(shell);
        IFigure panel = new Figure();
        panel.setLayoutManager(new FlowLayout());
        lws.setContents(panel);
        Clickable button = new Button("Click me");
        Clickable checkbox = new CheckBox("Check box");
        Shape ellipse = new Ellipse();
        ellipse.setBackgroundColor(ColorConstants.yellow);
        Shape rectangle = new RectangleFigure();
        rectangle.setBackgroundColor(ColorConstants.lightBlue);
        panel.add(button);
        panel.add(checkbox);
        panel.add(ellipse);
        panel.add(rectangle);
        Display display = Display.getDefault();
        while (!shell.isDisposed ()) {
            if (!display.readAndDispatch ())
                display.sleep ();
        }
    }
}
public class Demo {
    public static void main(String args[]){
        Shell shell = new Shell();
        shell.open();
        shell.setText("Draw2d with Java2D");
        LightweightSystem lws = new J2DLightweightSystem(shell);
        IFigure panel = new Figure();
        panel.setLayoutManager(new FlowLayout());
        lws.setContents(panel);
        Clickable button = new Button("Click me");
        Clickable checkbox = new CheckBox("Check box");
        Shape ellipse = new Ellipse();
        ellipse.setBackgroundColor(ColorConstants.yellow);
        Shape rectangle = new RectangleFigure();
        rectangle.setBackgroundColor(ColorConstants.lightBlue);
        panel.add(button);
        panel.add(checkbox);
        panel.add(ellipse);
        panel.add(rectangle);
        Display display = Display.getDefault();
        while (!shell.isDisposed ()) {
            if (!display.readAndDispatch ())
                display.sleep ();
        }
    }
}

That's all!
You can even mix regular and enhanced lightweight systems if they are not attached to the same canvas.

Converting GEF applications

For GEF, a little bit more work have to be done, because the LightweightSystem if often created internally to some classes.

More, to efficiently manage the new scaling capabilities, the intermediate ScalableGraphics object created by some classes (like the scalable layers) have to be short-circuited.

The GEF support comes with the essential framework classes already converted to Java2D. The following list summarizes the available classes: as their name if the regular GEF class name prefixed with J2D, their meaning is obvious:

Converting an existing GEF application, or writing a new one is almost straightforward:

For example, to convert the Logic example to support Java2D, you will have to change the following lines of code:

Original LogicEditor class
New code
public class LogicEditor
    extends GraphicalEditorWithPalette
{
...
protected void configureGraphicalViewer() {
    super.configureGraphicalViewer();
    ScrollingGraphicalViewer viewer = (ScrollingGraphicalViewer)getGraphicalViewer();

    ScalableFreeformRootEditPart root = new ScalableFreeformRootEditPart();
...
public class LogicEditor
    extends J2DGraphicalEditorWithPalette
{
...
protected void configureGraphicalViewer() {
    super.configureGraphicalViewer();
    ScrollingGraphicalViewer viewer = (ScrollingGraphicalViewer)getGraphicalViewer();

    ScalableFreeformRootEditPart root = new J2DScalableFreeformRootEditPart();

The LogicEditor will now render through the Java2D engine, while the SWT engine can be reactivated through the user prefrences.

Managing scaling

If you want to write applications that can support both rendering engines, you have to use one of the key top level classes instead of their regular Draw2d or GEF one.

One area where you may have to write some more intrusive code is when you plan to support scaling for both engines.

For example,  let us look at the org.eclipse.draw2d.examples.zoom example available from the GEF CVS website.

The main class org.eclipse.draw2d.examples.zoom.ZoomExample is modified as explained above:
public static void main(String args[]){
Display d = new Display();
final Shell shell = new Shell(d);
shell.setSize(800, 800);
LightweightSystem lws = new J2DLightweightSystem(shell);
...

But this is not sufficinet: if you run this application you will have a blank screen and nothing will appear if you change the zoom level!

The reason is that the zoom is actually performed inside another the class ZoomContainer which is not aware of the new rendering method.

Following the Draw2d recommandations, scaling is supported inside this figure that acts as the root figure of the application and manages the zoom related computations. The rendering process is delegated to a ScaledGraphics object, and this is the piece of code we are concerned with:

Original ZoomContainer code
New code
protected void paintClientArea(Graphics graphics) {
    if (getChildren().isEmpty())
        return;

    boolean optimizeClip = getBorder() == null || getBorder().isOpaque();

    ScaledGraphics g = new ScaledGraphics(graphics);

    if (!optimizeClip)
        g.clipRect(getBounds().getCropped(getInsets()));
    g.translate(getBounds().x + getInsets().left, getBounds().y + getInsets().top);
    g.scale(zoom);
    g.pushState();
    paintChildren(g);
    g.popState();
    g.dispose();
    graphics.restoreState();
}
protected void paintClientArea(Graphics graphics) {
    if (getChildren().isEmpty())
        return;

    boolean optimizeClip = getBorder() == null || getBorder().isOpaque();

   // ScaledGraphics g = new ScaledGraphics(graphics);

    if (!optimizeClip)
        g.clipRect(getBounds().getCropped(getInsets()));
    g.translate(getBounds().x + getInsets().left, getBounds().y + getInsets().top);
    graphics.scale(zoom);
    graphics.pushState();
    paintChildren(g);
    graphics.popState();
    // g.dispose();
    // graphics.restoreState();
}

Because the scaled rendering is the very job of Java2D, the intermediate ScaledGraphics is no longer needed, thus simplifying the painting code.

Writing dual code

If you also plan to support the regular Draw2d engine, all the necessary work is already done for the classes delivered with the new framework, but you have to test for it inside your code. For example the above new code will become:

protected void paintClientArea(Graphics graphics) {
// Preconditions are always verified first!
if (getChildren().isEmpty()) return;
boolean optimizeClip = getBorder() == null || getBorder().isOpaque();

// Creates a new ScaledGraphics or continue with the current one
Graphics g = null;
if (graphics instanceof J2DGraphics) {
// Java2D engine
g = graphics;
} else {
g = new ScaledGraphics(graphics);
}

// Always preserve current state
g.pushState();
// Apply application specific code
if (!optimizeClip)
g.clipRect(getBounds().getCropped(getInsets()));
g.translate(getBounds().x + getInsets().left, getBounds().y + getInsets().top);
g.scale(zoom);
// Paint figures with the new graphics state
paintChildren(g);
// Restore it
g.popState();
// dispose of the temporary ScaledGraphics
if (g instanceof ScaledGraphics) g.dispose();
}

This pattern is sufficiently generic (and really necessary in very few situations) that we can conclude that you can now provide the best of both worlds to your clients.