Composite templates lands in Vala

This is another journal entry relating to the composite template saga. It’s been a little over a month now since Openismus was kind enough to sponsor my work on embedding of GtkBuilder xml directly into GtkWidget class data, allowing the automation of composite widget classes.

As of recently, composite template support has been merged into Vala master. This Vala improvement was brought to you by Luca Bruno, so if you find yourself saving a lot of time in your daily Vala development practice, please be encouraged to transfer at least part of these savings into Luca Bruno’s personal beer fund.

This is really exciting for me because this integration in high level languages is really what I’ve had in mind while working towards this goal. Of course, the developer experience would be greatly improved by IDE tools which use Glade’s core and additionally have knowledge of Vala syntax and provide some glue features to help automate these associations (having both Glade’s core and Vala’s parser and object structures in the same memory space would allow some awesome integration features)… at any rate, this is still a major milestone on the road to a bleeding edge developer experience.

From now on your UI developer experience should look like this

The new Vala constructs allowing one to integrate with GtkBuilder files and create composite widgets in Vala are documented here.

Using the Vala compiler in GNOME git master today, it is possible to compile this full demo.

And here is just a sample from that demo:

using Gtk;

[GtkTemplate (ui = "/org/foo/my/mywidget.ui")]
public class MyWidget : Box {
        public string text {
                get { return entry.text; }
                set { entry.text = value; }
        }

        [GtkChild]
        private Entry entry;

        public MyWidget (string text) {
                this.text = text;
        }

        [GtkCallback]
        private void button_clicked (Button button) {
                print ("The button was clicked with entry text: %s\n", entry.text);
        }

        [GtkCallback]
        private void entry_changed (Button button) {
                print ("The entry text changed: %s\n", entry.text);

                notify_property ("text");
        }
}

The above is basically what an example composite widget looks like in Vala code. Notice that there are three attributes which can be used to bind your class to a GtkBuilder xml file.

  • GtkTemplate: This attribute tells the compiler to bind your class with the specified .ui resource, it is up to you to ensure that the specified resource is compiled into your program (using GResource).
  • GtkChild: This indicates that the instance variable refers to an object defined in the template GtkBuilder xml
  • GtkCallback: This defines one of your object class methods as a callback suitable to be referred to in the GtkBuilder xml in <signal> statements. If a class method is defined as a [GtkCallback], then you can simply specify the method name as a handler in Glade’s signal editor and your method will be called in response to the signal emission defined in the GtkBuilder file.

A small challenge

Over recent years, we’ve been hearing various stories about what GNOME should ‘choose for an official binding’, my money has always been on Vala. This is not because I know how to write code in vala, it’s not because I feel comfortable with vala or anything of the sort.

My reasoning is simple:

  • Vala is a formalism that we control, since it is based on GObject it’s the most valid candidate to deliver the features which are specific to our platform in a comfortable way. Examples of this are the implied syntaxes which Vala provides to connect callbacks to GSignals, built-in language features for using asynchronous callbacks from GIO, and now, my favourite addition is of course the [GtkTemplate] syntax.
  • A programming language is a window into a feature set available in a given platform. It took me all of 2 days to learn Objective-C and after doing so it makes perfect sense that one would choose Objective-C with it’s platform specific feature set to integrate with the NextStep environment, because hey, that’s what it was created for (so why try to use basic C code, or Java to integrate with the NextStep environment if a customized Objective-C variant was explicitly created to make your developer experience richer for that platform ?)

So the challenge is this: Prove me wrong.

Do you have another favourite language binding for GNOME ?

If so, can you please extend your language’s formalism to define composite widget classes ?

Whether this is really a challenge or not is yet to be seen, I’m really curious ;-)

 

24 Responses to “Composite templates lands in Vala”

  1. Gil Forcada says:

    Not to prove you wrong, but didn’t GNOME decide on Javascript (gjs) to be “the programming language”?

    (Note that I do like a lot Vala though)

  2. tvb says:

    @Gil

    Yes indeed. What I’m mostly curious about is, can GNOME Javascript developers provide integration features as rich as Vala can ?

    If so, it might be enough to sell me on JS being the right choice, then again, if you add syntactic sugar and GNOME platform specific keywords to JS, it wont be JS anymore will it ?

    So all around I’m very curious about where we are headed, my priority is not to have one language “beat” the other language, but only to have formalisms with good quality access to the GNOME platform’s feature set, if this is possible with JS as well as with Vala, then that’s really all the better.

  3. I can’t prove you wrong, but I support the decision of *not* choosing Vala as the official binding language. It’s not because of any faults in the language itself (which I don’t like, but this is irrelevant), but because of its popularity. Sure, your arguments make a lot of sense, however if I understood it correctly the “official binding” goal is to promote a certain language to third party applications writers: if you are a developer already familiar with GNOME development, the decision shouldn’t impact you at all: you can continue to write applications in C, Python, Vala and what not. What the “official bindings” decision affects is mostly third party developers new to GNOME; and for them, I think that providing a language already familiar to them can help to get them port/write their applications to GNOME. Having to learn both the GNOME libraries and a new programming language would probably be too much of an effort.

    Under this light, I think that the choice of a popular language like Javascript (or Python) was a sound one.

  4. tvb says:

    @Alberto:

    “I think that providing a language already familiar to them can help to get them port/write their applications to GNOME. Having to learn both the GNOME libraries and a new programming language would probably be too much of an effort.”

    Well, we’ll probably have to agree to disagree on that front.

    The same could really be said about Obj-C and Cocoa/Iphone, and it’s *damn* easy to learn those high level semantics to integrate with NextStep/Cocoa.

    The interesting question here is, is it more difficult to learn GAsyncCallback, GSignal and
    GtkWidget template features etc. with another formalism (one which you are already familiar with) or is it easier to just learn a new formalism with those features built into the language ?

    Anyway, as time goes by we will see what is chosen by more developers, and what is more powerful to use with the GNOME stack. However it would have been nice to promote something which has more potential to leverage our specific feature set from the get go. It would have helped to build more momentum in developing a more powerful programming environment for our platform in the long run, and that big picture is much more interesting to me, but perhaps we don’t all share that vision.

  5. Another Tristan says:

    Add me to the list of people who disagree with Gnome’s decision to bless JS ahead of Vala.

    I can understand the reasoning — JavaScript is where it’s at right now — but it’s not true to say that if you go with Vala, you need to learn a new language. If you’ve ever used Java, C# or C++ — and that covers an awful lot of people, including everyone who’s ever worked on an Android app — then you’ll instantly understand 95% of Vala’s syntax; the rest is learning about GObject’s slightly unusual construction mechanics, and learning to use signals and callbacks rather than event listeners or what-have-you — things you’d have to learn to use Gnome libraries via JS *anyway*, and without the helpful syntactic sugar that Vala gives you. There are even a couple of excellent “quick start” guides to Vala on the Gnome wiki for people coming from the Java and C# worlds.

    Vala has much more in common with mainstream (C++-derived) programming languages than Objective-C does, and there seem to be plenty of people who don’t have a problem learning that (even before the iPhone boom).

  6. bersace says:

    Hi,

    I also do love Vala and it should be e first-class citizen in GNOME plateform. However, i understand the choice of e script language.

    I think the real dilemna is between python and JS. And clearly, JS is a more versatile language to promote one plateform.

    Anyway, keep up the good work on Vala, i wish it to be along JS in GNOME IDE :-)

    Regards,

  7. tvb says:

    OK EVERYONE !

    Hahaha… I can see this might be turning into one of those JS vs Other ‘selected as official’ language for GNOME discussions… while I appreciate a good debate, I just want to highlight this is *not* my intention.

    I threw this challenge out there for the other bindings authors, I would really like to see JS, Python and other languages adopt the composite template features… hopefully in a way that does not look like a total hack (i.e. without inserting gross coding constructs into exposed GtkWidget class initializers).

    I would like to see it happen, I think this is plausible for Python, I’m not convinced it can be done elegantly for JS without modifying the JS formalism… in any case, I’d just like to see it happen ;-)

    So I threw the ‘challenge’ out there, now Vala has some pretty nice support, can you beat it in your favourite binding ?

    Here are some hints at where you can start:

    A.) Vala still needs work to improve type safety in signal callback signature type matching (as well as instance variable binding type safety)

    B.) It would be nice to not mention the name of the .ui file at all, can your compiler pull in a FooButton.ui into your FooButton.js automatically, for a FooButton which is defined as a template button in JS ? if the FooButton.ui is found in the same directory at compile time ?

    Be creative, how can we make the experience better than it already is ?

    Anyone up to the challenge ?

  8. Jon Nordby says:

    Nice!
    For Python, class decorators could be used for GtkTemplate case by replacing the __init__ with one that instantiates the template and assigns it to self.ui, then calls the original __init__.
    GtkCallback through a function decorator, introspecting the original func.__name__ to hook up the signals.
    Not sure if such a nice syntax is cleanly possible for GtkChild, there are no decorators for member instances and no nice ways to avoid passing self explicitly…

    @GtkChild
    @property
    def entry(self):
    pass # GtkChild decorator would do the actual work

    @property
    def entry(self):
    self.ui.get_child(“entry”)

    I would prefer the latter.

    Nice thing with Python is that one could implement this oneself without having to change the language/runtime.

    Open questions are (beyond proof-of-concept code, sorry…):
    - How obvious are user errors of these mechanisms when they occur
    - How can IDEs can bring further integration

  9. Kris Thomsen says:

    One thing I REALLY want to see in GNOME development / IDE is advanced IntelliSense-like features – this is fantastic for learning a language imho. And make it really easy to compile and test the application from the IDE.

    I think GNOME should focus on JS, Vala and Python – three languages that would complement each other well and really get a quite huge audience.

  10. Jim Nelson says:

    I think the strongest defense of Vala I’ve seen in the JS/Python/Vala official-language debate is yours, Tristan: “Vala is a formalism that we control”.

    The learning curve for Vala is incredibly flat. We’ve had college interns come in to Yorba with zero Vala experience landing quality patches in under three days.

    Here’s a language that is hand-crafted for GObject, is integrated with core GNOME technologies (D-Bus, gir, and now Glade), and can be integrated with future core technologies with little fuss. It can be used to create C-based libraries and easily binds to the same. Libraries written in JS or Python are pretty much only useful for those languages, whereas Vala can produce libraries usable by any language that can bind to C — which is pretty much every language out there.

    I would’ve thought Vala a no-brainer to be GNOME’s official language.

  11. eric-yorba says:

    The biggest problem with Vala is how few tools there are that support it. That’s more of a chicken-and-egg issue than any fault of the language, so it’s great to see Glade taking a step towards tighter integration.

  12. guy says:

    I like it. I always hated to deal with glade files the traditional way. I’m looking forward to use it.

  13. tvb says:

    @Jon Nordby:

    Hi !

    Yes I did have python in mind… I don’t have in depth knowledge of python’s implementation but as I understand it does at least register GTypes in the type system (which means all of the relevant gtk_widget_class_*() apis can be used on dynamically registered GTypes in python).

    Some things I made sure of, was that you have an API to easily fetch the children defined as automated children (that name might change, but essentially the [GtkChild] equivalent). This should allow the said [GtkChild] type of semantic to work with dynamic scripting languages (you can use this API once at instance initialization after calling gtk_widget_init_template(), or even every time that the variable’s value is referenced, at the cost of a hash table lookup).

    Also there is an API to set the GtkBuilderConnectFunc used to connect signals, which should be enough to provide the glue code needed to envoke python class methods in response to signal callbacks.

  14. shkn says:

    Nice!
    This is a beutiful new feature for vala.
    Thanks!

  15. Luca Bruno says:

    Now we got type safe callbacks and children connection in Vala landed in git master. The requirement is to pass –gresources file.xml to valac in order to inspect the ui files.
    There’s an up-to-date example of composite-demo-vala here: https://dl.dropboxusercontent.com/u/89525595/composite-demo-vala.tgz .
    Have fun :-)

  16. Yann-I says:

    at compile :

    mywidget.vala:4.1-4.27: error: UI resource not found: `/org/foo/my/mywidget.ui’. Please make sure to specify the proper GResources xml files with –gresources.
    I must have missed something

  17. tvb says:

    @Yann-I

    That has changed in recent Vala, see Luca’s comment ;-)

    Sorry I didn’t get around to moderating last couple days, hope you did not have too much trouble

  18. chavaone says:

    at compile:

    mywidget.c:(.text+0x49a): undefined reference to `gtk_widget_init_template’

    Here is the full output http://pastebin.com/S9AbMq6X. Do you know what I’m doing wrong?? :S

  19. tvb says:

    @chavaone: It looks like you need a more recent version of GTK+

    This feature is new in both Vala and GTK+.

    In GTK+ it should be there since around 3.9.1

  20. raha says:

    I love Vala, I am a .Net C# Developer and the first time I saw Vala I fell in love with it. I think the important thing for Vala lovers is to make Vala more accessible to other platforms such as creating assemblies for Windows and OSX, I am sure by doing that more people will be willing to learn and use this platform.

  21. Yann-I says:

    valac 0.22 & Gtk 3.9.12, this feature doesn’t work anymore :( ?!

  22. Yann-I says:

    requires glib >= 2.38, but the last is 2.37.6

  23. tvb says:

    Hi Yann-I,

    A couple weeks there were some final touch ups to the API in GTK+, some minor renames as well as adaptation to the new G_PRIVATE_OFFSET scheme for private data in GObject.

    Note that you should not technically need 2.38, the required new APIs for private data offsets are a part of the 2.38 API but those APIs are introduced in glib master (I am running 2.37.6 and I can compile just fine, without any warnings or errors).

  24. Yann-I says:

    thank you, it now works