Gtk# in Xamarin Studio

This post is going to cover one of the less discussed project types in Xamarin Studio, the Gtk# project. Gtk# is a wrapper over the Gtk+. Gtk+, AKA GIMP Toolkit, is a library that can be used to create user interfaces. GTK+ has the following dependancies…

  • Glib – A general purpose library consisting of various data types, string utilities. It’s also home to error reporting, message logging, and threading.
  • Pango – This library allows for internationalization.
  • ATK – Accessibility Toolkit to aid physically challenged to work with computers
  • GDK – This library is a wrapper around the low level drawing and windowing functions.
  • GdkPixBuf – This library handles loading images and pixel buffer manipulation.
  • Cairo – This library is used for creating two-dimensional vector graphics.

Gtk# allows for the creation of awesome user interfaces with the C# language using Mono or other CLR language. Even Xamarin Studio and Monodevelop were created using GDK#!  Which means, that although unlikely, theoretically Xamarin Studio could be maintained by Xamarin Studio, which is some kind of crazy inception. To learn more about GTK# check out  the documentation http://docs.go-mono.com/ .

Let’s dive right in and create our first Gtk# program, a simple image viewer.

First, open Xamarin Studio, choose File -> New Solution. From the new Solution dialog, in the left column select C#. From the list of project types, choose Gtk# 2.0 Project. We’ll name our project and solution ImageViewer.

CreateProject

After you press OK, you’ll notice that Xamarin Studio has created quite a few things for you. If you look under the User Interface folder you’ll notice a file called MainWindow. Double clicking this file opens up the designer.

SS_3

If you look on the right side under toolbox, you will notice two main categories, widgets, and containers. In reality, they are all widgets, some are just container widgets, while others are non-container widgets.

SS_4

If you try and drag a non-container widget into the designer without having a container widget, Xamarin studio gives you the following error message.

SS_2

For this project, we’ll use a VBox container.

SS_5

SS_6

This creates three separate panels. We really only need two, so right click over one of the panels, and choose delete.

SS_7

Our application needs a menu bar, so lets choose the Menu Bar widget.

SS_8

You’ll notice that the menu bar snaps to the top of the window, and instructs you to ‘click to create menu’. We’ll follow the instructions and enter file. Next, we’ll add three ‘actions’ under the File menu item. These are Open, About, and Exit.

SS_9

In Gtk# Signals are like events in .Net land. To wire out Signal Handlers for each of our menu items, first select a menu item. Next, open the properties tab on the far right side, and choose Signals at the top. Under the Activated signal we’ll create OnOpen, OnAbout, and OnExit for the Open, About, and Exit menu items respectively.

Double click the MainWindow.cs file, and you’ll notice that Signal Event Handlers have been added. Let’s first handle the OnExit action, by quitting the application.

     protected void OnExit (object sender, EventArgs e)
     {
         Application.Quit ();
     }

If you were to build and run the application, and choose the Exit menu item, your application should now exit.

Let’s go back to our MainWindow User Interface file, and add an Image Widget by dragging and dropping it into the container. With the Image widget still selected choose the properties tab on the right side, and re-name the widget to displayImage.

SS_10

Add the following code to the OnOpen Signal handler in MainWindow.cs.

     protected void OnOpen (object sender, EventArgs e)
     {
         FileChooserDialog fileChooser = new FileChooserDialog ("Choose an Image to View", this, FileChooserAction.Open, "Cancel", ResponseType.Cancel, "Open", ResponseType.Accept);
         if (fileChooser.Run () == (int)ResponseType.Accept) {

             if(fileChooser.Filename.ToLower().EndsWith(".png") || 
                 fileChooser.Filename.ToLower().EndsWith(".gif") ||
                 fileChooser.Filename.ToLower().EndsWith(".jpg"))
                 {
                     //Dispose of Old PixBuf
                     if (displayImage != null && displayImage.Pixbuf != null)
                         displayImage.Pixbuf.Dispose ();

                     displayImage.Pixbuf = new Gdk.Pixbuf (fileChooser.Filename);
                 }
         }

         fileChooser.Destroy ();

     }

This code simply opens up a dialog that allows the user to choose a file, verifies that the file chosen has either a .png, .gif, or .jpg file extension, and then loads the chosen file into our displayImage Image widget.

Finally, let’s add an About Dialog to our OnAbout Signal Handler. The following code will display an about dialog with information about our application when the user chooses About from the File menu.

     protected void OnAbout (object sender, EventArgs e)
     {
         var about = new AboutDialog ();
         about.ProgramName = "Blake's Image Viewer";
         about.Version = "1.0.0";
         about.Run ();

         about.Destroy ();

     }

Let’s run the application. If everything works correctly you should see the Open File Dialog when selecting Open from the file menu. After choosing an image the window will automatically re-size to adjust for the images size.

SS_11

And clicking the About menu option should display the About Dialog.

SS_12

I hope you’ve enjoyed todays recipe! All of the code can be found on GitHub . Please feel free to post or e-mail me any questions, comments, or suggestions.