Category Archives: Swing

Sneak peek of SWT and Swing in Vista

Here’s a screenshot of Eclipse (using SWT) on Vista, courtesy of Carolyn MacLeod and Ed Burnette.

And here’s NetBeans (using Swing) on Vista, courtesy of Chet Haase.

Looks like Java UIs have a good future in Vista. I believe they’re ahead of schedule compared to where they were when XP was coming out. I think with SWT being native and getting a good reception from the development community, that a big focus in Java 6 (Mustang) is pixel-perfect fidelity in Swing:

Chet Haase: We hear you. Native look & feel fidelity is a big thing for us in Mustang.

Gotta love competition!

Will Apple be supporting Eclipse and SWT better in the future?

Marcello pointed out this Apple job posting for a Java Frameworks Engineer in the Eclipse-Mac Google group:

“We are interested in an energetic developer who can master our Java implementation (Java, Obj-C, C & C++) and contribute to making Mac OS X the best environment for Java development.

…You will quickly become a valuable member of the team responsible for the next generation implementation of the HI Frameworks for Java on Mac OS X.

…Responsibilities include portions of the implementation of the MacOS X Java SWT, AWT and Swing APIs…

…Required experience:
We are looking for 1 of these 4 types of people:

- has developed core pieces of the Eclipse IDE and has strong knowledge of SWT and its implementation
…”

(emphasis is mine)

As far as I know, the SWT implementation for OS X has been an Eclipse Foundation affair, with Andre leading the way. So it is nice to see Apple starting to adopt SWT as one of its own.

I think they’ve done a great job with the Swing on OS X implementation. I think its one of the better (maybe best) Swing implementations available.

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);

Proposal to reduce repetition with Swing and SWT listeners

DRY – Don’t Repeat Yourself

We know that this is good, since it reduces code maintenance, so why do we persist with writing listeners like this: (Note that this is example is written with SWT; Swing looks almost the same.)

        final Button button = new Button(shell, SWT.NONE);
        button.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                text.setText("Hello World");
            }
        });

If you’ve got lots of these lying around, well first off, you should try using an application framework like the Eclipse Rich Client Platform or the Spring Rich Client Project. But if you don’t (and even if you do, you still need to deal with wiring interface elements together), then you can make a code template in your IDE to generate this idiom. However, you’re stuck with maintaining all this code, plus the code is not as clear as it could be.

What if instead, your code looked like this?

        final MyButton button = new MyButton(shell, SWT.NONE);
        button.onPress( text, "setText", new Object[] { "Hello World" } );

Unfortunately, because Java places a higher value on security of its classes than expressiveness, you cannot add methods to an existing class (which you can do in some other languages). Also, you cannot subclass SWT widgets. So, instead, we use a utility class, which is slightly less readable.

        final Button button = new Button(shell, SWT.NONE);
        ButtonUtils.onPress( button, text, "setText", new Object[] { "Hello World" } );

This is better, since it takes what used to take 5 lines of code to express and put it into 1. It also focuses on what should happen when the button is pressed, instead of that being dominated by the supporting code.

Swing introduced something similar back in Java 1.4 called EventHandler. This generates a dynamic event listener. For example:

        JButton button = new JButton( "Hello World" );
        button.addActionListener( (ActionListener) EventHandler.create(
                                                        ActionListener.class, textField, "setText", "source.text" );

Note that this has the disadvantage of having to grab parameters to pass to the target object from the ActionEvent object. That’s why I stuffed “Hello World” as the text of the JButton for this simple example.

Here is the main piece for ButtonUtils. The code for findMethod is relatively simple, but I can post it if people want it.

    /**
     * Registers an object that has a method named methodName,
     * which is called when the button is pressed.
     * 
     * @param button
     * @param instance
     * @param methodName
     * @param parameters
     */
    public static void onPress( Button button, final Object instance,
                                                    String methodName, final Object[] parameters ) {
        final Method method = findMethod( instance, methodName, parameters );
       
        button.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                try {
                    method.invoke( instance, parameters );
                } catch (IllegalArgumentException exception) {
                    exception.printStackTrace();
                } catch (IllegalAccessException exception) {
                    exception.printStackTrace();
                } catch (InvocationTargetException exception) {
                    exception.printStackTrace();
                }
            }
        });
    }

So what do people think about this? Does anyone use something like this in their code? The advantages are: 1. DRY, 2. less code overall, 3. somewhat clearer (could be clearer with Java language changes). Disadvantages: 1. reflection isn’t refactored easily, 2. reflective code doesn’t take advantage of static type checking at compile time, 3. potential for reflection exceptions.

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 Java.com, 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.

Native Browsers in Java on Windows (and Linux)

Last night I looked at embedded native browser components in Java, focusing on Mac OS X. Tonight we’ll look at what’s available on Windows. There are at least 4 contenders, perhaps more. In addition, there are 3 browser choices: Internet Explorer 5.x/6.x, Mozilla 1.4, and Mozilla 1.7.

First off, there is the Browser component that I talked about last night. Due to the elegance of the Eclipse plug-in loader (actually it is OSGi in 3.x), the name of the component is also called Browser. However, it is in the org.eclipse.swt.win32 plug-in instead of the org.eclipse.swt.carbon plug-in. This is the nicest of the bunch, with the caveat that it only embeds IE 5 or IE 6. Using the SWT Examples that you can download from the main Eclipse download page (look for Example Plug-ins), it worked pretty much like IE. You could even drag URLs to it and it would load them up and update the location bar. On my Windows XP laptop, I’ve got IE 6 installed and using the BrowserSpy information, I confirmed that it was indeed IE 6. Ryan Lowe pointed out that if you have IE 5.x on your Windows, then this component would embed IE 5.x. This came out with Eclipse 3.0.
Eclipse plug-in / RCP developers: I would use this implementation.

Second, we’ve got OLE/ActiveX integration on SWT Windows. I tried this via the SWT Examples again and was unimpressed, but probably because there was more work done in the SWT Browser widget. BrowserSpy couldn’t detect what it was, the location bar didn’t update, though it did otherwise work like IE. This has been around since at least Eclipse 2.x.

Third, there is the JDIC Browser component. This is an AWT component that can nest IE quite easily. There’s a demo available via JNLP. This can also embed Mozilla 1.4 (the whole thing, not Firefox), but you have to jump through some hoops to get there, including setting an environment variable and copying an .exe file. This performed well and the APIs are designed to work cross-platform. The SWT Browser API edges it out for completeness, though. BrowserSpy confirmed IE. This is licensed via LGPL. This project is looking for some help, especially with supporting Mozilla 1.5 and up. BTW, Mozilla 1.4 is around the timeframe of Firefox 0.7 – 0.8. This project started up around the JavaOne 2004 timeframe.
Swing developers: I would use this implementation.

Finally, there is the Webclient. This is another AWT-based implementation that predates the JDIC. This supports Mozilla 1.7 (the whole thing again, not Firefox) only. There is no IE support, but that only makes sense, since this is a collaboration between the Mozilla Foundation and Sun and is hosted at mozilla.org. BrowserSpy confirms that it is Mozilla 1.7. The installation for this was the most heavyweight, due to the reliance of Mozilla 1.7. Nonetheless, this performed decently. This project was started back in 1999 and is licensed with the Mozilla Public License. I suspect that this will either merge with JDIC or be overtaken by JDIC.

One more… JRex supports Mozilla 1.4+ and integrates with AWT/Swing. Haven’t tried this yet, but again, I think JDIC is the project to beat in the AWT/Swing universe.

Linux readers: The only problem is that the list would be almost the same as the one for Windows, except that IE gets the boot, with Mozilla being the only choice for embedding. Also, no OLE/ActiveX. SWT GTK2 3.0 supports Mozilla 1.4 – 1.6 and the 3.1 stream adds support for 1.7.

Update [11/3/2004 10:33PM] – I clarified which browser will be embedded using the SWT Browser widget on Windows. It will be whatever version of IE that is currently installed on your system.

Browser components in Java

I’m currently putting together an application that will be implemented in SWT/JFace/RCP/Java, Swing/Spring Rich/Java, and Cocoa/Objective-C. I’m doing to see what they will look like on OS X, plus to learn a little more about the RCP, a lot more about Spring Rich, and a whole lot more about Cocoa/Objective-C.

One of the interesting aspects of this application is that it will have a Browser embedded in it.

I looked first at the SWT sources, since I’ve use the Browser component in Eclipse. In fact, you can drag an .html file from the Finder and drop into the Package Explorer or the Resource Navigator, then double-click on the .html file to open it in the Browser. This shows the decent integration Eclipse has on OS X, but there are still some holes, such as dragging out of an SWT app which isn’t supported yet. By the way, if you care about that, you can register with the Eclipse Bugzilla and then vote for it. Anyways, the Browser integration in Eclipse is quite nice, as it embeds the WebKit (which is what Safari uses) in your SWT/JFace/RCP app. It has hooks for actions such as openURL, back, forward, stop, refresh, as well as listeners for state changes. The org.eclipse.swt.browser.Browser class in org.eclipse.swt.carbon_3.0.1 plug-in is quite clean. It doesn’t go directly against JNI, which always seemed ugly. It hides most (or all) of the native calls in the org.eclipse.swt.browser.WebKit class, which depends on the swt-webkit library I talked about in an earlier post.

I then searched around for a good Swing Browser component. I found the relatively new JDIC project, which was kicked off around the JavaOne 2004 timeframe. The acronym stands for JDesktop Integration Components, with JDesktop Integration Components, which when translated into English means: “let apps be more native”. This has a browser component, but doesn’t have one yet on OS X. In fact, most of the OS X port of JDIC is incomplete. However, I would give this a try on Windows, Linux, and Solaris.

Searching further, I ran across an integration of WebKit with AWT by Dmitry Markman. The code is not as clean as the SWT Browser code, but it looks like the JDIC-Mac team will probably adopt it and clean it up. However, if you try the sample app included, it works pretty much like the SWT Browser widget, since it uses the same WebKit. I think the SWT Browser still has better support for actions and state listeners, though. I’m looking forward to the JDIC-Mac browser though, as well as any Dock/menulet support they could offer.

By the way, there is a good article about using the SWT Browser widget at the Eclipse Corner.

UPDATE: [11/2/2004 10:52AM EST] I’ll be looking at embedded browser components (in Java of course) on Windows tomorrow.