4 Hugues Ross - Blog: DFGame: Glade-ing Along to Victory
Hugues Ross

10/15/17

DFGame: Glade-ing Along to Victory

I planned to take a break from DFGame, but I happened to be in the mood to play around with the editor module. I ran into some issues while working on a new demo, and ended up having to do a few hours of research to get things working. Then I thought to myself: "Gee, someone else is bound to have this problem. Maybe I should write about it!"

What's New?

Sometime last year, I learned how about this cool feature in Vala, and started using the Glade UI editor with my software projects. However, it was only recently that I learned about a way to add custom widgets (such as DFGame's editor widgets) to Glade for graphical editing. Naturally, I had to give this a shot for the new and improved DFGame!

Let's discuss what went wrong, and how I solved these problems.

Problem 1: Nothing Happens?

It took quite a while for me to actually get any new UI elements to appear in Glade. There were a couple issues that caused this, primarily thanks to the documentation being rather vague about about how templates work... at least until you notice the tiny "next" button. Let's look at the example widget catalog that the documentation shows:

<glade-catalog name="foo" library="foo" depends="gtk+">
  <init-function>my_catalog_init</init-function>

  <glade-widget-classes>
    <glade-widget-class name="FooFrobnicator" generic-name="frobnicator" title="Frobnicator"/>

    ... widget classes go here
  </glade-widget-classes>

  <glade-widget-group name="foo" title="Foo">
    <glade-widget-class-ref name="FooFrobnicator"/>
    ... widget class references go here
  </glade-widget-group>

  ... widget groups go here
</glade-catalog>
(Borrowed from this page)

The difference between "name", "generic-name", and "title" isn't immediately obvious. If you look at a later page, there is an explanation:
  • "name" is the name of the widget's class in code. It also seems to be used for class references in widget groups later in the file
  • "generic-name" is used internally, I guess? Still not 100% sure on that one
  • "title" is what the user will actually see in Glade
Unfortunately, this still wasn't enough because there remained an underlying problem to address: I write my Gtk code in Vala, but Glade only cares about GObject C. For the unacquainted, Vala acts as a wrapper language of sorts, and gets converted to GObject C for compilation. This means that there are two more things to adjust:

First of all, the class names are different. C lacks namespaces, so in order to provide them Vala adds each namespace onto every class that you create. In my case, this meant changing "Viewport" to DFGameViewport.

Next, there's a less obvious issue. Vala generates something referred to as a "get type function" which does something? I assume it either returns something that represents the object's type, or it returns an instance, but I don't have enough experience with GObject to know for certain. Glade overrides this function to create placeholders, but it apparently guesses the function name based on the "name" value that's passed in. In my case, I had to pass in the function name explicitly in order to make the catalog work. This is probably just a quirk in Vala's naming conventions, I suppose.

Once that was out of the way, Glade finally displayed my new viewport widget for DFGame and all was well, right?

Problem 2: Nope, That Doesn't Exist

As any seasoned programmer will tell you, life is never simple.
The fixes above were enough to let me create the UI for a new demo, but once the time came to actually test it out the UI wouldn't load! Instead, I was left with a cryptic message:

"(demo_editor:24355): Gtk-CRITICAL **: Error building template class 'MainWindow' for an instance of type 'MainWindow': .:3:4733 Invalid type function 'df_game_viewport_get_type'"

...???????!!?!??!??!?!!!??!!?!
The class was there. I could see it in the code. The library was definitely getting linked. So why then did it fail? Given a good couple hours, I was unable to answer this question. Luckily, the internet came through for me. All I had to do was slip in a single line of code at the start of the program
typeof(Viewport).ensure();
...and that was enough.

Takeaways

 This little experience further cements my thoughts regarding Gtk and many GNOME technologies, and I thought I'd discuss that briefly before as this post wraps up.

I like working with Gtk, Vala, and so on, but I think many of these technologies share the same problem. At the same time as GNOME works to streamline the design of its software and simplify things for normal users and new devs, there's this weird dropoff point where most docs past the beginner tutorials assume that you understand the technology stack and just need a quick reference.

The result is (presumably) "intermediate" devs like myself getting lost and confused after their gentle start suddenly drops out from under them. Thankfully, I ran into most of those issues a couple years ago, but occurrences like this one remind me that they still exist.

So I guess today's lesson is...maybe I should try writing a couple mid-level Vala/Gtk tutorials? Maybe GNOME needs more acknowledgement of their newer users and non-C APIs? Beats me.

No comments: