I’ve been complaining about the state of GUI toolkits and standards, etc, for some time now. Even (and especially) in the FLOSS world we have so many incompatible ways to do GUIs, it’s crazy. No one can bother to write a GUI in every possible toolkit (or usually even in more than one!) so we end up with multiple projects all working on the same thing, but “in X toolkit/style”.
I was looking at the output of the Qt Designer (GUI drag-n-drop tool for the Qt toolkit) a couple weeks ago and realised something: the output is very hackable! In fact, many of the GUI designer tools out there have text or XML files that can be processed. To convert between them, all it would take is mapping the classes, properties, and events between the different toolkits.
Of course, that got me thinking. Mapping Qt to Gtk and Tk etc al, then mapping Gtk to Qt and Tk et al would be a rediculous proposition. Each toolkit or format would add an increasing number of bidirectional mapping requirements to any software.
The solution was pretty obvious. Create an intermediate data model that can represent GUIs from any toolkit and just write input/output filters. The strategy has a side-benefit too: such a data model could form the basis for discussion between different toolkits and formats on their similarities and where they could be brought closer together. Ideally, very simple GUI programs could be source-compatible between, say, Qt and Gtk.
So, how to determine the best way to model this data? Research and a wiki of course! Document existing toolkits and formats and what widgets/properties/events/layout stragegies they have, and see what the common patterns are.
So far I have at least widgets documented for Gtk, Qt, HTML forms, XForms, XUL, and wxWidgets. I have identified common widget and property patterns and common layout patterns. I have already started writing software to read and write GladeXML and should start on Qt Designer output soon.
They all suck. I’m not kidding. I’ve tried Qt, GTK+, Tk, even Shoes. Shoes is the best of the lot so far, but none of them seem to get right the one thing I’ve come to take for granted on the web: layout.
Take the following HTML snippet, for example:
<div>
<input type="checkbox" />
<span>label</span>
<div style="display:inline-block;margin-left:40px;margin-right:40px;">
<div>name</div>
<div>description</div>
</div>
<span>HAI</span>
</div>
You may crtisize the form of this snippet, but it’s pretty clear what it does: one row with a checkbox, a label next to it, a two-line element with a name and description, and finally the text “HAI”.
In Shoes (the one that makes this easiest) this is almost:
stack {
flow {
check
stack {
para 'name'
para 'description'
}
para 'Free'
}
}
Though apparently I need to know the width I want for the name/description pair up front (in pixels or percents) or it will try to take up the full window and thus wrap to a seperate line.
The thing is, though, it’s not really the toolkits’ fault. Layout isn’t a thing they’re supposed to be good at, and they’re certainly not used to use fluid-layout types who care what happens when the window gets resized (with all fairness to toolbars, which handle that ok). Most simple apps are designed to have their main window one size and not changed, which makes absolute positioning of everything possible. Toolkits have enough to deal with drawing widgets and interacting with the desktop environment and OS to get events.
The thing is, widgets are a solved problem. Really. If I want to throw some widgets on a window and hook up event handlers, I have umpteen choices available to me. Yet another new toolkit is not the answer, since it too would likely get bogged down with the same details, and if it didn’t have good bindings to a lot of languages might end up like shoes, which is bound to its own custom VM.
I think, then, I have something that may begin to resemble a solution. Why not use a syntax that is much better at expressing the nature of a layout? Why not, in fact, use XForms (with some lightweight subset of CSS)? Then we just need scripts to convert the layout descriptions into the widget and positioning code for each different toolkit. Then the developer can wire up events using their favourite toolkit, regenerating the widget part of the code when changes are made to the UI.