Eclipse JFace tip: How to add column headers to a TableViewer

So you’ve created a JFace TableViewer, via:

TableViewer tableViewer = new TableViewer(parent);

The scenario: You have already set up the label provider, the content provider and the (model) input. The label provider, which extends ITableLabelProvider returns values for two columns. The data is showing up nicely, but you don’t see any APIs in TableViewer to set column headers.

The key to understanding the problem is realizing that the Swing API != JFace API. It is more like Swing = JFace + SWT. Yes, I know that technically Swing sits on top of AWT, but in practice, most of the AWT APIs have been superceded by Swing, so most of the time when you deal with Swing, you’re dealing with a JSomething. In fact, you know if the code is bad if it uses a lot of non JSomethings.

On the other hand, Eclipse has more than one dedicated project teams dedicated to UI development that have well defined boundaries. The SWT team builds the widgets which either wrapper or emulate native widgets. They also build the supporting structures around these, like Drag and Drop. The JFace team wrappers these SWT widgets to let programmers work with them in Model-View-Controller (MVC) way. The JFace team is careful not to duplicate any of the SWT work. There’s also GEF, which I won’t cover in this post.

This JFace and SWT partnership leads to some confusion, since programmers can access both APIs. Swing/AWT programmers can also access both APIs, but in practice, 80% of the code uses the Swing APIs. (With notable exceptions for the various Layouts and Graphics2D.) When using JFace and SWT, there is greater usage of SWT. So AWT has a List which is not used in practice and Swing has a JList which supersedes it. In contrast, SWT has a List and JFace has a ListViewer, which uses that List. If you need to do view-specific stuff, you access the SWT List inside of the JFace ListViewer.

This leads us to the solution to our problem of adding column headers to a JFace TableViewer: You need to get the table (which is playing the View of MVC), add the column headers to it, and also tell it to show its headers.

Here’s code that illustrates how to do this:

// Get the SWT Table that's inside the TableViewer
Table table = tableViewer.getTable();
// Add a column header named "Column 1" that's left justified TableColumn column = new TableColumn(table, SWT.LEFT); column.setText("Column 1"); column.setWidth(100);
// Add a column header named "Column 2" that's left justified TableColumn column2 = new TableColumn(table, SWT.LEFT); column2.setText("Column 2"); column2.setWidth(100);
// Show the column headers table.setHeaderVisible(true);

A Desktop Java Renaissance

I finally got used to the new look of JavaLobby and am glad that the gliding nav toolbar stopped gliding. That’s one of those features that seems glitzy but just ends up distracting the user. Anyways, I responded to two posts and found myself thinking… there is going to be a Desktop Java Renaissance.

Why so? Hasn’t Microsoft frozen the JDK out of Windows? Sun has a workaround for that, with Java WebStart, the consumer-oriented, and the Java Auto Update system tray icon. Also, Java is installed by default on Mac OS X, SUSE Linux and Java Desktop System.

Doesn’t Swing emulate everything and make your apps seem slightly out of place? Sun has improved the L&Fs of Swing in 1.4.2 and 1.5, but if those aren’t native enough, you can use the Eclipse Foundation’s SWT / JFace.

Are there any Desktop Application Frameworks, so I don’t have to roll my own every time? Eclipse refactored the Rich Client Platform (RCP) out of itself, due to popular demand. Trivia: The RCP Birds of a Feather (BOF) session at EclipseCon 2004 was the most popular, leading people like myself to write my name sideways in the margin to jam myself in there. Thanks again to Ed Burnette for spearheading the RCP effort.
If you’d rather use Swing (since RCP requires you use SWT / JFace), then you have Spring Rich or NetBeans to choose from as a framework. I’m interested in trying out Spring Rich and will share my experiences with you.

Are there any components available, ala Visual Basic or Delphi, to speed my development? In VB or Delphi, there’s a large assortment of components that you can buy instead of build, which shortens your dev cycle. This has been lacking in the past. However, now there is a multitude of Eclipse plug-ins, most of which can be used in the RCP, with more being developed every day it seems. If that’s not enough, you can even embed native components (like ActiveX on Windows or WebKit on Mac OS X) through either SWT or JDIC (which integrates well with AWT / Swing.)

What about Enterprise Java? Don’t worry, that’s still alive and well and thriving. Not only will J2EE focus on ease of development, but there are alternative frameworks like Spring.

The reason all of this is occuring is due to plain and simple market competition. Eclipse raised the bar when it came to look and feel and plug-in infrastructure, RCP on the framework side, and Spring on the enterprise side. Eclipse plug-ins started to multiply as the platform became more viable. While this can cause some divisions for those deeply invested in one specific technology, I think this is good for the Java community as a whole, because the choices this competition creates lets us developers decide our own fates. (And if our choice is open source, we can even contribute to the production and not just be a consumer.) All the pieces seem to be falling in place for a renaissance for Java on the desktop. Things should get even better, once Eclipse 3.1, with its extensive support for developing RCP apps, is released, its alternative Spring Rich matures, and as the plug-in market continues to grow.

Interesting developments to watch: There seems to be an effort to make RCP easier to install via either: 1. RCP support for Java WebStart or 2. natively compiling Eclipse / RCP apps.

What to do when you get an UnsatisifiedLinkError when running an SWT or JFace application

So you’re trying to run an SWT application (or JFace, since JFace relies on SWT) inside Eclipse and you get the dreaded UnsatisfiedLinkError. This usually appears as one of the following: Exception in thread “main” java.lang.UnsatisfiedLinkError: no swt-pi-carbon-3063 in java.library.path (Carbon on Mac OS X), Exception in thread “main” java.lang.UnsatisfiedLinkError: no swt-win32-3063 in java.library.path (Win32 on Windows), or Exception in thread “main” java.lang.UnsatisfiedLinkError: no swt-pi-gtk-3063 in java.library.path (GTK2 on Linux). Those are the UnsatisifiedLinkErrors for SWT in Eclipse 3.0.1.
For Eclipse 3.0, it would be swt-pi-carbon-3062, swt-win32-3062, and swt-pi-gtk3062 respectively.

Now there is an easy correction for this. Just go to “Run” | “Run…”, which brings up the “Run” dialog. Then navigate to the “Arguments” tab and in the “VM Arguments:” text box, enter (for Eclipse 3.0.1):

-Djava.library.path=${system:ECLIPSE_HOME}/plugins/org.eclipse.swt.carbon_3.0.1/os/macosx/ppc (for Carbon on Mac OS X)

-Djava.library.path=${system:ECLIPSE_HOME}/plugins/org.eclipse.swt.win32_3.0.1/os/win32/x86 (for Win32 on Windows) or

-Djava.library.path=${system:ECLIPSE_HOME}/plugins/org.eclipse.swt.gtk_3.0.1/os/linux/x86 (for GTK2 on Linux).

For Eclipse 3.0, substitute 3.0.0 wherever you see 3.0.1.