Responsive UIs with Eclipse and SWT

Recently I had the problem that my ‘well-conceived’ view design did not scale down reasonably. I realized that the flexibility to arrange viewparts in stacks of arbitrary sizes in an Eclipse workbench window does not exactly ease the development of appealing UIs. At least if you strive for more than a set of actions placed around a list, table or a tree.

As luck would have it I also spent some time on responsive web design since we plan an overhauling of codeaffine.com. It was then when I had the idea to ‘rescue’ my UI concept by making it more responsive to size adjustments. As the result looks quite promising I decided to share the experience (and the code as GitHub gist) although the stuff is somewhat experimental1.

Setting up the Stage

First you might watch this short video (10 sec) that demonstrates what I mean by ‘responsive to size adjustments’:

The example shows a fictive task management view that is composed of various custom controls. You can see a use case selection, a list-detail representation and an action bar. At the beginning these controls are arranged vertically. But as the width expands the alignment changes. The selection bar is shown at the left, the list-detail section in the middle and the action bar moves to the right.

Furthermore the controls change their appearance gradually. The selection bar displays now a list of the available use cases. The action bar switches the action items to vertical alignment and – as space increases – additionally shows labels for each item. Finally the width expansion reaches saturation and from this point the layout stays fixed.

How is it implemented?2

For me, the obvious point to start with were SWT Layouts. But a straight forward solution based on one of the layouts I am aware of seemed difficult. So I tried my luck with a hand crafted one.

The idea was to use a scale of width ranges as measurement unit for the layout algorithm. All controls are associated with an individual storage for related layout data. The storage allows to configure different settings for each range. Now the algorithm can pick up the appropriate configuration for the actual composite width and layout the controls accordingly3.

Given this it seemed natural to call the custom layout ScaleLayout accompanied by an enumeration Scale and a layout data implementation ScaleData. The following code snippet shows how to use the latter:

class ViewContentScaleConfig {

  private final ScaleData selectorData;
  private final ScaleData seperatorData;
  private final ScaleData detailData;

  [...]

  void configure() {
    layoutSuperCompact();
    layoutCompact();
    [...]
  }
  private void layoutCompact() {
    selectorData.on( Scale.COMPACT )
      .setMargin( 5, 3, 0, 0 );
    seperatorData.on( Scale.COMPACT )
      .setWidth( 1 ).setMargin( 5, 0, 0, 0 );
    detailData.on( Scale.COMPACT )
      .setMargin( 3, 3, 2, 2 );
  }

  private void layoutSuperCompact() {
    selectorData.on( Scale.SUPER_COMPACT )
      .tie( seperatorData ).setMargin( 3, 0, 3, 0 );
    seperatorData.on( Scale.SUPER_COMPACT )
      .tie( detailData ).setHeight( 1 );
    detailData.on( Scale.SUPER_COMPACT )
      .setMargin( 0, 8, 0, 0 );
  }
}

The ScaleData facilitates a fluent attribute configuration, which I guess is quite self-explanatory. More noteworthy is the tie call which concats layout datas for a given Scale value, because this defines how a ScaleLayout arranges the controls within a certain range.

The Layout Algorithm

Without any ties all controls are aligned seamlessly in a horizontal row, each control taking the available client-area height and its preferred width as size. The last in line grabs the residual width of the client-area.

To change this a control can be tied to another. Note that only one tie per Scale and ScaleData is allowed. In fact this organizes the controls in one or more disjointed lists.

Now the list-head-controls will be lined up horizontally. In addition the controls of a particular list will be arranged subsequently below the head control. This is done in a way that the list controls appears as a column. The width of such a column is determined by the control with the largest preferred width. Height calculations for the different column controls follow the same rules as explained above for widths4.

sc7

As shown in the example snippet the default size calculations of a control can be overriden by hints. But even with that information the attentive reader might wonder how this construct with a fixed scale enumeration can possibly work within nested UI compositions.

Scale Provider

The missing piece to make the ScaleLayout actually work is a reference point. The scale has to be related to a certain composite of your UI. Changing the width of this ‘base’ composite might change the placement in the ‘scale’. And this information has to be propagated throughout the composition structure. The root composite of a viewpart is obviously a good choice to serve as reference point.

For this purpose there is a class called ScaleProvider which takes a composite – the reference point – as constructor parameter and a ScaleLayout instance in turn takes a ScaleProvider as constructor parameter. This is how the layout algorithm gets its frame of reference.

Moreover the ScaleProvider offers the possibility of listener registration. This e.g. enables to map the appearance modes of a control to Scale values. The principle is illustrated by the use case selector in the video above. The selector implementation can be switched between two modes: STANDARD and COMPACT. The following snippet shows how the mode changes are triggered by scale change events:

class SelectorModeUpdater implements ScaleListener {

  private final InfoSelector selector;

  SelectorModeUpdater( InfoSelector selector ) {
    this.selector = selector;
  }

  public void scaleChanged( ScaleEvent event ) {
    if( Scale.SUPER_COMPACT == event.getNewScale() ) {
      selector.setMode( Mode.COMPACT );
    } else {
      selector.setMode( Mode.STANDARD );
    }
  }
}

A similar mapping is used to trigger the appearance changes of the action bar.

Conclusion

The responsive UI approach improves the appearance of my view design considerably as it now adopts to different sizes. However I have to point out that the ScaleLayout has some drawbacks that should be solved before it can serve as a general purpose solution. First the layout algorithm is probably a bit too simplistic. Second the fixed scale approach is inflexible and induces a kind of semantic coupling. Third the ScaleData configuration tend to get a bit verbose…

But things may evolve in subsequent iterations and for an inventive soul this might serve as a good inspiration or starting point. And by the way in this regard I am very curious about the solution Holger and Jordi will present for RAP/Tabris in their talk Creating Responsive SWT Applications with RAP at EclipseCon 2014. In particular as they also cover resource handling which I omitted completely in this post.

For the folks that like to play around I provide the code of the ScaleLayout implementation as a GitHub gist: https://gist.github.com/fappel/9168399

  1. Note that it is not the intention of this post to provide a comprehensive paper of how to adapt responsive web design concepts to rich client applications. I neither have enough expertise on that matter nor do I have an opinion whether this is actually desirable.
  2. This was actually a question from Moritz Post I received while writing this post. Probably I should not have shared the video beforehand
  3. In case someone wonders: I do not handle height changes as they posed no problem to my UI design (KISS Principle)
  4. The gist download contains a demo that shows actually how it works

 

Reference: Responsive UIs with Eclipse and SWT from our JCG partner Frank Appel at the Code Affine blog.

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

JPA Mini Book

Learn how to leverage the power of JPA in order to create robust and flexible Java applications. With this Mini Book, you will get introduced to JPA and smoothly transition to more advanced concepts.

JVM Troubleshooting Guide

The Java virtual machine is really the foundation of any Java EE platform. Learn how to master it with this advanced guide!

Given email address is already subscribed, thank you!
Oops. Something went wrong. Please try again later.
Please provide a valid email address.
Thank you, your sign-up request was successful! Please check your e-mail inbox.
Please complete the CAPTCHA.
Please fill in the required fields.

Leave a Reply


− one = 2



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy | Contact
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close