Rapid GNOME Development with Mono

How to get started with GNOME monkeyshines using the open-source .NET system Mono.

Mono is an open-source implementation of the .NET development platform, a powerful and now open development platform. Mono contains a number of components: a Common Language Infrastructure (CLI) virtual machine, a C# compiler and a set of class libraries. Mono implements the C# language and runtime environment according to ECMA standards 334 and 335, respectively.

Mono—which is the word for monkey in Spanish—provides various class libraries, including an open-source implementation of the .NET Framework SDK. In this article, however, we discuss one of Mono's brightest assets: its GNOME support, in the form of Gtk#.

Gtk# is a .NET language binding for the Gtk+ toolkit and various other GNOME libraries. More than a simple wrapper, Gtk# provides a powerful platform for developing GUI software in the GNOME environment. Gtk#'s language bindings utilize good object-oriented principles and C#-style design to make GNOME development easy and natural, yet flexible and powerful.

In this article, we investigate the construction of a simple C# application, starting with a trivial “Hello, World” application and building it into a basic Wikipedia search tool. Our only dependencies will be Mono and Gtk#. Packages are available for most distributions—see the on-line Resources.

Hello, World!

Let's start by constructing the most basic Mono application possible, which prints “Hello, World!” to the console:

using System;

class first {
    public static void Main (string[] args)
    {
        Console.WriteLine ("Hello, World!");
    }
}

Fire up your favorite editor, enter this code and save it as first.cs. We can then compile the program into an executable image with the following:

$ mcs first.cs

Finally, we can run it via the following command:

$ mono first.exe
Hello, World!

This application implements the first class. Every application needs an entry point, an initial function inside of the class for the Mono runtime to jump to and begin the program's execution. As with C and C++, this is the Main function. The prototype of this function is:

public static void Main (string[] args)

In our program's Main, we invoke a single function, WriteLine, which is found inside the Console class. This function, similar to printf(), writes a line of text to the console. It can be used to output the values of variables too:

int x = 5;
String s = "wolf";

Console.WriteLine ("x={0} s={1}", x, s);

This gives us:

x=5 s=wolf

Hello, World! in Color

We do not, however, have to confine our “Hello, World!” to the console; with Gtk#, we can build a trivial GUI dialog to hoist our message onto the world:

using System;
using Gtk;

class Two {
    static void WindowDelete (object o, DeleteEventArgs args)
    {
        Application.Quit ();
    }

    static void InitGui ()
    {
        Window w = new Window ("My Window");

        HBox h = new HBox ();
        h.BorderWidth = 6;
        h.Spacing = 6;
        w.Add (h);

        VBox v = new VBox ();
        v.Spacing = 6;
        h.PackStart (v, false, false, 0);

        Label l = new Label ("Hello, World!");
        l.Xalign = 0;
        v.PackStart (l, true, true, 0);

        w.DeleteEvent += WindowDelete;
        w.ShowAll ();
    }

    public static void Main (string[] args)
    {
        Application.Init ();
        InitGui ();
        Application.Run ();
    }
}

As before, enter the code via your favorite editor. This time, save it as two.cs. To compile this program, we need to tell the Mono compiler that we want to use the Gtk# assembly:

$ mcs two.cs -pkg:gtk-sharp

Running it, however, is the same:

$ mono two.exe

The application creates a small window, titled My Window, and writes “Hello, World!” into the window (Figure 1). The window is a GtkWindow, the label a GtkLabel. Gtk lays out windows via boxes. Boxes are invisible widgets—existing solely for the purpose of layout—into which other widgets are packed. The arrangement of widgets within a box determines the physical layout of the widgets within the window. Although it is possible in Gtk to arrange widgets using tables, most programmers prefer boxes for their flexibility and power—plus, once you get the hang of them, they are not difficult to use.

Figure 1. My Window

Gtk provides two types of boxes: vertical and horizontal. A vertical box, called a vbox, defines the vertical arrangement of widgets—vboxes arrange widgets into columns. A horizontal box, known as an hbox, defines the horizontal arrangement of widgets, by arranging them into rows. Widgets are packed into boxes, boxes are packed into other boxes, and the boxes are added to windows.

A new hbox is created via:

HBox h = new HBox ();

And a new vbox is created via:

VBox v = new VBox ();

The new objects representing the boxes have various properties that one can set to manipulate the look and feel of the box. In our previous example, we set two properties on the hbox:

h.BorderWidth = 6;
h.Spacing = 6;

Here, we set the border of and the spacing around the hbox to six pixels each. This provides a net spacing of 12 pixels around the hbox. Coincidentally, for purposes of aesthetics and consistency, the GNOME HIG (Human Interface Guideline) dictates a minimum spacing of 12 pixels between widgets—thus the six and six pixels in this example are perfect.

To add a box to a window, the Add() member function is called on the window in question and provided to the box:

w.Add (h);

To pack a widget into a box, the PackStart() member function is called on the box in question:

public void PackStart (Widget child,
            bool expand,
            bool fill,
            uint padding)

In our example, we did:

v.PackStart (l, true, true, 0);

This call packs our label into our vbox. If the expand parameter is true, the widget child expands to fill all available space within the box. If the fill parameter is true, the widget consumes all of its space for rendering; otherwise, if false, the widget uses superfluous space for padding. The padding parameter allows for the addition of extra spacing around the widget, within the box, beyond any padding already provided.

Starting our application is simple. We perform three simple steps:

Application.Init ();
InitGui ();
Application.Run ();

Application.Init() initializes Gtk# and the application's GUI. It should be one of the first functions that a Gtk# application invokes. After executing this function, applications set up their GUI, create and arrange their widgets, and draw the initial windows and other UI elements. In our program, we do this in the InitGui() function. Once everything is complete and ready to roll, the program calls Application.Run() and the race is off. Our main window pops up because we exposed it, back in InitGui(), via:

w.ShowAll ();

______________________

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Mono IDE

DanielDevine's picture

Nowadays you don't have to worry about coding your GTK interface! :)

Monodevelop is the official IDE of Mono. It is an IDE just like MS Visual Studio/VB Express... Drag your widgets onto a window, assign them signals and the IDE automatically puts the interface code into your project. Just fill in the blanks with your code and you have a GTK program!

Small addition

Caleb's picture

Thanks for the article. More than that, thanks for you work on other projects (especially NetworkManager).

The Wikipedia sample application doesn't allow for spaces in the text box, I added the following just before the Gnome.Url.Show(s) call:

s = s.Replace(' ', '+');

Lovely article!

totoro's picture

Dear Robert, thanks for yet another lovely article!

I'm reading your book, "Linux Kernel Development" these days as well, and it is an absolute pleasure to read.

Webinar
One Click, Universal Protection: Implementing Centralized Security Policies on Linux Systems

As Linux continues to play an ever increasing role in corporate data centers and institutions, ensuring the integrity and protection of these systems must be a priority. With 60% of the world's websites and an increasing share of organization's mission-critical workloads running on Linux, failing to stop malware and other advanced threats on Linux can increasingly impact an organization's reputation and bottom line.

Learn More

Sponsored by Bit9

Webinar
Linux Backup and Recovery Webinar

Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.

In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.

Learn More

Sponsored by Storix