GWT: Better Layouts Through Subclassing

Here's a way to handle your layouts a little differently in GWT. Let's go beyond the canned tutorials that feature a single Panel layout and imagine the following structure.  Here we are using a DockPanel as a top-level container, with various other panels embedded inside of it:

Gwt_root_panel

It's easy to imagine the contents of each embedded panel changing as a result of actions taken against widgets in other panels, but for purposes of this post, let's just consider each sub-panel contains a static label.  For the tabbed panel, we define two tabs.

If you consider the way most tutorials and textbook examples are written, you might describe this layout with code like this:

Gwt_root_panel_ols_2

Looks messy, but functional.  There are accessor methods for each panel here since, realistically, you will need them in order to build on this functionality.  And did I mention 'messy'?  If you keep looking at pages and pages of code like this you might start to have more than a few misgivings about the choice of using Java to code your JavaScript application.  And this is just layout-- picture how all of this looks when you start adding dynamic behavior to your widgets.

Due to the nature of GWT, our options for improvement are limited.  We are forbidden from using reflection to build a more descriptive syntax.  We can not use any Java5+ constructs such as generics either.  So left with our options, what we really need is to find a way to abstract the construction of the layout behind some sort of builder mechanism.  We could grab the bull by the horns and write our own, native widgets.  Or we can subclass the existing UI classes.  Let's take a first stab at the problem through sub-classing:

Gwt_root_panel_nls

Interesting, no?  Here we take a rather unorthodox approach by setting up our layout in the first six lines of code and making heavy use of chained method calls to do it.  To reduce the clutter of accessor methods or local variable declarations for sub-panels, we provide a unique 'name' for each section which we use later on to look up the panel to work with it after the layout has been determined (in a real application, we would use the same kind of lookup mechanism as a registry to resolve dependencies as we introduced some dynamic behavior into the application).

I won't go through all of the subclasses which were required to make this example work, but here is enough code to give you a glimpse into what is going on.  We start with the class which extends GWT's DockPanel:

Gwt_my_dock_panel

As you can see, there's not much to it.  We defined the constants 'TOP', 'BOTTOM', etc elsewhere, which I think are better than 'NORTH'/'SOUTH'.  When we 'setContentAt' a given spot in the DockPanel, we return an object (poorly named, perhaps, but you get the idea) which allows deferred binding of the layout until the actual content is passed through to the proper method:

Gwt_my_container

Etcetera.  Clearly we can extract a method here or there to make the code more concise.  It would also be possible to reduce the number of methods on MyContainer by parameterizing the Panel type, but I chose to keep the method names distinct for the sake of clarity.  The last piece of the puzzle involves extending each Panel class we have defined in order to keep track of all instances in a Map.  Here's our custom VerticalPanel class.  The rest of the sub-classes follow the same footsteps. 

 

Gwt_my_vert_panel

As for the overhead involved in all this sub-classing, the difference in generated Javasript ends up to be fairly minimal.  Whether it's worth it or not may be a matter of taste, but there are cases where you may wish to sub-class panels in order to define additional behaviors (listeners, etc) associated with specific panel instances, so introducing a layout mechanism such as the one above won't add much more overhead to the equation.

What I described above is just a start.  There's room for improvement, but I think you are left with a good base to build on.

Topics:

Comments: 7 so far

  1. This style of programming has been termed “fluent” by others, and is typically useful whenever there is detailed process of building up complete component. See:

    http://martinfowler.com/bliki/FluentInterface.html

    This is the first time I’ve seen it applied to building GUIs, and now that I’ve seen it, I think it is a natural fit. The alternative I’ve used in the past is to create several classes for each sub-panel within a specific UI, which enhances readability, but which is not typically amenable to reuse. With your approach, you managed to enhance readability of the UI API, which can be reused immediately in every single new UI you construct.

    In fact, this “fluent” encapsulation of the GWT UI components would be a good candidate for a library that others could use to enhance productivity. Have you considered sharing this code with others?

    Comment by Robby, Monday, September 10, 2007 @ 10:43 am

  2. Robby,
    Thanks for the comments. I had completely forgotten that Martin Fowler covered this style before, so I appreciated the link on fluent interfaces.

    As for releasing a library to build on GWT, I think it would be great to see something like that come about. I think more real-world examples would be needed before deciding on how to proceed (namely, to keep the syntax somewhat consistent across the GWT client API). I have not used this in anything beyond prototypes, so I’m keen on finding out how this would help (or hurt) building complex user interfaces in a team environment. This is something I will keep revisiting.

    Comment by Anonymous, Tuesday, September 11, 2007 @ 11:30 pm

  3. Fluent APIs are often used with builder pattern i-e you build a complex object through a series of small settings.

    Use of builder pattern for building UI is not new. See Groovy SwingBuilder for example. JavaFX also employs the builder pattern for building user interface.

    Comment by Tahir, Thursday, September 13, 2007 @ 1:47 am


  4. Comment by Bruce Johnson, Saturday, September 22, 2007 @ 2:20 pm

  5. Great job.
    Any example-class for the registry?

    Comment by Mirco, Thursday, June 5, 2008 @ 1:44 pm

  6. Can you provide more information about the registry ?

    Thanks in advance.

    Comment by Miroslav, Thursday, August 21, 2008 @ 8:56 am

  7. [...] Here’s a clever DSL to build the GUI in a “fluent” way: http://www.pathf.com/blogs/2007/09/expressing-rich/ [...]

    Pingback by Structuring Java code that assembles a UI | Jake Herringbone, Saturday, November 1, 2008 @ 4:27 pm

Leave a comment

Powered by WP Hashcash

About Pathfinder

Follow the Blog

    Get a monthly update on best practices for delivering successful software.

    Subscribe via email

      

    Subscribe via RSS      RSS icon

Topics

Search

WordPress

Comments about this site: info@pathf.com