Vala GTK+ Example

/* GTK+ in Vala sample code */

using GLib;
using Gtk;

public class GtkSample : Gtk.Window {

    construct {
        this.title = "Sample Window";
        this.create_widgets ();
    }

    public void create_widgets () {
        this.destroy += Gtk.main_quit;

        var button = new Button.with_label ("Hello World");
        button.clicked += btn => {
            title = btn.label;
        };

        add (button);
    }

    static int main (string[] args) {
        Gtk.init (ref args);

        var sample = new GtkSample ();
        sample.show_all ();

        Gtk.main ();
        return 0;
    }
}

Compile and Run

$ valac --pkg gtk+-2.0 -o gtksample GtkSample.vala
$ ./gtksample

GtkTreeView and GtkBuilder Example

This example uses the GtkBuilder API to create the interface from XML declarations. The interface file is attached to this page: main_window.ui

/* GtkTreeView and GtkBuilder in Vala sample code */

using GLib;
using Gtk;

public class BuilderExample : Gtk.Builder {

    string uifile = "main_window.ui";

    public bool create_widgets () {
        try {
            add_from_file (uifile);
            Gtk.Widget window = (Gtk.Widget) get_object ("window");
            setup_treeview ((Gtk.TreeView) get_object ("treeview1"));
            window.show_all ();
            window.destroy += Gtk.main_quit;
        } catch (GLib.Error err) {
            var msg = new Gtk.MessageDialog (
                null, Gtk.DialogFlags.MODAL, Gtk.MessageType.ERROR, Gtk.ButtonsType.CANCEL, 
                "Failed to load UI\n" + err.message);
            msg.run();
            
            return false;
        } 
        return true;
    }

    public void setup_treeview (Gtk.TreeView view) {

        /* use liststore to hold accountname, accounttype, balance and color attribute */
        /* for more info how gtkTreeview works take a look in the GTK API */

        var listmodel = new Gtk.ListStore(4, typeof(string), typeof(string), typeof(string), typeof(string));
        view.set_model(listmodel);

        view.insert_column_with_attributes (-1, "Account Name", new Gtk.CellRendererText(), "text", 0, null);
        view.insert_column_with_attributes (-1, "Type", new Gtk.CellRendererText(), "text", 1, null);

        var cell = new Gtk.CellRendererText ();
        cell.set ("foreground_set", true, null);
        view.insert_column_with_attributes (-1, "Balance", cell, "text", 2, "foreground", 3, null);

        Gtk.TreeIter iter;
        listmodel.append (out iter);
        listmodel.set (iter, 0, "My Visacard", 1, "card", 2, "102,10", 3, "red", -1);

        listmodel.append (out iter);
        listmodel.set (iter, 0, "My Mastercard", 1, "card", 2, "10,20", 3, "red", -1);
    }

    public static int main (string[] args) {     
        Gtk.init (ref args);

        var mainapp = new BuilderExample ();
        if (mainapp.create_widgets ()) {
            Gtk.main ();
        }

        return 0;
    }     
}

Compile and Run

$ valac --pkg gtk+-2.0 -o builderexample BuilderExample.vala
$ ./builderexample

(A more complete example can be found at my SVN repo at http://svn.tielie.com/filedetails.php?repname=repos+1&path=%2Ftestapps%2Ftestgio%2Ftestgio.vala&rev=0&sc=0")

GtkFileChooser subclass example

/* Custom FileChooserDialog in Vala sample code */

using GLib;
using Gtk;

class OpenFileDialog : Gtk.FileChooserDialog {

    public static string? CWD = null;

    construct {
        this.set_title ("Open file");
        this.set_action (FileChooserAction.OPEN);
        this.add_button (STOCK_CANCEL, ResponseType.CANCEL);
        this.add_button (STOCK_OPEN, ResponseType.OK);

        this.set_default_response (ResponseType.OK);

        if (CWD != null) {
            this.set_current_folder (CWD);
        }
    }

    public override void response (int resp) {
        if ((ResponseType) resp == ResponseType.OK) {
            CWD = this.get_current_folder ();
        }
    }

    public static void main (string[] args) {
        Gtk.init (ref args);

        for (int i = 0; i < 2; i++) {
            var ofd = new OpenFileDialog ();

            if (ofd.run () == ResponseType.OK) {
                stdout.printf ("filename = %s\n".printf (ofd.get_filename ()));
            }

            ofd.destroy ();
        }
    }
}

Compile and Run

$ valac --pkg gtk+-2.0 -o openfiledialog OpenFileDialog.vala
$ ./openfiledialog

Custom GtkWidget example

//
// Johan Dahlin 2008
//
// A quite simple Gtk.Widget subclass which demonstrates how to subclass
// and do realizing, sizing and drawing. Based on widget.py in PyGTK
// 
 
using GLib;
using Gtk;
using Cairo;
 
public class ValaWidget : Gtk.Widget {
  private static const string text = "Hello World!\n";
  private static const int _BORDER_WIDTH = 10;
  private Pango.Layout _layout;
 
  construct {
          this._layout = this.create_pango_layout (ValaWidget.text);
  }
 
  // The realize method is responsible for creating GDK (windowing system)
  // resources. In this example we will create a new gdk.Window which we
  // then draw on
 
  public override void realize ()
  {
        // First set an internal flag telling that we're realized
        this.set_flags (Gtk.WidgetFlags.REALIZED);
 
        // Create a new gdk.Window which we can draw on.
        // Also say that we want to receive exposure events by setting
        // the event_mask
        var attrs = Gdk.WindowAttr ();
        attrs.window_type = Gdk.WindowType.CHILD;
        attrs.width = this.allocation.width;
        attrs.wclass = Gdk.WindowClass.INPUT_OUTPUT;
        attrs.event_mask = this.get_events() | Gdk.EventMask.EXPOSURE_MASK;
        this.window = new Gdk.Window (this.get_parent_window (), attrs, 0);
 
        // Associate the gdk.Window with ourselves, Gtk+ needs a reference
        // between the widget and the gdk window
        this.window.set_user_data (this);
 
        // Attach the style to the gdk.Window, a style contains colors and
        // GC contextes used for drawing
        this.style = this.style.attach (this.window);
 
        // The default color of the background should be what
        // the style (theme engine) tells us.
        this.style.set_background (this.window, Gtk.StateType.NORMAL);
        this.window.move_resize (this.allocation.x, this.allocation.y,
                                 this.allocation.width, this.allocation.height);
  }
 
  // The unrealized method is responsible for freeing the GDK resources
  public override void unrealize ()
  {
        // De-associate the window we created in realize with ourselves
        this.window.set_user_data (null);
  }
 
  // The size_request method Gtk+ is calling on a widget to ask
  // it the widget how large it wishes to be. It's not guaranteed
  // that gtk+ will actually give this size to the widget
  public override void size_request (Gtk.Requisition requisition)
  {
        int width, height;
 
        // In this case, we say that we want to be as big as the
        // text is, plus a little border around it.
        this._layout.get_size (out width, out height);
        requisition.width = width / Pango.SCALE + this._BORDER_WIDTH*4;
        requisition.height = height / Pango.SCALE + this._BORDER_WIDTH*4;
 
  }
 
  // The size_allocate is called by when the actual size is known
  // and the widget is told how much space could actually be allocated
  public override void size_allocate (Gdk.Rectangle allocation)
  {
 
        // Save the allocated space
        this.allocation = (Gtk.Allocation)allocation;
 
        // If we're realized, move and resize the window to the
        // requested coordinates/positions
        if ((this.get_flags () & Gtk.WidgetFlags.REALIZED) == 0)
          return;
        this.window.move_resize (this.allocation.x, this.allocation.y,
                                 this.allocation.width, this.allocation.height);
  }
 
  // The do_expose_event is called when the widget is asked to draw itself
  // Remember that this will be called a lot of times, so it's usually
  // a good idea to write this code as optimized as it can be, don't
  // Create any resources in here.
  public override bool expose_event (Gdk.EventExpose event)
  {
        // In this example, draw a rectangle in the foreground color
        var cr = Gdk.cairo_create (this.window);
        Gdk.cairo_set_source_color (cr, this.style.fg[this.state]);
        cr.rectangle (this._BORDER_WIDTH,
                      this._BORDER_WIDTH,
                      this.allocation.width - 2*this._BORDER_WIDTH,
                      this.allocation.height - 2*this._BORDER_WIDTH);
        cr.set_line_width (5.0);
        cr.set_line_join (Cairo.LineJoin.ROUND);
        cr.stroke ();
 
        // And draw the text in the middle of the allocated space
        int fontw, fonth;
        this._layout.get_pixel_size (out fontw, out fonth);
        cr.move_to ((this.allocation.width - fontw)/2,
                    (this.allocation.height - fonth)/2);
        Pango.cairo_update_layout (cr, this._layout);
        Pango.cairo_show_layout (cr, this._layout);
        return true;
  }
 
  static int main (string[] args) {
 
        Gtk.init (ref args);
 
        Gtk.Window win = new Gtk.Window (Gtk.WindowType.TOPLEVEL);
        win.set_border_width (5);
        win.set_title ("Widget test");
        win.destroy += Gtk.main_quit;
 
        Gtk.Frame frame = new Gtk.Frame ("Example Vala Widget");
        win.add (frame);
 
        ValaWidget w = new ValaWidget ();
        frame.add (w);
 
        win.show_all ();
 
        Gtk.main ();
        return 0;
  }
}

Compile and Run

$ valac --pkg gtk+-2.0 -o valawidget ValaWidget.vala
$ ./valawidget

Vala/GTKSample (last edited 2008-08-14 04:00:19 by ValekFilippov)