Loading Glade UI Confgiuration Files into Tcl/Gnocl Applications

WJG (26-Mar-09) One of the features added into Gnocl 0.9.94 is the import of Glade files and there are some experimental scripts in the present release to illustrate the power of using Glade files.

Glade is a Gnome developer application that allows for the visual creation of detailed UIs drawing upon the wide range of Gtk/Gnome widgets. The latest release of Glade [1 ] may even have support for other popular third-party widgets. The resulting layout is saved as an XML file and be easily loaded into a Tcl script using the gnocl::gladeXML command. At the moment this feature is still under development and much work needs to be done on settling upon a strategy on how to bind the UI signal callbacks to scripts on the Tcl side of the interpreter.

Whilst I personally have steered away from using visual UI builders and prefer the direct approach of scripting, for the vast majority of Gtk developers Glade is a 'wonder-tool'. Incorporating full support for both Glade and GtkBuilder would place Tcl in a good position in the Gtk bindings stakes as Gnocl would really come into its own, not merely as a UI builder, but enabling the runtime reconfiguration of widgets, which is complex using C.


tb 2009-03-26 - Me Too! I was thinking about just traversing the glade file using tdom and then returning some code containing a window creation procedure and some callback handler stubs.

Package example:

 namespace eval ::sysdlg::file {
   eval [::gnocl::tclFromGlade "filedlg.glade"]
 }
 package provide filedialog 0.1

Now, one could load the package, look up the callback handlers like...

  info proc ::sysdlg::file::handle*

...and start overwriting the stubs. Ready!

WJG (26-Mar-09) Yes, I've looked at tdom and found it more reliable. You see, if Tcl has conflicting object-orientation extensions, then Gtk has conflicting UI xml files. There's glade and builder. Both types can be valid XML (according to tdom), but not necessarily loadable (although matters might have eased since the near simultaneous release of new versions by both the Glade and Gtk development teams). But, for Gnocl to work well, we need access to widgets from their Tcl names and the ability to script the callback signals that libglade and GtkBuilder would not do for us. So, step in tdom. As you suggest, parsing the XML file and making assignments is quite straight forward. Here's a Glade snippet that relates to the addition of a button to an existing button bar:

 <widget class="GtkToolButton" id="add">
    <property name="visible">True</property>
    <property name="sensitive">False</property>
    <property name="label">Add Event</property>
    <property name="stock_id">gtk-add</property>
    <signal name="clicked" handler="on_add_clicked"/>
 </widget>

This would correspond the following line of Gnocl script:

 $toolBar add item \
   -visible 1 \
   -sensitive 1 \
   -text {Add Event} \
   -icon "%#Add" \
   -onClicked on_add_clicked

Straightforward, eh? As can be seen there are some option names that are more inspired by Tk than the GtkWidget properties to which they map. In fact, when they are at variance, there can be a lot more hidden than meets the eye. The %# prefix for the icon, for instance, tell us that it is a stock item from the current Gnome theme. This could equally be an image file stored on disk as supported by the GtkImage libraries. Some widgets, like the gnocl::text, gnocl::tree and gnocl::list widgets are in fact pretty well mature megawidgets that would produce some unusual effects if used in the way listed above. But, adding support in terms of new Gnocl library functionality for the instancing of new widgets, assigning properties and registering them with the interpreter should not be too problematic. It's the error checking that is the nightmare, but would be usually handled by Glade itself as any compiled C code application loading a glade file would not check the validity of the XML file either.

Maybe you're interested in taking this project further? XML gives me a headache, but I'd be only too delighted to co-operate with anyone who enjoys it.

tb - Hi, I did some investigation over the weekend. To me it seems a job of translating Gtk widget class names to Gnocl, while traversing the "child" tree of the glade file. There are lots of implications, like for example most properties with an underline character in their names don't exist in Gnocl. Though using rules and translation tables isn't the best way, because things might change over time, I don't see a real robust solution at the moment.

WJG (20-Mar-09) Thanks for taking a look at the issue. It's not as problematic as it would seem. Each one of the GtkProperties has a Gnocl C library routine associated with it order complete the wrapping process. A Tcl-side solution, of course, is always in the cards, and once the initial framework is in place most of the work would be quite straightforward, albeit laborious!

WJG (21-Nov-09) Returning to the comments made by tb above. Rather than parsing the glade file and building a gnocl script equivalent, I've followed the route of loading the glade file and registering the new widgets with the Tcl interpreter using existing gnocl library calls. To do this I've worked through the glade gui widget trees obtaining pointers, names, and widget types. During the registration process, the new widgets are supplied handlers, again from the existing libraries. This means, that once loaded, the various parameters can be set and modified using the established scripting method.


WJG (23-Nov-09) Put a little more time into the glade routines for gnocl this weekend. Previously, the gnocl libglade stubs just permitted the loading of the glade description file and returned/displayed the created toplevel windows. Now all the the widgets are registered with the interpreter itself and the creating command returns a list of all new widgets.

In terms of completing the project, all that now remains is completing the job of assigning handler functions to the widgets' types created by libglade.

Here's my new test script...

#---------------
# gladeXMLTest.tcl
#---------------
# William J Giddings
# 21-Nov-2009
#---------------

#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "[email protected]"

package require Gnocl

set win1 [gnocl::glade glade calculator.glade]
$win1 configure -title "Calculator Renamed!" -onDestroy {puts "Done!" ; exit}

gnocl::mainLoop

And the sample screengrab:

http://lh4.ggpht.com/_yaFgKvuZ36o/SwqGbOXRLyI/AAAAAAAAAKw/brqGSzFCucw/s800/Screenshot-Calculator%20Renamed%21.png

Keep watching this space... more to follow!

RLH That is most awesome!

WJG Thanks. I'm quite pleased with this one. Although I personally prefer scripting GUIs directly, I know that a lot of potential Gnocl users are waiting for a bridge between Tcl and Glade/Guibuilder. Looking at the library functions it might also be possible to 'dump' GUIs out to a glade file. This would be a useful development as it would enable GUIs built or prototyped in Gnocl to be reused in other applications. One feature that might also be useful is that selected 'parts' of a Glade-based GUI, e.g., a particular toolbar layout, can be picked out and selectively reused.

tb Amazing!!! - A big step towards rapid prototyping of Gnome apps. I'll definitely stay tuned :)


WJG (30/Nov/09) Well, the major structure for implementing glade files is in place, and now all that remains is to complete the lengthy task of writing the code to map/patch together glade objects with handler functions existing in the gnocl libraries. As another taste, here's the current test script to show how progress is moving along.

#---------------
# gladeXMLTest1.tcl
#---------------
# William J Giddings
# 30-Nov-2009
#---------------

#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "[email protected]"

package require Gnocl

# load a simple glade file, containing three buttons in a horizontal row
# the variable glade1_widgets contains a list of all widgets created
# by loading this file, they will include the names given in the glade file
# itself along with the names assigned when registering these with Tcl

set glade1 button1.glade
set glade1_widgets [gnocl::glade new $glade1]

# create a list of aliases for these new widgets 
# we can use the glade widget names to do this, to make things manageable
# when switching between Tcl and Glade

foreach item $glade1_widgets {
    foreach {gnocl glade} $item {}
    set $glade $gnocl
}

# in the glade file the toplevel window is named window1
# let us resize, rename and centre it on screen

$window1 configure -title "Glade Test" -width 320 -height 200
$window1 centre ;# or 'center' if you wish

# we can now access the widget attributes as these are registered with gnocl!
$button1 configure -icon "%#New" -onClicked { puts "NEW! from %w" }
$button2 configure -icon "%#Open" -onClicked { puts "Open! from %w" }
$button3 configure -icon "%#Save" -onClicked { puts "Save! from %w" }

# as there needs to be a container for these widgets we can get its name with
set box [$window1 cget -child]

# and, of course, add new widgets too!
$box add [gnocl::toggleButton -text "CLICK ME!"]

gnocl::mainLoop

After all this, our simple layout...

http://lh3.ggpht.com/_yaFgKvuZ36o/SxPzjxDI5EI/AAAAAAAAAK0/flz-pTuBTbU/s144/Screenshot-gladeXMLTest1.tcl_1.png

Becomes this...

http://lh3.ggpht.com/_yaFgKvuZ36o/SxPzj-NIPaI/AAAAAAAAAK4/5nj_Vr91BAM/s800/Screenshot-Glade%20Test.png

WJG (06/Dec/09) Support for button, statusbar, toolbar, text and menuing system now completed.