Glade - Rapid Application Development with Gnome 2

by Johannes Roith (johannes@jroith.de)

Introduction

In the previous chapter, you learned how create a Gnome GUI. If you've worked with Visual Studio, Delphi/Kylix or Visual Basic you might be missing the easy way of dragging widgets on forms.

You're right, after all, what we want to do is creating good applications faster with mono. Development , where the programmer gets assistance in non-coding tasks from (visual) tools and focuses on the real work is called RAD - Rapid Application Development. Gnome offers a set of such technologies, known as Glade.

Glade consists of 2 part:
That means, the user will need have libglade installed, and the xml file must be distributed with the application. Glade# is the C# binding for libglade and even offers some advanced features - like self-contained glade files - that are only available in Gtk#.

Language independence has always been a goal in Gnome Development. For that reason the Glade Interface Builder exports xml, that can be used with any language with glade bindings. This benefit is bought with little more effort compared to Visual Studio, as the code can't be generated automatically.

Creating the UI

Before we try to use glade with our Project, first get some experience with it. Fire up the Glade Interface Designer. You will be greeted by three windows: the main window, a properites and a palette window, containing icons. Click Project - New and select "Gnome Project".

To create a new window click on the first icon in the palette-window. The new window is shown in the list. You can modify Type, Position, Caption, and other things in the Properties window.

If you want your application to quit, if the window is closed you'll have to connect a signal with an event handler. Select "Signals" and add a handler for "delete_event" and call it "OnWindowDeleteEvent".

Take a button and drop it on the window. As you know, gtk+ has the concept of invisible boxes, to position widgets, and for that reason the button will fill the whole window. Modify some properties and add a signal handler for "clicked" and call it "OnButton1Clicked".

Save to a new directory. Glade will put 2 files there: [projectname].glade and [projectname].gladep, wich does only save some information for the Interface Builder. The "interesting" file is the .glade file, that you can open in any text editor. It's plain XML and looks like that:


<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">

<glade-interface>

<widget class="GtkWindow" id="window2">
  <property name="visible">True</property>
  <property name="title" translatable="yes">window2</property>
  <property name="type">GTK_WINDOW_TOPLEVEL</property>
  <property name="window_position">GTK_WIN_POS_NONE</property>
  <property name="modal">False</property>
  <property name="resizable">True</property>
  <property name="destroy_with_parent">False</property>

  <child>
    <widget class="GtkButton" id="button1">
      <property name="border_width">10</property>
      <property name="visible">True</property>
      <property name="can_focus">True</property>
      <property name="label" translatable="yes">button1</property>
      <property name="use_underline">True</property>
      <property name="relief">GTK_RELIEF_NORMAL</property>
    </widget>
  </child>
</widget>

</glade-interface>

It's time to start coding

The code is similiar to previous chapters. What has changed is, that most of the code is move to the GladeTest constructor. That's because the main-method is static and therefor doesn't belong to any class. Altough possible, moving code to Main() would only lead to more complicated code.
namespace GladeSamples {
  using System;
  
  using Gtk;
  using Gnome;
  using Glade;
  using GtkSharp;

  public class GladeTest
  {

    public static void Main (string[] args)
    {
      new GladeTest(args);
    }
    public GladeTest (string[] args) 
    {

      Application.Init();

      /* This loads the glade file glade.glade, selects window2 and connects it to the current object,
       *  which is the class GladeTest here. */
 
      Glade.XML gxml = new Glade.XML ("file.glade", "window2", null);
      gxml.Autoconnect (this);

      Application.Run();

      /* If you want to access the glade objects you have to "import" them.
       * This is not required, but else you can only work with the pre-defined signal handlers */

      Button button1 = (Gtk.Button) gxml["button1"];

      button1.BorderWidth=10;

          }


    /* Connect the Signals defined in Glade */


    public void OnWindowDeleteEvent (object o, DeleteEventArgs args) 
    {
      Application.Quit ();
      args.RetVal = true;
    }
    
    public void OnButton1Clicked (System.Object obj, EventArgs e) 
    {
      Console.WriteLine ("Button 1 clicked");
    }

  }
}

compile with:
mcs /unsafe -r gtk-sharp.dll -r glade-sharp.dll glade.cs

Of course, include the Gnome and Glade namespaces.
using Gnome;
using Glade;
The first part inits the Application.
Then the glade xml file is connected. The first param is the file, the second the main widget (here: the window). The second line connects gxml to the current object.
Glade.XML gxml = new Glade.XML ("file.glade", "window2", null);
gxml.Autoconnect (this);
Altough glade will show all widgets and cares about the events defined, most likely you will want to change properties, or add events during the runtime. For that to work you have to connect a new object to the glade widget. This example also sets the BorderWidth.
Button button1 = (Gtk.Button) gxml["button1"];
button1.BorderWidth=10;
That's it.

Available Widgets

All available widgets are devided in 4 categories. If you want your application to be independent of gnome and portable to windows, or Mac OS X, use only Gtk+ and Gtk+ Additional. If you don't need that flexibility I strongly encourage you to make also use of the Gnome category. That includes Font-Selector, Druids, Iconlists and other useful things.

Glade can be extened, for example gnome-db extensions are available.

Using Glade in our Project

After explaining how it works, like in the other chapters we want to go on with our little Project, introducing the new learned technology and extending the knowledge. This chapter removes the few UI bits, done by hand and adds an Interface using Glade.

[TODO]

Didn't you say something about this self-contained thing?

Yes, I did. And it's quite a good feature. Now, that we're using Glade our application consists not only of 1, but 2 files. Luckily, the CLR has a way, to embedd any file in the executable, like images or text files. Glade offer an additional constructor to load the glade file from a resource, so you don't have to distribute it. The only difference is the "null" before the filename.
Glade.XML gxml = new Glade.XML (null, "file.glade", "window2", null);
gxml.Autoconnect (this);
You have then to compile the file in, with the resource switch.
mcs /unsafe /resource:glade.glade -r gtk-sharp.dll -r glade-sharp.dll  glade.cs