Introducing YippieMove '09. Easy email transfers. Now open for all destinations.

Today WireLoad is releasing SwtCallback, a Java library for SWT that enables callbacks for event handling. SwtCallback is inspired by the Swing enhancer Buoy by Peter Eastman.

If you know you want this, just skip to the bottom of this post for the download link. Otherwise, read on and I’ll explain the reason we wrote this library.

I’m a big fan of readable and concise code. Another thing I’m a big fan of is user interfaces that look and feel like what users expect. Given this, I’ve always had an aversion to UI programming in Java. Because I think it’s very telling, I’ll let this flash video illustrate: totally gridbag. Bottom line is that in Java, user interfaces look weird and often attempts to alleviate this weirdness result in enormous amounts of hard to read code.

One solution is to use the Standard Widget Toolkit (SWT) instead. SWT enables easier UI building with resulting UIs that are both faster and look and feel better for the end user. What’s more, the code is more concise thanks to FormLayouts, sane widget sizing and the availability of standard functionality.

There’s one thing I think can be improved on though: readability. SWT code has a tendency to, like Swing, become littered with hundreds of listener classes, or worse, faceless listener implementations. For example, your code may look like this:

public class Demo implements SelectionListener {

...
   void initialize() { 
      Button myButton = new Button(shell, SWT.NONE);
      myButton.setText("Click Me"); 
      myButton.addSelectionListener(this);
   }
...

   public void widgetDefaultSelected(SelectionEvent e) {
      // I don't care about this event but I have to 
      // have a handler to satisfy the interface.
   }

   public void widgetSelected(SelectionEvent e) {
      // Do something
   }
}

Notice how the method named ‘widgetSelected’ has a very generic name: it has to since that’s the name it was given in the SelectionListener interface. Also, if there are many widgets that listen for selection events, then this single method has to handle all of them with a big if statement or some such. Not very readable. We also had to thumb on conciseness by adding one method which we didn’t even want: widgetDefaultSelected.

A better method is to associate the handler with only a single widget by using an inner class, and to use an adapter to avoid having to add a dummy method. This would typically look like this:

Button myButton = new Button(shell, SWT.NONE);
myButton.setText("Click Me"); 
myButton.addSelectionListener(new SelectionAdapter() {
   public void widgetSelected(SelectionEvent e) {
      // Do something
   }			
});

Much better. Less code, easier to read and it’s clear what ‘do something’ is associated with. But now we end up with a bunch of anonymous classes and deeply nested code. It’s still not perfect.

Enter SwtCallback. With SwtCallback, our final version of the program may look like so:

void initialize() { 
   Button myButton = new Button(shell, SWT.NONE);
   myButton.setText("Click Me"); 
   Callback.add(myButton, SWT.Selection, this, 
      "myButtonSelected");
}

/**
 * Called when myButton is selected.
 */
@SuppressWarnings("unused")
private void myButtonSelected() {
   // Do something
}

This has everything we wanted: it’s clear what the ‘myButtonSelected’ method does because it’s well named. There are no listeners to implement and no inner class bloat. The definition of myButton is short without being complicated or hard to understand. As an added bonus SwtCallback allowed us to make the event handler method private – this makes sense since the method is only relevant for the corresponding UI class.

UI programmers with experience outside of Swing will hopefully immediately recognize and appreciate the idea of callbacks. If you still need more reasons though, I’ll suggest a couple:

  • Less code means fewer bugs and easier maintenance. Callbacks allow you to handle events without lots of extra classes or big if-else statements.
  • You can link many events to the same handler. For example, maybe you have a ‘Quit’ button in a window. This button can have the same handler as the standard close event for the window.
  • No need for dummy methods. Since you’re not implementing listener interfaces you don’t have to implement handlers for events you don’t care about.
  • Natural names for methods. You’re not constrained to some standard name for an event handler. You can name your method ‘handlePasswordFieldGainedFocus’ if you want to.
  • Private or protected event handlers. With interfaces your event handling methods have to be public. Most of the time they’re very specific to some UI classes. It doesn’t make sense for other unrelated classes to call your handlePasswordFieldGainedFocus() method.

If you still need more, Peter Eastman, the author of Buoy, expresses the rationale for callbacks much better than I ever could here.

SwtCallback is released under the BSD license. Download the source and binary here:

Download SwtCallBack. More information is available here.

Patches and comments are welcome. Apologies for the lack of documentation – if there’s interest in this library we’ll revisit it. For now, if you find it useful, great!

Update 1: SwtCallback 0.2 has been released.

Author: Tags: , ,

Trackbacks/Pingbacks

  1. Playing With Wire » Java library SwtCallback 0.2 released, helps avoid Runnable interface

3 Comments

  1. Ben Pryor says:

    This is an interesting approach. I’d be interested to hear your thoughts on one of the big downsides to this method, which is that you give up type safety and the refactoring wizard won’t change the string literal when you refactor the method name. To me (others may disagree) this is a lot to give up for a little extra typing.

    I didn’t look at the code behind this at all, but don’t you also lose the event object with this approach? You don’t always need it but sometimes you do.

    Also, the recommended SWT approach is to have anon. inner class methods delegate to an identically named private method in the outer class:

    myButton.addSelectionListener(new SelectionAdapter() {
    public void widgetSelected(SelectionEvent e) {
    MyClass.this.widgetSelected(e);
    }
    }

    private void widgetSelected(SelectionEvent e) {

    }

    You could of course change the private outer class method to something that was named more specifically if you had more than one of these handlers.

    To my eyes anyway, the above method is as readable as using the callback library and has the advantage of type safety and refactorability.

    Anyways, like I said an interesting approach – I’d enjoy hearing your comments on the above.

  2. Like you touch upon in your comment there are definitely a couple of downsides. I assume that by the type safety problem you refer to the fact that there is no compile time checking of your event handling methods. This is true, but this problem is alleviated by the fact that callbacks are usually registered early on during program execution, and that SwtCallback will throw an exception at this time if it can’t find an appropriate handler. This means that for most programs you’ll know immediately that there’s a problem.

    A surprising side effect of this runtime check is that it avoids a problem with using Adapters: if you subclass an adapter and you try to override one of its methods, you may actually typo the override method and neither the compiler nor the runtime environment would be able to detect this. With SwtCallback a typo like that would be detected at runtime. (The @overrride tag is another solution to this problem.)

    As for refactoring, you’re right. Eclipse wouldn’t be able to rename one of these methods. In practice the callbacks are usually declared in the very same class or possibly in the corresponding view class for a particular controller. In the rare case that you do want to rename a method you would indeed have to suffer changing two different places by hand, but at least the other place you need to change is usually close at hand.

    You don’t need to lose the event object. If your callback method signature includes an event parameter, SwtCallback will pass the method the corresponding event object when calling it.

    Using an anonymous inner class to call out to a private handler is a good solution which I like too. I still prefer the one line solution of SwtCallback as it’s shorter and less complex: I don’t have to remember that the method I need to override is ‘public void widgetSelected(…)’ in a SelectionAdapter. With an Swtcallback, all I have to do is to select the right SWT.XXX identifier and I’m good to go. Every handler I make will have this consistent syntax.

    Thank you for your interesting comments. To summarize: yes, there is no compile time checking of the provided method. On the flip side there’s solid runtime checking. You don’t need to lose the Event object when using SwtCallback. Finally, SwtCallback is easier on the programmer’s memory and less complex than anonymous extended adapters in inner classes, at least in my taste.

    That said, Mr. Pryor’s presented solution is a good alternative to SwtCallback, especially if you wish to be able to refactor your handler methods, and you desire a solution that is statically correct instead of being a dynamic runtime solution.


© 2006-2009 WireLoad, LLC.
Logo photo by William Picard. Theme based on BlueMod © 2005 - 2009 FrederikM.de, based on blueblog_DE by Oliver Wunder.
Sitemap