These weeks, on the generous behalf of Openismus; I’ve been spending my full attentions on teaching GTK+ some new tricks where resizing the interface is involved.
It was a rocky ride of detective work at first; picking up the bit’s and pieces of Mathias Hasselmann’s original work, various other patches from the old branch and reading dozens of email threads and bug reports; all of which make up a web of information that spans over the last 5 years.
This was followed by a session of regression testing; I wanted to have a good grasp of what was working and what was broken in the branch (I also hoped I could kill all the regressions before introducing any features). That went quite well as I have a good grasp on what’s still broken and what features are still missing.
After all that hacking it was about time I owed you all a blog so lets take a look at what the features are and where we stand with them.
What is the Extended/Natural Layout ?
The Extended Layout has been defined as a few things in the past which covered different feature sets. For the purpose of this writeup we intend to achieve the 2 main goals which are:
- Smartly distributing space to child widgets to display the maximum content of children before adding any extra space.
- Allowing height-for-width/width-for-height contextual resizing
Some key points about what these features introduce are:
- In addition to the concept of a widget having a minimum size; a widget can also use up extra space by declaring a “natural size”, this aspect allows for the first feature.
- Sizes are only ever computed in one dimension at a time, either for the default widths/heights or in context of the size in the opposing dimension. This means a minimum “size” no longer exists as we know it; although it can be emulated by getting the minimum width for the natural height of a widget. This change is also what allows us to negotiate size properly with wrapping labels.
So, people may remember Havoc Pennington’s blog post on text that resizes properly (it was years ago), anyhow; here are some similar visuals on how GTK+ widgets are resizing in the native-layout branch:
Here is a horizontal box with some basic display widgets inside; at the natural size:
And here at a smaller size, note that the larger button and label will ellipsize before the small combo box:
But all the children do ellipsize:
When the layout is larger; the button in the center is sized to its natural size before allocating extra size to the children which asked to “expand”:
Well that’s an idea of what the natural sizes bring to the GTK+ interface, there are of course other widgets that are not yet working with the new layout; I gave cell renderers some attention for combo boxes but they still need work to be usable in treeviews (that’s one of the current regressions actually…).
The height for width feature basically allows for the above feature to work the same for container widgets who are interested in allocating decent sizes for children, but allow for more flexible display widgets found deep in the roots of GTK+ widget hierarchies.
Here is a quick example of what wrapping labels can do with height-for-width support, here is a vertical box with some height-for-width aware widgets packed in; along with a static Label widget to fill the extra space:
Here is the same interface slightly wider:
Note how the wrapping labels request less height for every line they unwrap:
Extended Layout features allow labels to unwrap automatically; relinquishing valuable screen realestate to parent containers in the interface. These are the effects of "height-for-width".
Currently I’m also experiencing some difficulty getting height-for-width information to cascade correctly through the ancestry of boxes in GTK+, I tried my best to outline the details in a post I wrote to gtk-devel-list yesterday, of course all feedback welcome there.
For those who will checkout the branch; I will be adding some more test cases next week (in a few days), currently sizegroups are broken after a mega API change; although they we’re broken in some ways to begin with and now I have a good idea of how to fix them; any feedback on the new GtkExtendedLayout/GtkExtendedCell apis would be great if you have time to stop by gtk-devel-list.
Well so far it’s been an honor and pleasure to do this work for Openismus, on a project I already like to participate in (GTK+). The project is an ambitious one surely, lets go do it justice
Murray suggested I should post some comparison shots; Good idea.
All the previously shown screen shots were taken using the new GTK+ native-layout features.
Here are some comparisons of how the interface reacts with and without the added features. In this first example you can see that with current GTK+; Combo Boxes request widths for ellipsizing Cell Renderers which it shouldn’t. Also you can see that Buttons/Labels will not know how to request more than: “…”:
A Combo Box, Button and Label with Current GTK+
Here we can see that without any explicit width requests, GTK+ with Extended Layout features can spread the ellipsizing Labels properly:
A Combo Box, Button and Label with the Extended Layout
when stretched out, the exact same interface will comparatively look like this:
Stretched Combo Box, Button and Label with Current GTK+
In the case of normal GTK+ the Button in the center never requests a “Natural” size. As it is also not set to expand inside the Horizontal Box; the button stays very small in the center.
Here we can see that even though we never told the button to expand, Extended Layout will help it at least request a “Natural” size:
Natural Size Combo Box, Button and Label with Extended Layout
In the height-for-width case, this is what the stretched UI would look like without the Extended Layout features:
GTK+ does not unwrap the Label naturally to fit the width. With the Extended Layout the Labels will unwrap and relinquish vertical space to its parents.
In this final case its clear that GTK+ doesn’t know how to rewrap the label on its own, some applications these days implement hacks to get this to work by riding the “size-request” and “size-allocate” signals.