/// Thursday, November 10

Use XSLT Transformations to Ease Glade#


This article describes how to use the XslCodeBuilder to simplify cross-platform Gtk# application development.


In a previous article, I described the implementation of XslCodeBuilder to inject code generated by an XSLT transformation. In this article we'll apply XslCodeBuilder to ease Gtk# development.

There are at least two ways to build a Gtk# application. The first is to use the Gtk# library as is, manually creating widgets and compose them in a hierarchy to build your GUI. The easier way is to use the Glade# library. Draw your GUI using the Glade 2 utility then save the project creating XML metadata in a .glade file. The .glade file is loaded by the glade-sharp library to render your GUI.

Glade development is summed up in these steps:

  1. Draw your GUI - use the glade utility to generate a .glade file
  2. Declare variables for widgets - each widget in a .glade file has a unique id
  3. Set event handlers - each widget has a set of 'signals' or events
  4. Load the .glade file and run

The rest of the article describes the use of XslCodeBuilder to semi-automate these steps.

XslCodeBuilder and the Glade stylesheet

A .glade file is simply an XML file. It's simple enough to create a stylesheet to generate Boo code to perform the steps described above:

01 <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
02  <xsl:output method="text" />
03  <xsl:template match="/">
04      <xsl:apply-templates  select="glade-interface/widget[1]"/>
05      def RunGlade():
06              RunGlade(null)
07      end
09      def RunGlade(init as callable):
10          Application.Init()
11          gxml = Glade.XML("view.glade", "window1", null)
12          gxml.Autoconnect(self)
14          if init != null:
15              init()
16          end
18          Application.Run()
19      end
20  </xsl:template>
22  <!-- build variables -->
23  <xsl:template match="widget">
24      [Widget]
25      <xsl:value-of select="@id"/> as <xsl:value-of select="substring(@class, 4)"/>
26      <xsl:apply-templates select="child/widget" />
27  </xsl:template>
28 </xsl:stylesheet>

Line 03 is the entry point into the stylesheet. The apply-templates statement starts a recursive descent into the XML file invoking any template that matches the current XML node. In this example, there is a template defined for match="widget". The template emits a declaration like this:

id as widgetClass

After all the widgets are found, processing continues at line 05 which emits overloaded methods of RunGlade(). The XSL-savvy will realize this stylesheet only acts on the first widget from the root and all its children. This is just a sample stylesheet. In all honesty I'm a Glade# NoOB. I need a better understanding of Glade to create a robust stylesheet.

Anyway, here is the source of a basic Glade# application using XslCodeBuilder and the stylesheet:

import Gtk from "gtk-sharp"
import Glade from "glade-sharp"
import MGutz.CodeInjection from "MGutz.CodeInjection"

[InjectCode(XslCodeBuilder, "view.glade;glade.xsl")]
public class GladeView:
    def Run():

InjectCode generates this code and stores it in a file so you can step through it in the debugger if needed:

    window1 as Window
    vbox1 as VBox
    toolbar1 as Toolbar
    openButton as ToolButton
    quitButton as ToolButton
    scrolledwindow1 as ScrolledWindow
    textview1 as TextView

    def RunGlade():

    def RunGlade(init as callable):
        gxml = Glade.XML("view.glade", "window1", null)

        if init != null:


Create and compile a simple controller then run it:

o = GladeView()

If you click on either button nothing will happen. We need to hook events and display a FileChooserDialog when the Open button is clicked.

[InjectCode(XslCodeBuilder, "view.glade;glade.xsl")]
public class GladeView:
    def Run():

    def Init():
        quitButton.Clicked += OnQuitButtonClicked
        openButton.Clicked += OnOpenButtonClicked

    def OnQuitButtonClicked():

    def OnOpenButtonClicked():
        fcd = FileChooserDialog(Title: "Select File")
        fcd.AddButton("OK", ResponseType.Accept)
        fcd.AddButton("Cancel", ResponseType.Cancel)
            response = cast(ResponseType, fcd.Run())
            if (response == ResponseType.Accept):
                file = fcd.Filename
                using reader = StreamReader(file):

The overloaded RunGlade(callable) is used to set event handlers. The handlers are self-explanatory. Run the controller, then click open

File loaded


I've shown how to use XslCodeBuilder to transform Glade's XML metadata to inject Boo code into a class.

Glade masters are probably thinking this doesn't save much time. I agree somewhat. The point is it does save time. When partial classes are merged into Boo event handlers can be autogenerated into a partial file to survive round-trips between regeneration. I didn't attempt to do that in this example as it's bad kharma to modify the source of the decorated class.


Great! Thanks for your work...

Do you realize that you're quite near to implement a compiled XML general class instantiator รก la MyXaml?

Please, compare your work with this article.
Post a Comment

<< Home

This page is powered by Blogger. Isn't yours?