Thursday, August 30, 2007

New Europa default presentation

An internal note in the WorkbenchPage code lead me to think that our legacy code was broken due to a valid API change. Boris Bokowski has correctly pointed out that it is a bug 202280.

Eclipse Europa has a new default presentation that includes a new minimize/maximize behavior and new tab treatments.

I like the new feature but was a bit puzzled at the API changes made to IWorkbenchPage. Calls to IWorkbenchPage.html#isPageZoomed() always return false. Our application would never call IWorkbenchPage.html#toggleZoom(IWorkbenchPartReference) and our users became a bit bewildered by a view taking up the whole view stack.

IWorkbenchPage page = workbench.getActiveWorkbenchWindow().
                                getActivePage();
if (page.isPageZoomed()) {
    page.toggleZoom(workbenchPartReference);
}

Instead you need to call IWorkbenchPage.html#getPartState(IWorkbenchPartReference). It returns one of the following states.

IWorkbenchPage.STATE_MINIMIZED
State of a view in a given page when the page is zoomed in on the view stack. (int)0
IWorkbenchPage.STATE_MAXIMIZED
State of a view in a given page when the view stack is minimized. (int)1
IWorkbenchPage.STATE_RESTORED
State of a view in a given page when the view stack is in it's normal state. (int 2)

In our case a simple call to restore the view to its original state is all thats needed.

IWorkbenchPage page = workbench.getActiveWorkbenchWindow().
                                getActivePage();
page.setPartState(workbenchPartReference, 
                  IWorkbenchPage.STATE_RESTORED);

Wednesday, August 15, 2007

High performance graphics with SWT

When dealing with high performance graphics using a Graphics Context is not always the fastest way to render images.

We discovered this when trying to render a seismic variable density plot. On a typical two monitor system we were rendering an partial image of 2,000x800 pixels. Repeated calls to GC.drawPoint() or GC.fillRectangle() returned extremely slow rendering times. A whole seismic panel could be 10,000x4000 pixels. A large dataset could have 15,000 panels (about 500 Gigabytes) so you see we have to do things quickly.

The answer was to draw directly into an ImageData by setting each pixel using an indexed palette. In the image above text and grid lines are drawn using the Graphics Context while the colour pixels are set using ImageData.setPixel(). It sounds slow but ends up being extremely fast.

    PaletteData paletteData = new PaletteData(new RGB[] 
                   {new RGB(255,0,0), new RGB(0,255,0)});
    ImageData imageData = new ImageData(48,48,1,paletteData);
    for(int x=11;x<35;x++){
        for(int y=11;y<35;y++){
            imageData.setPixel(x,y,1);
        }
    }
    Image image = new Image(display,imageData); 

There is a great article on using SWT Image called Taking a look at SWT Images Summary which the code example above was taken from.

SWT Canvas default behaviour

This eclipse.platform.swt news group posting started me thinking again about platform differences in Eclipse RCP and Java. Without a bit of care you could end up having DOUBLE SECRET SWT.DOUBLE_BUFFERED! My apologies to Harold Ramis.

The default behaviour of org.eclipse.swt.widgets.Canvas does support SWT.DOUBLE_BUFFERED on Linux GTK but not on Windows.

import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class CanvasTest {
 public static void main(String[] args) {
  Display display = new Display();
  Shell shell = new Shell(display);
  Canvas canvas = new Canvas(shell, SWT.NONE);
  System.out.println("SWT.NO_REDRAW_RESIZE: "
    + stateToString(canvas.getStyle(), SWT.NO_REDRAW_RESIZE));
  System.out.println("SWT.DOUBLE_BUFFERED: "
    + stateToString(canvas.getStyle(), SWT.DOUBLE_BUFFERED));
  System.out.println("SWT.NO_BACKGROUND: "
    + stateToString(canvas.getStyle(), SWT.NO_BACKGROUND));
  System.out.println("SWT.NO_MERGE_PAINTS: "
    + stateToString(canvas.getStyle(), SWT.NO_MERGE_PAINTS));
 }

 private static String stateToString(int style, int styleFlag) {
  return (style & styleFlag) != 0 ? "on" : "off";
 }
}

Run on a Windows platform has the org.eclipse.swt.widgets.Canvas set as:

           SWT.NO_REDRAW_RESIZE: off
           SWT.DOUBLE_BUFFERED: off
           SWT.NO_BACKGROUND: off
           SWT.NO_MERGE_PAINTS: off

Run on a Linux GTK platform has the org.eclipse.swt.widgets.Canvas set as:

           SWT.NO_REDRAW_RESIZE: off
           SWT.DOUBLE_BUFFERED: on
           SWT.NO_BACKGROUND: off
           SWT.NO_MERGE_PAINTS: off