Tuesday 24 June 2008

automatic widget binding for glade/gtk-builder and vala

I am an old delphi user. For delphi 1 I even wrote a multi-threader, and a form-inheritance mechanism.

I’m now playing with vala, but I miss the automatic class member definitions from Delphi, where items on a window would have fields automatically defined in the source, so I could refer to widgets directly.

With current vala demo’s I have to make calls to this.xml.get_widget("widget_name") and I can’t be doing with that.

I’ve written some xslt which will convert the glade file into a vala file and class, which should be a super-class to whatever vala class is going to implement the form and signal handlers.

At Nicolas Joseph suggestion (and help for providing a sample gtk builder file) I’ve converted this to gtkbuilder. Glade can still be used to design the UI, but libglade is no longer needed at runtime.

Any .glade file can be automatically converted to a gtkbuilder .ui file, and any .ui file can be converted to a .vala file, and they are converted as a group to .c and .h and then compiled.

Because the .vala file contains the gtkbuilder xml within it, the .glade files don’t need to be around at runtime.

When the subclass is instantiated the superclass constructor will instantiate the window from the glade xml, and fix up all the widget locations, so that the subclass can refer to this.widgets.name_entry and so forth.

demo.glade


A sample "hello world" glade file with a button, and a label, and event handlers on button click and window close.

demo.ui


demo.ui is a gtkbuilder format built automatically from demo.glade IF demo.vala is listed as one of the vala sources.

demo.vala


When xsltproc –nodtdattr gen-vala-gltk-widget-bindings.xslt is invoked it generates the vala file, with the xml embedded. The main class name is taken from the top level widget identifier.
It’s widgets protected class has a member defined for each of the widgets.
Such code as:
this.widgets.label2.label=’Hello’;
can be used to affect the UI.

mainwindow.vala


The human subclasses the automatically generated class (named after the top level widget) in demo.vala, in order to implement signal handlers, and can still access widgets with:
this.widgets.label2.label=’Hello’;

Makefile.am


I also had to make changes to Makefile.am (generated vala-gen-project) to add the reciples for building .vala files from .ui files from .glade files.

To add a new auto-built source based on window.glade, you must add the window.glade file to the project_GLADESOURCES definition and window.vala to project_VALASOURCES

gen-vala-gtk-widget-bindings.xslt


This converts gtkbuilder files to vala files with the original xml as a string constant.

widget-bindings-0.1.0.tar.gz


Here is a sample project. I use it with anjuta and it mostly works, but I edit Makefile.am manually when I add new source files cos anjuta gets anxious about adding certain filetypes to certain targets if it doesn’t know about. them