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.
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
- 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.
- This was actually a question from Moritz Post I received while writing this post. Probably I should not have shared the video beforehand
- In case someone wonders: I do not handle height changes as they posed no problem to my UI design (KISS Principle)
- The gist download contains a demo that shows actually how it works
Nowadays, Responsive Design is on the Top & Thanks a lot for sharing such step by steps details regarding designing Responsive Web Layouts using eclipse & swt .
The way google has given priority to mobile first indexing and the mobile users are increasing in big numbers it important to take care of responsive desinging and this is perfect of developer
By start build up feature becomes default and Nowhere is it uploaded to the device unless later you build the project.
What’s the Pros and Cons of these disk caching algorithms.?
Quite details post! Gives some more information.
Hi, very interesting story. I really like yours works. Keep up the good work
https://www.javacodegeeks.com/2014/02/responsive-uis-with-eclipse-and-swt.html
Thanks for sharing this, It is really helpful.
Thanks for the information. I’ve definitely pick up something new from great content.
I’ve been surf riding on the net for over three hours these days; nevertheless, I ne’er found any gorgeous article like yours. It’s alluringly valued on my behalf of me. As I might see it, if all Net proprietors and bloggers created puzzling substance as you probably did, the world wide web is in a general sense additional helpful than at no matter purpose in late memory.
Thanks for this great informative content, really gain some knowledge here.