GTK+ Learns height-for-width geometry

Over the past weeks I’ve been concentrating my full energies on an Openismus funded expedition to finalize the extended layout patches that teach height-for-width geometry management to GTK+.

Its time to show off a little what came out of this effort:

The test/extendedlayoutexample program screenshot cropped by gimp running against the native-layout branch.

No ! not the crazy allocation assertions from hell ! I’m just kidding; I’m not sure if those assertions come from running the Gimp against git master or from running against the native-layout branch. The point of this shot is only to say the stuff is pretty damn stable. I’ve been creating the demos (in this post and my last blog post) using Glade running directly against a modified height-for-width GTK+ core. The above screenshot was taken with the Gimp running against the modified GTK+ and it displayed and behaved fine during the exercise.

So that was my first priority: turn the work into something that we can all use right now, there are some really minor API breaks (also discussed in the announcement) but from what I’ve seen so far you’re favorite application will run just fine against the new GTK+ code (that includes sticky places where the application tries to hack its own height-for-width labels by way of handling “size-request” signals and such).

One of the really difficult parts of getting this working was to make container widgets report sensible width-for-height/height-for-width collectively for their children:

Two wrapping labels in a horizontal box (top left)

The trick is the horizontal box has to compute a collective minimum and natural height for its overall allocated width:

When stretched, the horizontal box reliquishes height by collectively calculating height-for-width of its children.

Trickier still, was to figure out how a height-for-width widget and a width-for-height widget could live together  in the same hierarchy and at least always require enough space in both dimensions (so that we can set reasonable window constraints based on the interface’s minimum size and labels don’t wrap ever out of view unexpectedly).

After a lot of thought and valuable insights shared on irc (Owen, Matthias…), a good nights sleep and then another day hacking we were able to dish out a GTK+ that will also do width-for-height:

An interface that uses width-for-height

And the two possible extremities of the window pane:

Lowest position for the window pane

And:

Highest position of the window pane

All of this is available in the ‘native-layout’. A trimmed down branch has been created for review of the base feature set called ‘native-layout-incubator’ where you can find the above demo ‘extendedlayoutexample’.

Thanks Murray and Openismus for the great experience, and for the great new features for GTK+ !

Glade could use a little help

While the Glade project can seem complex and not everybody writes GObject code in C; there are a few things that could really improve the usability of Glade without applying any real coding skill.

For instance, ever since GtkBuilder was introduced, we are still missing icons for almost all the important and attractive new objects available with GtkBuilder:

The missing icons include things like Size Group, Status Icon, Text Buffer, Text Tag, Entry Buffer, some of the newer Cell Renderers etc. Glade uses these icons every chance it gets to help to give context to the user while editing the interface, like in the Property Editor:

They are also a great indication when viewing the overall project with the Inspector view:

Note that most of the missing icons are not widgets and don’t already have a visual representation. The design needs creativity to create visually familiar patterns based on functionalities of new and interesting objects that are available, like a Size Group or a List Store.

We’ve made requests before but I suppose the interest just wasn’t there.

But really, Glade’s engine is not doing so bad, if it only had a good paint job to match then it wouldn’t appear so much like it just came out of the junkyard.

Note also Glade installs the icons into the theme, which means other development tools can also leverage the icon set that Glade installs.

Please help us with the icons ?

Good afternoon 😉

Extending the layout for GTK+

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…).

Height-for-Width

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 😉

Update:

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.