W Wrapl, The Programming Language

Using GTK+

The Gtk.* modules provide wrappers for most of the functions in the GTK+ api. They try to apply a Wrapl/Riva style to the functions, for example:

  • There is a one-to-one mapping of GTK+ types to Riva types and GTK+ objects to Riva objects. In general, the Riva types follow the same hierarchy as their GTK+ counterparts, and GTK+ objects of a particular type map to Riva objects of the corresponding Riva type.
  • Where possible, lists are used as arguments for functions expecting arrays in C.
  • Passing variables by reference is used where the function expects an address to write results.
  • Enumerations are placed in separate modules, which export each of the possible values.

For the most part, writing GTK+ apps using Wrapl is quite similar to writing them in C.

Constructing UI's in Wrapl

Gtk1.wrapl
1MOD Gtk1; 2 3IMP Gtk.Gtk; 4 5VAR window <- Gtk.Window.New(Gtk.WindowType.Toplevel); 6VAR button <- Gtk.Button.NewWithLabel("Press Me!"); 7window:Add(button); 8 9VAR dialog <- Gtk.Dialog.New(); 10VAR label <- Gtk.Label.New("Sample GTK+ application"); 11dialog:Vbox:PackStartDefaults(label); 12label:Show; 13dialog:AddButton("gtk-ok", Gtk.ResponseType.Ok); 14dialog:SetTransientFor(window); 15 16button:Connect("clicked", <button, userdata> ( 17 dialog:Run; 18 dialog:Hide; 19)); 20 21window:Connect("destroy", Gtk.Main.Quit); 22 23window:ShowAll; 24Gtk.Main.Run(); 25 26END Gtk1.
Screenshot of Gtk1.wrapl

Using Glade files in Wrapl

Since there is a one-to-one mapping of GTK+ objects to Riva objects, and since the riva module loader is extensible at runtime, the module Gtk.Glader.Loader registers a loader for .glade files. A .glade loaded in this fashion behaves like a Riva module, exporting widgets as Riva objects using their names in the .glade file. In addition, they can be set to automatically connect to Wrapl/Riva functions to handle signals. Callbacks are specified as Module.Export where Module is the path of the module separated by /'s. To denote a module relative to the directory containing the .glade file, Module should start with a /.

The following code combined with the proceeding .glade file will produce the same result as the code above. There is one caveat: the module must be loaded using riva -PGtk/Glade/Loader -L. Gtk2, in order to preload Gtk.Glade.Loader, and so that the module Gtk2 is loaded within the module system and not as an anonymous module.

Gtk2.wrapl
1MOD Gtk2; 2 3IMP Gtk.Gtk; 4IMP .Gtk2UI; 5 6Gtk2UI.MainWindow:ShowAll; 7Gtk.Main.Run(); 8 9DEF OnClick!(button, userdata) ( 10 Gtk2UI.Dialog:Run; 11 Gtk2UI.Dialog:Hide; 12); 13 14END Gtk2.
Gtk2UI.glade
1<?xml version="1.0" encoding="UTF-8" standalone="no"?> 2<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd"> 3<!--Generated with glade3 3.4.5 on Sun Sep 14 10:55:50 2008 --> 4<glade-interface> 5 <widget class="GtkWindow" id="MainWindow"> 6 <signal name="destroy" handler="Gtk/Gtk/Main.Quit"/> 7 <child> 8 <widget class="GtkButton" id="button1"> 9 <property name="visible">True</property> 10 <property name="can_focus">True</property> 11 <property name="receives_default">True</property> 12 <property name="label" translatable="yes">Press Me!</property> 13 <property name="response_id">0</property> 14 <signal name="clicked" handler="/Gtk2.OnClick"/> 15 </widget> 16 </child> 17 </widget> 18 <widget class="GtkDialog" id="Dialog"> 19 <property name="border_width">5</property> 20 <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property> 21 <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> 22 <property name="transient_for">MainWindow</property> 23 <child internal-child="vbox"> 24 <widget class="GtkVBox" id="dialog-vbox1"> 25 <property name="visible">True</property> 26 <property name="spacing">2</property> 27 <child> 28 <widget class="GtkLabel" id="label1"> 29 <property name="visible">True</property> 30 <property name="label" translatable="yes">Sample GTK+ application</property> 31 </widget> 32 <packing> 33 <property name="position">1</property> 34 </packing> 35 </child> 36 <child internal-child="action_area"> 37 <widget class="GtkHButtonBox" id="dialog-action_area1"> 38 <property name="visible">True</property> 39 <property name="layout_style">GTK_BUTTONBOX_END</property> 40 <child> 41 <widget class="GtkButton" id="button2"> 42 <property name="visible">True</property> 43 <property name="can_focus">True</property> 44 <property name="receives_default">True</property> 45 <property name="label" translatable="yes">gtk-ok</property> 46 <property name="use_stock">True</property> 47 <property name="response_id">0</property> 48 </widget> 49 </child> 50 <child> 51 <placeholder/> 52 </child> 53 </widget> 54 <packing> 55 <property name="expand">False</property> 56 <property name="pack_type">GTK_PACK_END</property> 57 </packing> 58 </child> 59 </widget> 60 </child> 61 </widget> 62</glade-interface>