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:
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:
The trick is the horizontal box has to compute a collective minimum and natural height for its overall allocated width:
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:
And the two possible extremities of the window pane:
And:
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+ !
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.
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.
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:
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: “…”:
Here we can see that without any explicit width requests, GTK+ with Extended Layout features can spread the ellipsizing Labels properly:
when stretched out, the exact same interface will comparatively look like this:
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:
In the height-for-width case, this is what the stretched UI would look like without the Extended Layout features:
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.
So its Tuesday afternoon prime time on Planet GNOME, here’s an inside look on whats been going on this week for Glade.
Runtime Warnings
Last week we got the GtkToolPalette integrated into Glade and got Glade vertical again, this week I went on a rampage of hunting down startup warnings, warnings caused by loading Glade files and generally any warnings/assertions that can be fired while manipulating projects in Glade.
That effort left us with a couple interesting side effects:
Now we introspect if widget classes are scrollable and we don’t allow adding non-scrollable widgets to scrolled windows
Now we update treeviews in the workspace seamlessly when the underlying treestore columns are redefined
A nasty data corruption bug occurring when loading liststore data that contains gaps (missing unserializable columns) was also fixed.
Once these items were fixed I was pretty much left on my own to fix some issues of my choosing and improve some things in Glade – awesome – so I decided to prioritize on issues that did not need backing support in GTK+, as there has been lots of development there that we haven’t been able to keep up with.
The signal editor
The first issue I decided to tackle was the ‘swapped’ attribute for signal connections defined in Glade – that’s right, until this week Glade was never able to read/write this attribute. To illustrate the importance this has in Glade I want to show you a before shot:
Ok so the editor looks alright at first sight but there are some confusing aspects, for instance the “user data” in the signal can only ever refer to an object in the Glade file – no mention of that is made. Furthermore when one goes through the whole google research to find that the user data is supposed to be an object, they immediately get stumped by GTK+ swapping the object at connection time for seemingly no desired reason – very, very confusing.
Something to keep in mind as well is that signal definitions in Glade have generally been unused. Mostly because of an inability to pass data external to the Glade file as user data to callbacks. Generally people use a parent or controller object as a module pointer to be passed to all callbacks; this technical problem with signals has really been a non-issue ever since the introduction of the gtk_builder_connect_signals() api which takes a default pointer argument to pass to signals for just this purpose.
Well, moving on – after adding the “swapped” attribute to the editor I was quite unable to tear myself away from the editor, it hasn’t seen an update in many years and has been lagging behind the rest of the UI, so without further adieu I present to you:
Now the signal editor is doing a bit better, I didn’t have the time for a full scale rewrite using GtkBuilder for its store, view and renderers as I have been hoping to do for a while but – at least she learned some tricks from her big brother the property editor:
Now the signal editor lets you view the documentation for a signal at the click of an icon (Thank you Frédéric Péters for getting DevHelp page contextual searches working again ! sorry for waiting 6 months+ to notice !).
The editor does not let you type text for connected objects for user data, instead you get an object selection dialog
Now versioning support icons/tooltips show up for signals that are introduced in the future of your project’s target version.
Tooltips explaining about the signal editor fields show up on the treeview column headers
Signal, Handler and Object fields in the editor are user resizable but allocate a reasonable size.
Actions
So, with a rocking new signal editor in master I still had some hours to kill, I went on to tackle the relationships of GtkActionGroup <–> GtkAction in Glade – I wasn’t able to pull out a customized editor for this yet, but I imagine it will look like the menu or toolbar editor and allow hierarchical configuration of the project’s action groups/actions (currently Glade will only let you add an action to a group via the Inspector widget: Right click -> Add widget here / Paste commands will do the trick).
Glade now also lets you set an accelerator key for a GtkAction, the property only applies to actions which are placed into a group, ideally this will be the ultimate place to define accelerator keys using Glade so that they integrate well with menus and toolbars.
Thank you
A big thankyou to Openismus GmbH who sponsored the project and made all of these unlikely advancements in Glade actually happen.
I’ll be turning my attention away from Glade this week to look at some other serious GNOME issues, keep up with my blog for regular updates on this Openismus sponsored effort.
Among some other recent developments, one interesting thing is that the GtkToolPalette; which was previously EggToolPalette dating from 2008 by Mathias Hasselmann modeled to behave as a palette written for Glade by Vincent Geddes back in 2007 (drum roll…) : is now integrated as a drop in replacement for the original palette code in Glade !
This allowed me to remove 3 source files and 3 header files from the Glade tree, but not only that; it was also an enriching experience to see the improvements that have been made on the palette (the built-in drag/drop support, integration with GtkToolItems and better scrolling functionality was noticeable) and to think of all the bright individuals who put work into it from a variety of continents.
All that being said I think there still needs to be a generic way to do context menus for the palette, GtkToolbar exports something like this; currently we are stuck with something of a hack to get our context menus working.
Vertical Glade
Another event of interest this week is that Federico Mena-Quinero came around and showed willingness to fix Glade side effects on that nasty horizontifying bug. After short lapse of thought I agreed to throw away the “orientation” property from Glade and only support it for base classes which are not implicitly oriented – in short; Glade will not do that horizontal weird thing with .ui files that fail to mention the orientation explicitly (likely converted by gtk-builder-convert stript…).
Sponsored by Openismus
It’s truly a pleasure to announce that the GtkToolPalette integration patch along with a few other bugs I closed yesterday are only the first patches in an effort sponsored by Openismus GmbH. This effort will be focused partly on Glade and partly on GTK+, I’m very excited and determined to make the most of this time improving GNOME.
So I took another Saturday afternoon to look after the whole composite thing I started hacking on last week. It’s surprisingly not a lot of work to do in terms of lines of code written.
First, I went and enhanced GtkBuilder so that you can add a parent widget context to the parse; this way while parsing GtkBuilder fragments you can start them with the <child> tag instead of <object> and have the builder parent the serialized children onto a dynamic runtime instance (in our case, a composite container widget).
Second, I trashed gtkcomposite.[ch] and integrated the code into GtkContainer (following Rafael Villar Burke’s advice); this way any already existing container widget can be extended as a composite widget.
Third thing was, as Torsten Schoenfeld pointed out was missing, I added api for bindings to assign a GtkBuilderConnectFunc to be used on a per class basis, this means that for instance, composite widget code in GTK+ gets connected with regular C callbacks, but derived code of that same widget in another language gets to use a connection algorithm specific for that class vtable for that language… which brings me to..
Finally composite classes can also be extended and each class can optionally pull in a .ui template to define its children, which means with some added magic of gtk_container_get_composite_child() to pull out implicitly defined composite children, GtkBuilder has no problem to “blend in” widgets added from subclasses into internal composite containers exposed from a composite parent (I added a new test case to the bug describing this).
For those who are wondering what the hell kinda crack this guy is cookn’ up, basically… its an api of GtkContainer that lets you associate a GtkBuilder .ui file with any container class you define, automatically assigning any property endpoints you define to the corresponding instances built from the GtkBuilder fragment – at construct time, for free – an effort to completely abstract the packing of widgets from user code, and hide GtkBuilder semantics under the hood.
So it was saturday afternoon this weekend, and I was already tired – of reading all crap being thrown back and forth at one another on our own foundation-list, that is really a shame because it looks like we could be ready to make some real changes and set a better directive – or at least our OWN directive for GNOME as a foundation – for us – for the hackers.
Obviously feelings are mixed in this debate, and before people started throwing crap at eachother, for misrepresenting each other and correcting each other and basically looking like very professional and like pompous asses, there were some interesting things said. This post by Dave Neary was drowned out in noise twice so far and thats a shame, hopefully linking to it here on planet will help to give his post a better audience, personally I really love the “dangerous and racy” proposal/idea: GNOME hidden in plain sight, if you like you can read why in my post – in a nutshell I think our code base suffers from popularity and we end up writing results-oriented software because of it – because we end up working on what “downstream needs now” instead of the innovative future technology that we should be working on… and everyone here has worked for a corporation – we know that results-oriented code gets thrown in the garbage.
So – partly because I think people are sore about the whole mobile thing (silly but true), and partly because it seems like a perfect time to innovate, and partly because I just miss the days when we would argue vehemently on gtk-devel-list about future apis and if they were perfect enough or what… I think we need a bit more of that excitement in general, to attract more serious hackers, and make GNOME by GNOME for GNOME – an umbrella for free software projects to really get the space, infrastructure and as Dave so elegantly put it; the “stewardship” that these projects need to really flourish and innovate (ok misrepresentation mittens on, no he didnt say “stewardship” exactly like that… but I’m borrowing the word for today).
So because of all those reasons above I just LOST IT and wrote a patch, the patch is something I had in mind for some months now and I’ll try to explain in human terms as best I can what this patch does.
The patch introduces a notion to GTK+ that a GtkBuilder file can be associated with a Widget Class, when a widget is built with a template.ui file assigned to it, then any instances of that class will come with its composite hierarchy prebuilt, signals from its child hierarchy connected to its own class methods – and instance variables already preinitialized to access desired components of a composite widget’s children.
And I need people who implement language bindings to look at this 🙂 ideally, how it should look in super-duper object oriented language ‘x’, would be something like this:
class MyClass:GtkComposite {
var someObject:GtkAdjustment; // some instance variable
connectable var someLabel:GtkLabel; // A "connectable" instance variable
function the_button_clicked (var button:GtkButton) {
someLabel.setText ("the button was clicked");
}
}
So, for the user – the idea is they compile a class MyClass, and hopefully he doesnt have to say anything explicit, i.e. when the compiler/interpretor finds that MyClass.language has an accompanying MyClass.ui – the ui should just be compiled into the class and the above code should “just work” after instantiating a “MyClass” object.
For the language binding – it would mean that the language binding would have to install GtkParamSpecComposite properties onto the GObject it creates under the hood for a derived GTK+ widget class (i.e. Im sure this will work for vala but others… dont know) – this way the language can introduce the “connectable” keyword which explicitly asks for a property name <–> child instance name association before any user code runs.
For the devtools front, it means we can have a tool like Glade add a feature that lets you rip out a sub-hierarchy and implement it as an object class in the user’s language of preference, the sub hierarchy would become an independant Glade file and can be re-included with its hierarchy at multiple places in the program/UI.
The general idea of this patch is to push GNOME devtools/GTK+ apis towards catching up with the industry leaders in UI tools, its a migration of coding practice in GNOME uis all across the board.
We can move from: old-school “kinda dynamic” interfaces where an object loads an interface explicitly and then plays god on the widgets, connecting to signals and making the whole thing move from some controller proxy object, or worse, not modular and handle all callbacks in a main “application bussiness logic” zone.
To: A world where if you need a widget to have different functionality – you add to it – always by inserting your code onto the object running in the interface – if you need a form with lots of entries and an OK button – thats a Composite widget, can be reused over and over without any added hassle of using a controller object, can be derived and extended like any object, no controller proxy, no hassle – just a UI inside a widget fully functional after g_object_new() time.
So lets create some hype and lets do some real innovations – we could very easily come up with some tools that leverage GObject and GTK+ in modern ways and smash the competition (I’m thinking Xcode/Interface Builder as an initial “beat them” target, hey what if we had the same API usability and integration of IDE tools, but we werent restricted to Objc, or Cocoa api, and we compile everywhere, and we support every popular language… what could beat us then ?)
Well as I said we need to create some hype – bugzilla is okaaaay but I started a thread for this on gtk-devel-list, ofcourse in the hope to turn some heads and get ṕeople excited about GNOME… please jump in !
Actually long time since I’ve been actually doing gnome stuff and for not rolling a tarball this winter I’m a bit sorry… actually I did get the impression this past year that there was really very little interest in our little Glade project, which from my point of view is a work in progress with so many really amazing opportunities on the horizon.
But on the other side of the coin, while not everyone sees the potential as I do – I do not think all that work to get our initial writeup of GtkBuilder support was a waste of time; on the contrary, it still amazes me how many people around the world are using Glade and getting stuff done, even though Glade itself… is not done !
Actually I’m also touching base with you guys because my own plans fell to the water this winter and I need some help to make my wishes come true !!!
I dont wish for a house… I dont wish for a BMW… all I wish is to get to Korea soon to visit somebody important to me (as silly as it sounds – seems to me the house and the beemer are more attainable in the world I live in).
So doesn’t anyone have some odd contract for me ? I’d love to do some serious hacking of course, as specially anything gnome development platformish (hint hint: … 😉 ), but hey I can write silly iphone apps or even script some php if I have to.
So whether this is an opportunity for you to secure my services for a long term, or just throwing me a bone cause you’re a nice guy, just send my cv along to someone who might be interested and you’ll really make my day.
and dammit why cant I build gnome-doc-utils today ?! (joke, dont have to answer that 😉 )
This year I’ve had lots of mixed feelings about Glade 3.6 … The bright side of things is that despite some regressions and even if some of the feedback we get is negative – alot of people are still using Glade 3.6 and leveraging at least some of the new features available with GtkBuilder (ofcourse only a few loose strings can make entire features unusable, like tight GtkTextBuffer/GtkTextView integration for a random example), but Im still really happy for this – its a shame we missed out on tying up GtkActionGroups so far but I think some people might already be doing some interesting stuff with GtkActivatable/GtkAction associations.
Some things do make me sad, and if you are reading this and I snapped at you in the past for some bugzilla comment that I found was not helpful to me at the time, sorry about that. The truth is I bit off more than I could chew, and for some reason I imagined that picking up the pieces after releasing 3.6 would be different.
The bugmail I received this morning was kindof disheartening, this bug was probably one of the most imporant and most annoying bugs still open since the release of 3.6, it was filed in April.
It took me 20min. to fix including the changelog entry, and it took me more time to beat up git and make a fresh checkout/commit and go comment/close the bug … and the core is like 100% documented … and I usually answer my emails …
Well I think Glade has big big potential personally, but sadly the potential is (potential * 0) if people are so scared to fix the bug in Glade, that they need to integrate a script into the build to reinterpret Glade’s xml output to fix the bug locally instead.
Anyway I wish you all luck, theres another big decade coming up for the those who will do this thing all over again, I dont know if or how much Im gonna be there but man, its important to be a crew and stick together, set your objectives together, get funding together, rock the gnome crew logo, leverage it and do something really revolutionary. I doubt the traditional competitive every man for himself attitude inherent in the free software domain is going to cut it this time.
In the last couple of days there has been some quick unexpected improvements in Glade, Javier Jardón wrote us up a brand new website !
So with the help of Rafael Villar Burke (Pachi), we touched up and finalized the content and translated it into python scripts so it can be easily updated with news items in the future.
I was also inspired to write down and share all my possible plans (a frustrating kung-fu process of mailing plain text attachments), and also compile them into a list of possible roadmaps that we can track on the Wiki. Hopefully, since I cant move mountains by myself other people will be interested and we can accomplish some great things together 😉