Alex headshot

AlBlue’s Blog

Macs, Modularity and More

The difference between SWT and AWT

Eclipse 2005 Swt

In an interview, James Gosling (founder of the Java language) said that he didn't understand why IBM had re-invented the wheel and created the SWT. He made some very negative comments as to the purpose of the SWT, and went as far as saying that he viewed NetBeans as a better IDE because it used Swing, whereas Eclipse uses SWT.

For those of you who don't know, Eclipse is an open-source Java IDE that has its roots in IBM's Visual Age for Java product. In building Eclipse, IBM created a new windowing toolkit called SWT or Standard Window Toolkit to create the user interface, instead of Swing or AWT. NetBeans is Sun's open-source Java IDE, but unlike Eclipse, is largely controlled by one company.

People never get things right on the first try, and Java's AWT was no exception to this rule. When Java came out, the AWT gave a very simple way of programming GUIs, and could be executed on any platform. One of the reasons that Java is so popular today is that this happened around the time of the web explosion, and Java (via Applets) were propelled to the fore with web browsers. In order to provide the same windowing experience on a variety of different platforms, Sun took the common set of features from every platform (e.g. Buttons) and made them available in the AWT. In doing this, they discarded some features which were available on some platforms, but not others. Examples include progress bars, three-valued checkboxes, combo (editable and drop-down lists) and so forth.

The AWT was also built as a 'closed' system; you had exactly those components, and there were no others that could ever be added. As a result, the AWT was born into a cramped straitjacket from which it could never hope to escape. (Amusingly enough, because the AWT was part of the core JVM, it couldn't -- and still can't -- be optional on a Java install. So even though server-side systems such as mainframes (zSeries) and AS/400 (iSeries) have no concept of graphics, the VMs still had to have an AWT implementation. IBM actually solved this problem by devising a remote windowing protocol -- similar to VNC -- that would allow Applets to run on a mainframe but be displayed somewhere else.)

There were some other technical problems that the AWT posed; for example, overlapping components were dodgy and the behaviours of the back-end were subtly different on different platforms. [Windows displays & as an Underline character, for example.] However, these weren't problems with the approach; they were problems with the implementation. The Sun AWT actually had one big Java/Canvas window(displayed at the back) and one window for each widget at the front. There was nothing stopping them having multiple canvases overlapping if they wanted to implement it. Similarly, there's no reason why the AWT toolkit should have had to be constrained in terms of its implementation; instead of methods like createButtonPeer and createListPeer it would have been trivial to implement a parameterised createPeer method.

Instead, Sun solved the problem with Swing, which is a very heavy event-driven system in which all the graphics are drawn in Java. [OK, so some recent JVMs have had graphics-card accelleration, but that's by far the exception than the norm.] As a result, Swing applications tend to feel sluggish in operation, and although computers have increased in speed since Java's Swing was thrust onto the stage, operating systems and the VM themselves have bloated and negated some of that improvement, so they still feel sluggish even today. There's also the down-side of the app not looking like a 'real' OS application, because Sun wanted to push the Metal Look And Feel instead of defaulting to running like a real OS app. [I know it's trivial to do the change, and most apps do. The question is; why isn't it the default?]

So why did IBM create a new widget set for its new IDE? Well, Eclipse was born out of WebSphere Studio, which itself was born from a migration away from Visual Age for Java many years ago. [In fact, it was at a time when VAJ only supported Java 1.1, to put it in perspective.] Even then, it was clear that Swing was going to be sluggish, and for anything other than a hello-world type application, you feel its performance. But it's not all down to drawing speed; it's also down to how events are taken off the queue and processed. There's a single Thread pulling windowing events from the OS, and I'm betting that you've come across at least one app where the screen redraw freezes as it resolves a DNS name or waits for a file to become available. I also have a personal bone to pick with the implementation of the AWT/Swing Thread; bug 4030718 highlights this 'feature' in which in order to exit a JVM, you must call System.exit() before you can leave the application. In fact, the JVM is quite capable of knowing when threads and windows are open, and could take care of this automatically, but bad design resulted in this not being implemented. [It was actually possible; I wrote a piece of software that would actually read in classes.zip and apply the fix for this bug, but it never made it in. Another case of Not Invented Here?]

But I digress. There are some fundamental problems with AWT that over-constrained, and some of those important problems weren't fixed in Swing. The performance issues aside, Swing is a capable GUI tool, but large Swing-based applications certainly don't feel as integrated into the OS as they could do.

IBM's decision to implement SWT was based on three issues:

  • They needed something that operated like, not just looked like, the custom OS
  • They needed to deal with event queues properly, so that a hanging application thread didn't kil the redraw
  • They needed all the performance they could get when running a heavy process such as an IDE

It wasn't a dig at Sun, and (despite claims to the contrary) Eclipse wasn't about keeping Sun out. It's just they wanted to go their own way, and everyone else wanted to go with Eclipse. They've been offered a place to join in with Eclipse, but they're too busy with NetBeans to want to go. And, as James rightly says, it's good to have competition between the two, though I wouldn't go as far as wanting to standardise on the keystrokes.

In fact, it's a misconception that Eclipse is 'just SWT' and that SWT is one big lump. In actual fact, there are 4 different layers that make up Eclipse's UI:

  1. SWT mapping layer. For each OS (and technically, each widowing system as well), there is a 1-1 mapping layer between the OS component and an SWT wrapper. So on Windows, there's a RECT class, whereas on Mac OS X there's a Rect class. These map directly to OS-level objects; essentlially, a Java wrapper around a native component.
  2. SWT implementation/emulation layer. To present a unified view of the SWT to programs, an SWT Button class exists, which is built out of OS-level primitives. So an SWT Button corresponds indirectly to an NSButton in Aqua, but an MFC Button in Windows. The purpose of the extra layer means that if bugs are found (e.g. the NSButton doesn't handle & characters) there can be a Java-related workaround in the OS X implementation of button. There's no dynamic switching of UI designs in SWT like there is in Swing; essentially, you put either swt-macosx.jar or swt-windows.jar on your classpath, and both contain an implementation of Button, that to the outside world, appear to behave exactly the same way. To be honest, there's very little reason why skinnable apps is a good thing (unless you talk to marketeers; but what do they know?) About the only good one is the NapkinLAF, which allows you to pretend your app is a demo, unfinished version.
  3. JFace assemblage of multiple SWT components. Although primitive widgets such as buttons are a necessity, there are some components (think JFileChooser) that are composed of such primitives. This is the purpose of JFace. As well as combining multiple features together (e.g. a Wizard) it also provides simple hooks to control data. As an example, there's a Tree component in SWT that you can use to display tree-oriented data, or there's a JTree JFace component that provides all the interactive selection and marking of a Tree UI that you could want. Clearly, JFace is much more powerful, but it's built on top of a SWT Tree component.
  4. Views, perspectives, and windows. Eclipse is made up of lots of Views (which themselves are often one or more JFace component; so the Tasks view is essentially a JFace component with other selection and filtering applied). Views are combined into Perspectives, and it's thus possible to configure Eclipse however you want it to look.

The architectural differences between AWT/SWT and Swing/JFace are the key reason they're different. AWT covers both 1 and 2 above; you couldn't have one without the other. Further, if there was a bug in the operation of a component, it required a JVM update, often wth a DLL fix. On the other hand, if there's a bug with SWT, you can download the source, make the fix, and because it's a Java fix, no expensive/difficult DLL re-compilation is required; just a class on a class-path.

Swing on the other hand tried to straddle both 2 and 3 at the same time. It provided the basic components, and some combinations of them (JFileChooser) but with a limited repetoire. And there's nothing that Sun produce that come close to the integration of the views and perspectives, which are a key part of the Eclipse Rich Client Project. Indeed, instead of focussing on just the low-level code (and expecting developers to create standard applications), Eclipse has actually provided what Sun haven't -- a framework for building new applications. It's a shame that more developers don't realise what the Eclipse Platform could be used for; mention Eclipse, and you can see the word 'Java IDE appearing in their eyes. It's actually a framework, guys -- what you're using is Eclipse Java Development Toolset or Eclipse JDT.

The partitioning that the UI takes is both important, extensible and refreshing. For example, not all OSs will have a combo box, but for those systems, it's possible to write an emulation layer in Java, so it will still run the same. Or, you can have a cut-down UI toolset that doesn't provide everything; and what do you know, but it's possible to get SWT for PDAs. There's even an Embedded Rich Client Project that aims to provide for developing applications for low-power devices.

Since it's extensible, we aren't going to be locked into the same set of components that we have for years. Since Java 1.0 came out, GUIs have become more complex, and there's no reason why AWT couldn't have had a ProgressBar by now (other than it's now implemented in Swing, and AWT is seen as a dead duck). In SWT, we have a ProgressBar, but next year when Widgets are all the rage, we'll get an SWT Widget, long before Java's Swing does. And it'll work the same on all platforms, except that it will be displayed by the platform, not drawn by hand (or the JVM). You don't see Eclipse hanging and the UI going completely blank whilst its compiling. On Mac OS X, the button still pulses gently whilst it's doing a checkout, and the progress bar animates. Run a Swing app on Mac OS X, and the progress bar is an ugly blue that doesn't animate and the button is a grim picture of a pulse locked in mid-step. (Arguably, the pulsing is an artistic feature that doesn't lend itself well to everyone, but Java apps are Different.)

Arguing that SWT is like going back to AWT isn't really right. Yes, it uses native OS components. It does that for performance, and to allow the VM to be doing useful things instead, like compiling code. But it's not hobbled like the AWT was implemented, and it's extensible to new widgets as they evolve. There are also far more powerful groupings of components in JFace than there are in Swing, which means you can write applications faster using it. And it looks and feels like a real application; it doesn't look and feel like a Java application.