GtkAda User's Guide
*******************

   GtkAda User's Guide

   GtkAda, the Ada 95 graphical toolkit

   Version 1.2.4

   Date: 1999/10/21 10:16:11

   Copyright (C) 1998-1999, Emmanuel Briot, Joel Brobecker, Arnaud
Charlet

   This document may be copied, in whole or in part, in any form or by
any means, as is or with alterations, provided that (1) alterations are
clearly marked as alterations and (2) this copyright notice is included
unmodified in any copy.

Introduction
************

The home page for GtkAda, that will always contain the latest news for
this binding, is

   `http://gtkada.eu.org'

The home page for gtk is

   `http://www.gtk.org'

   This is GtkAda version 1.2.4. This package is an Ada95 graphical
library for the Gimp Toolkit, which means this is a set of packages to
allow you to easily create some graphical interfaces under X11 and
Win32, using Ada95 as a programming language.

   From now on, major version numbers will follow Gtk+ (e.g 1.2, 1.3),
meaning that stable versions of GtkAda will have major number 1.2 and
development versions will have number 1.3.

   Every widget from gtk 1.2 has been implemented, and the test program
found in the gtk release has been reimplemented in Ada (have a look at
the `testgtk/' directory).

   This binding was tested on the following systems:
   * Linux/x86

   * Solaris/sparc

   * Solaris/x86

   * Dec Unix 4.0b

   * SGI IRIX 6.5

   * HP/UX 10.20

   * NT 4.0

   * AiX 4.3.2 using the following compilers:
   * Gnat 3.12a2

   * Gnat 3.11b2

   * Gnat 3.11p

   the following versions of gtk:
   * Gtk 1.2.2

   * Gtk 1.2.1

   * Gtk 1.2.0

   and the following versions of glade:
   * Glade 0.4.1

   * Glade 0.4.0

   Although versions up to 0.2.1 were compatible with Gtk-1.0, this one
is Gtk-1.2 specific. If you are looking for a binding to Gtk-1.0,
please consider downloading GtkAda 0.2.1.

   If you manage to use it on other systems (which should probably be
straightforward - just recompile GtkAda), please let us know so that we
can add to the above list.

   This documentation is largely inspired from the Gtk+ documentation
written by Ian Main and Tony Gale.

   GtkAda uses extensively the object oriented programming capabilities,
access to subprograms, exceptions and genericity (in particular to
define and handle callbacks) provided by Ada 95.  As a result, this
library provides a secure, easy to use and extensible toolset.

   A complete example of the use of GtkAda is provided at the end of
this document.

Getting started with GtkAda
***************************

How to build and install GtkAda
===============================

   To build and install GtkAda, simply do the following steps:
   * ./configure

   * make

   * make install

   You then have to make sure that the dynamic library `libgtkada' is
known by your system, by typically running `ldconfig', editing
`/etc/ld.conf' or add the path that contains libgtkada (by default
`/usr/local/lib', or `$prefix/lib' if you specified the `--prefix'
option during the configure step) to your `LD_LIBRARY_PATH'

How to compile an application with GtkAda
=========================================

   A script, `gtkada-config', is provided to simplify the build of an
application:
     gnatmake <main-file> `gtkada-config`

Architecture
============

   There are three major libraries: GTK, GDK and GLIB.  GTK is based on
GDK and GLIB, GDK is based on GLIB and the underlying windowing library
(X-Window or Win32).

     +---------------------------------------------+
     |             Your Application                |
     |               +-----------------------------+
     |               |            GTK              |
     |       +-------+-----------------------------+
     |       |           GDK                       |
     +-------+--------------+--+-------------------+
     |          GLIB        |  | X-Window / Win32  |
     +----------------------+  +-------------------+

   GTK is the interface you will use most, but it is sometimes needed
to use directly GDK and GLIB.

   The Gtk components (resp. Gdk and Glib) are available in packages
whose name start with `Gtk_' (resp. `Gdk_' and `Glib').

   GtkAda uses an object oriented approach of the components (called
`widget'), whose hierarchy is given in the following section.

Widgets Hierarchy
=================

   The simple rule followed by GtkAda to implement each widget is the
following: Given a widget `Gtk_Xxx', its definition can be found in the
package `Gtk.Xxx' in the file `gtk-xxx.ads'.

   For example, the `Gtk_Text' type is defined in package `Gtk.Text'
located in the file `gtk-text.ads'.

   Here is the complete hierarchy of Gtk widgets:

     1    Gtk_Data
     2       Gtk_Tooltips
     2       Gtk_Adjustment
     
     1    Gtk_Widget
     2       Gtk_Calendar
     
     2       Gtk_Container
     3          Gtk_Bin
     4             Gtk_Alignment
     4             Gtk_Event_Box
     4             Gtk_Frame
     5                Gtk_Aspect_Frame
     4             Gtk_Handle_Box
     4             Gtk_Invisible
     4             Gtk_Item
     5                Gtk_List_Item
     5                Gtk_Menu_Item
     6                   Gtk_Check_Menu_Item
     7                      Gtk_Radio_Menu_Item
     6                   Gtk_Tearoff_Menu_Item
     5                Gtk_Tree_Item
     4             Gtk_Viewport
     4             Gtk_Window
     5                Gtk_Color_Selection_Dialog
     5                Gtk_Dialog
     6                   Gtk_Input_Dialog
     5                Gtk_File_Selection
     5                Gtk_Font_Selection_Dialog
     5                Gtk_Plug
     3          Gtk_Box
     4             Gtk_Button_Box
     5                Gtk_Vbutton_Box
     5                Gtk_Hbutton_Box
     4             Gtk_Color_Selection
     4             Gtk_Combo
     4             Gtk_Gamma_Curve
     4             Gtk_Status_Bar
     3          Gtk_Button
     4             Gtk_Option_Menu
     4             Gtk_Toggle_Button
     5                Gtk_Check_Button
     6                   Gtk_Radio_Button
     3          Gtk_Clist
     4             Gtk_Ctree
     3          Gtk_Fixed
     3          Gtk_Layout
     3          Gtk_List
     3          Gtk_Menu_Shell
     4             Gtk_Menu
     4             Gtk_Menu_Bar
     3          Gtk_Notebook
     4             Gtk_Font_Selection
     3          Gtk_Packer
     3          Gtk_Paned
     3          Gtk_Scrolled_Window
     3          Gtk_Socket
     3          Gtk_Toolbar
     3          Gtk_Table
     3          Gtk_Tree
     
     2       Gtk_Drawing_Area
     3          Gtk_Curve
     
     2       Gtk_Editable
     3          Gtk_Entry
     4             Gtk_Spin_Button
     3          Gtk_Text
     
     2       Gtk_Misc
     3          Gtk_Arrow
     3          Gtk_Image
     3          Gtk_Label
     4             Gtk_Accel_Label
     4             Gtk_Tips_Query
     3          Gtk_Pixmap
     
     2       Gtk_Preview
     2       Gtk_Preview_Info
     2       Gtk_Progress
     3          Gtk_Progress_Bar
     
     2       Gtk_Range
     3          Gtk_Scale
     3          Gtk_Scrollbar
     
     2       Gtk_Ruler
     2       Gtk_Separator

   The number represents the type's depth in the hierarchy.

Contents
********

   The almost full set of widget that comes with Gtk 1.2 has been bound,
and you should be able to use all of these widgets from your Ada
program.

   Although it is not quite complete yet, the Gdk binding (the low level
layer) will probably not evolve soon, unless some people (why not you?)
send us patches, or at least ask for specific functions.

   The specs have been evolving a lot since version 0.5, but things
should really stabilize now. We hope that the changes in the next
versions will not break existing code, but we certainly can not
guaranty anything.

   We have tried to adopt a consistent naming scheme for Ada
identifiers:
   * The widget names are the same as in C, except that an underscore
     sign (_) is used to separate words, e.g

          Gtk_Button   Gtk_Color_Selection_Dialog

   * The function names are the  same as in  C, ignoring the leading
     `gtk_' and the widget name, e.g

          gtk_misc_set_padding        ->  Set_Padding
          gtk_toggle_button_set_state ->  Set_State

   * All the enum types have been grouped in the gtk-enums.ads file

   * The only tricky part is for the callbacks, the timeout functions,
     the idle functions, and the data that can be attached to any
     object. In these cases, we have used generic package to provide
     type safety. Please have a look at the files in testgtk to see how
     these functions are used.

   WARNING: all the generic functions allocate some memory for internal
structures. This  memory is freed  by gtk itself,  by calling some Ada
functions. Therefore the generic packages  have to be instanciated at
library level, not  inside a subprogram,  so that the functions are
still defined when gtk needs to free the memory.

Hierarchical composition of a window
************************************

   Typically, a window is created in which one can insert a box
containing either:
   * Atomic components such as Button, Text, Label, ...

   * Other boxes recursively.

   Each component is a widget (Window Gadget), even the windows.

Signal handling
***************

   A signal is `emited' by a widget when an action is performed by the
user on this widget. If the widget has one or more procedures attached
to this signal, they are then executed.  Such procedure will be called
`callback' in this document.

   To associate a callback to a widget, you have to connect this
callback to the specific widget, specifying which signal will be
handled. This is done with the `Connect' function.

   Depending on their type, the widgets can emit zero (e.g `Gtk_Label'),
one or several different signals.

   A signal is identified by a string, e.g
   * "clicked"

   * "destroy"

   * "delete_event"

   * "configure_event"

   * "expose_event"

   For a specific widget, you can connect several callbacks on the same
signal.  They will be executed in the order in which they have been
connected.

   One single callback can be connected several times on the same
widget and even on different widgets.

   The choice made by GtkAda to use generics may look complicated but is
actually simple to use and more important, ensures type checking.

   For example, you can connect to a `Gtk_Button' an action to execute
each time the button is clicked (signal `"clicked"').  Here is how to
do it:
     declare
        Button : Gtk.Button.Gtk_Button;
        Cb_Id  : Glib.Guint;
     
     begin
        Gtk.Button.Gtk_New (Button => Button, Label => "Load");
        Cb_Id := Callbacks.Button_Callback.Connect (
           Obj  => Button,                     --  the emitting widget
           Name => "clicked",                  --  the generated signal
           Func => Callbacks.Load'Access);     --  the signal handler
     end;

   The package `Button_Callback' is an instanciation of the package
`Gtk.Signal.Void_Callback' with the type `Gtk.Button.Gtk_Button'.

   This package defines an access type to a procedure
`Button_Callback.Callback' and the corresponding connect function
`Button_Callback.Connect'.

   The callbacks provided to this function have to respect the
`Button_Callback.Callback' type. Below is an example of how to declare
this package.

     with Gtk.Signal;
     with Gtk.Button;
     
     package Callbacks is
        --  Define callbacks that apply on the widget that detected the
        --  corresponding signal.
        --  These callbacks have only one parameter: the widget itself
     
        package Button_Callback is new Gtk.Signal.Void_Callback
          (Widget_Type => Gtk.Button.Gtk_Button_Record);
     
        --  Which is equivalent to:
        --     package Button_Callback is
        --
        --        type Callback is access procedure
        --           (Widget : access Gtk.Button.Gtk_Button_Record);
        --        --  Definition of the Callback type
        --
        --        function Connect
        --          (Obj    : access Gtk.Button.Gtk_Button_Record'Class;
        --           Name   : in String;
        --           Func   : in Callback;
        --           After  : in Boolean := False)
        --           return Guint;
        --         --  Connect a callback to a button
        --
        --     end Button_Callback;
     
        procedure Load (Widget : access Gtk.Button.Gtk_Button_Record);
        --  The callback procedure
     
     end Callbacks;

   `Callbacks.Load' is a procedure that can be used to handle a signal
since its profile conforms with `Button_Callback.Callback'.

   Note that `Callbacks' must be declared at the library level to
ensure its lifetime and the presence of its variables during the
execution of the application. This is needed so that GtkAda can take
care of freeing memory.

   Although GtkAda tries to check whether you gave enough arguments to
your callback handlers, it is of course easier if you know what gtk+
expects!  The easiest way to find out is to look at the C header files.
Each widget is described in its own C file, and has two C structures
associated with it. One of them is the "class" structure, and contains a
serie of pointers to functions. Each of these functions has the same
name as the signal name, and the arguments are the one that are expected
in the handlers.

   For instance, consider the following extract from gtkbutton.h:
     struct _GtkButtonClass
     {
       GtkBinClass        parent_class;
     
       void (* pressed)  (GtkButton *button);
       void (* released) (GtkButton *button);
       void (* clicked)  (GtkButton *button);
       void (* enter)    (GtkButton *button);
       void (* leave)    (GtkButton *button);
     };

   This means that the Gtk_Button widget redefines five new signals,
called respectively `"pressed"', `"release"', ...  Each of them expects
a handler looking like:

        procedure Pressed_Handler (Button : access Gtk_Button_Record;
                                   Data   : ...);

   The type of Data is given by one of the generic parameters to the
packages in Gtk.Signal.

   For more information on how signals work, we recommand having a look
at the book [1].

Start an application with GtkAda
********************************

   You need to perform some initializations to start a GtkAda
application:
     --  predefined units of the library
     with Gtk.Rc;
     with Gtk.Main;
     with Gtk.Enums;
     with Gtk.Window;
     ...
     --  My units
     with Callbacks;
     ...
     procedure Application is
        procedure Create_Window is ...
     
     begin
        --  Set the locale specific datas (e.g time and date format)
        Gtk.Main.Set_Locale;
     
        --  Initializes GtkAda
        Gtk.Main.Init;
     
        --  Load the resources
        Gtk.Rc.Parse ("application.rc");
     
        --  Create the main window
        Create_Window;
     
        --  Signal handling loop
        Gtk.Main.Main;
     end Application;

   the `Create_Window' procedure looks like

        procedure Create_Window is
           Main_Window : Gtk.Window.Gtk_Window;
           ...
        begin
           Gtk.Window.Gtk_New
             (Window   => Main_Window,
              The_Type => Gtk.Enums.Window_Toplevel);
     
           --  From Gtk.Widget:
           Gtk.Window.Set_Title (Window => Main_Window, Title  => "Editor");
     
           --  Construct the window and connect various callbacks
     
           ...
           Gtk.Window.Show_All (Main_Window);
        end Create_Window;

General GTK documentation
*************************

   This section describes briefly how to use the GTK toolset. This is
largely inspired from the GTK+ documentation. It is recommended that
you read this documentation for all general GTK topics.

   The GTK toolkit is based on two lower level layers: GDK and Glib.
It is sometimes needed to call these layers directly. *Note Description
of the GDK hierarchy:: for a brief description of these packages.

   Each widget is declared in a separate package.  The file, package and
type names can be automatically retrieved from one another. For example,
the type `Gtk_Text' is defined in the package `Gtk.Text' which is
defined in the file `gtk-text.ads'.

   You may want to look at the sources themselves to find informations
on a specific widget.

Package Gtk.Main - high level routines
======================================

   These procedures are described in the order in which they should be
called:

   * `Set_Locale' must be called first. It sets the various datas
     specific to your location, e.g time, date, decimal formats.
          procedure Set_Locale;

   * `Init' initializes the Gtk ENGINE. Among other things, it parses
     the arguments provided on the command line.
          procedure Init;

   * The signal handling loop: call it once the interface has been
     set-up.
          procedure Main;

   * To interrupt the signal handling loop. Usually called in a
     callback to stop the application.
          procedure Main_Quit;

Package Gtk.Signal - connecting callbacks
=========================================

   This section describes three of the generic packages provided by
`Gtk.Signal'.  You can connect as many callback per signal and widgets
as needed.  For a given widget and signal, the various callbacks will
be executed in the order in which they have been connected.

   On the other hand, a same callback routine can be connected to
several widgets and signals.  The `Connect' function returns an integer
(`Glib.Guint') that identifies the connection, allowing you to destroy
it later by giving this identifier and the appropriate widget.  It is
also possible to destroy all the connections to a widget.

   The first package (`Void_Callback') provides a way to create
callbacks that have no specific parameter other than the emitting
widget:
     generic
        type Base_Type is new Gtk.Object.Gtk_Object_Record with private;
     
     package Void_Callback is
     
        type Callback is access procedure (Widget : access Base_Type);
     
        function Connect
          (Obj    : access Base_Type'Class;
           Name   : in String;
           Func   : in Callback;
           After  : in Boolean := False)
           return Guint;
     end Void_Callback;

   The callback procedure that can be connected with the `Connect'
function must follow the profile defined by the `Callback' type.  The
object parameter will be the widget that emitted the signal.  For the
`Connect' function, the parameters are:

   * [Obj] The widget associated with the signal,

   * [Name] The signal name (`"clicked", "destroy", "delete_event"',
     ...),

   * [Func] A pointer to the callback routine,

   * [After] Indicates whether the callback should be executed before
     or after  the widget's automatic class behavior.

   The second package (`Callback') whose callbacks accept an additional
data dynamically allocated during the call to `Connect' and whose
initial value is set by the `Func_Data' parameter

     generic
        type Base_Type is new Gtk.Object.Gtk_Object_Record with private;
     
        type Data_Type (<>) is private;
        --  The type of the data for the callback
        --  This type need not be an access type (as opposed as what
        --  happens in C). A new access is created by the connect function.
     
     package Callback is
     
        type Callback is access procedure
          (Widget : access Base_Type;
           Data   : in Data_Type);
        --  Callback function for Signal_Connect below
     
        function Connect
          (Obj       : access Base_Type'Class;
           Name      : in String;
           Func      : in Callback;
           Func_Data : in Data_Type;
           After     : in Boolean := False)
           return Guint;
     end Callback;

   The last package `Object_Callback' provides callbacks that can be
connected to any kind of widget.  (the `Obj' parameter can be any kind
of object), but the callback parameter, as for previous packages will
still have to be the same as the one specified during the instanciation.

   At run time, the callback will get the widget parameter
`Slot_Object' that has been given to `Connect'.

   This is for example useful when you need to handle a button click
depending on the window that contains the button instead of the button
itself.

     generic
        type Base_Type is new Gtk.Object.Gtk_Object_Record with private;
     
     package Object_Callback is
        type Callback is access procedure (Object : access Base_Type);
     
        function Connect
          (Obj         : access Gtk.Object.Gtk_Object_Record'Class;
           Name        : in String;
           Func        : in Callback;
           Slot_Object : access Base_Type'Class;
           After       : in Boolean := False)
           return Guint;
     end Object_Callback;

   Here a sample code extracted from a text editor that corresponds to
the text loading operation.  The `Callbacks.Load' procedure is a
callback executed when the user clicks on the "Load" button. This
callback will create the file selection window (`Gtk_File_Selection')
and make it modal to force the user to select a file before continuing
to work.  When the user clicks on the "Ok" button of the file selection
window, the `Callbacks.Ok' procedure is called with the parameter
selection window.

     with Gtk.Button;
     package Callbacks is
     
        procedure Load (Widget : in out Gtk.Button.Gtk_Button);
        --  Callback for the ``Load'' button of the text editor
     
     end Callbacks;
     
     with Gtk.Signal, Gtk.Window, Gtk.Main;
     with Gtk.Widget, Gtk.File_Selection, Glib;
     with Editor;
     
     package body Callbacks is
     
        package Files_Cb is new Gtk.Signal.Object_Callback
          (Gtk.File_Selection.Gtk_File_Selection);
     
        --  A callback of type File_Cb.Callback corresponding to the
        --  Cancel button of the file selection window.
     
        procedure Cancel
          (Files : access Gtk.File_Selection.Gtk_File_Selection_Record) is
        begin
           --  Hide the file selection window
     
           Gtk.File_Selection.Hide (Files);
     
           --  This window is no longer modal
     
           Gtk.Main.Grab_Remove (Files);
        end Cancel;
     
        -- A callback of type File_Cb.Callback corresponding to the ``OK''
        -- button of the file selection window.
     
        procedure Ok
          (Files : access Gtk.File_Selection.Gtk_File_Selection_Record) is
        begin
           Editor.Load (Gtk.File_Selection.Get_Filename (Files));
           Gtk.File_Selection.Hide (Files);
           Gtk.Main.Grab_Remove (Files);
        end Ok;
     
        -- Internal procedure to initialize a Gtk_File_Selection
     
        procedure Initialize_File_Selection
          (Files : access Gtk.File_Selection.Gtk_File_Selection_Record;
           Label : String;
           OK_CB : Files_Cb.Callback)
        is
           Cb_Id : Glib.Guint;
        begin
           Gtk.File_Selection.Gtk_New (Files, Label);
     
           --  Hide the create/remove buttons
     
           Gtk.File_Selection.Hide_Fileop_Buttons (Files);
           Cb_Id := Files_Cb.Connect (
              Obj         => Gtk.File_Selection.Get_Ok_Button (Files),
              --  The signal applies to the OK button
     
              Name        => "clicked", -- Event to detect
              Func        => OK_CB,     -- Callback procedure
              Slot_Object => Files);    -- Parameter given to the callback
     
           Cb_Id := Files_Cb.Connect (
              Obj         => Gtk.File_Selection.Get_Cancel_Button (Files),
              Name        => "clicked",
              Func        => Cancel'access,
              Slot_Object => Files);
        end Initialize_File_Selection;
     
        -- The file selection window
     
        Input_File_Sel : Gtk.File_Selection.Gtk_File_Selection;
        Input_File_Sel_Existe : Boolean := False;
     
        -- The ``Load'' callback body
     
        procedure Load (Widget : access Gtk.Button.Gtk_Button_Record) is
        begin
           if not Input_File_Sel_Existe then
              Initialize_File_Selection
                (Input_File_Sel, "File to load ?", OK'Access);
              Input_File_Sel_Existe := True;
           end if;
     
           Gtk.Main.Grab_Add (Input_File_Sel);
     
           --  Show the file selection window
     
           Gtk.File_Selection.Show (Input_File_Sel);
        end Load;
     
     end Callbacks;

   Two procedures to destroy a specific or any connection.

     procedure Disconnect
       (Object     : access Gtk.Object.Gtk_Object_Record'Class;
        Handler_Id : in Guint);
     
     procedure Handlers_Destroy
       (Obj : access Object.Gtk_Object_Record'Class);

Package Gtk.Tooltips
====================

     type Gtk_Tooltips_Record is new Gtk.Data.Gtk_Data_Record with private;
     type Gtk_Tooltips is access all Gtk_Tooltips_Record'Class;

   The message hint that pops up in a little window when the mouse stay
on a widget long enough without moving.

Package Gtk.Adjustment
======================

     type Gtk_Adjustment_Record is new Data.Gtk_Data_Record with private;
     type Gtk_Adjustment is access all Gtk_Adjustment_Record'Class;

   These objects allow you to create a link between a scrollbar and a
scrollable widget (text, scrolled_window).

Package Gtk.Widget
==================

     type Gtk_Widget_Record is new Object.Gtk_Object_Record with null record;
     type Gtk_Widget is access all Gtk_Widget_Record'Class;

   Root of the widget tree. Here are a few useful primitives that are
inherited by all the widgets.

   * Destroy the widget
          procedure Destroy (Widget : access Gtk_Widget_Record);

   * The Widget can be referenced in a resource file under a specified
     name

          procedure Set_Name
            (Widget : access Gtk_Widget_Record; Name : in String);

   * The `Widget' is displayed

          procedure Show (Widget : access Gtk_Widget_Record);

   * The `Widget' and its child widgets are displayed

          procedure Show_All (Widget : access Gtk_Widget_Record);

   * Hide the `Widget'.

          procedure Hide (Widget : access Gtk_Widget_Record);

   * To manipulate the color tables (see, e.g `Gdk.Color.White')

          function Get_Colormap (Widget : access Gtk_Widget_Record)
            return Gdk_Colormap;
          
          function Get_Default_Colormap return Gdk_Colormap;
          
          procedure Set_Default_Colormap
            (Widget : access Gtk_Widget_Record; Cmap : Gdk_Colormap);

   * To (de)associate a Gdk_Window to a widget:
          procedure Realize (Widget : access Gtk_Widget_Record);
          procedure Unrealize (Widget : access Gtk_Widget_Record);
          function  Realized_Is_Set (Widget : access Gtk_Widget_Record'Class)
            return Boolean;

     You need to use `Realize' when for example you want to insert text
     in a `Gtk_Text' before calling `Show'.

   * To make a widget (un)sensitive so that it won't generate any
     signal:
          procedure Set_Sensitive
            (Widget    : access Gtk_Widget_Record;
             Sensitive : in Boolean := True);
     `Set_Sensitive' can be used to temporarily disable a button or a
     container. When it is not sensitive, its visual aspect changes.

   * To know whether a widget has no parent (usually a main window):
          function Toplevel_Is_Set (Widget : access Gtk_Widget_Record'Class)
            return Boolean;

   * To get the parent widget:
          function Get_Parent (Widget : access Gtk_Widget_Record)
            return Gtk_Widget;

   * To get the low level window (`Gdk_Window') associated with a
     widget:
          function Get_Window (Widget : access Gtk_Widget_Record)
            return Gdk.Window.Gdk_Window;

Package Gtk.Label
=================

     type Gtk_Label_Record is new Misc.Gtk_Misc_Record with private;
     type Gtk_Label is access all Gtk_Label_Record'Class;

   To display and then modify a simple string.  A `Gtk_Label' can emit
no signal (see `Event_Box' if you want to connect a signal)

   Create a new label
     procedure Gtk_New (Label : out Gtk_Label; Str : in String);

   Change the label string
     procedure Set_Text (Label : access Gtk_Label_Record; Str : in String);

Package Gtk.Scrollbar
=====================

     type Gtk_Scrollbar_Record is new Gtk.GRange.Gtk_Range_Record with private;
     type Gtk_Scrollbar is access all Gtk_Scrollbar_Record'Class;

   Horizontal or vertical scrollbars that can be associated with the
`Widget' you want to scroll using `Adjustment' (see, eg
`Gtk.Text.Get_Vadj').

     procedure Gtk_New_Hscrollbar
       (Widget     : out Gtk_Scrollbar;
        Adjustment : in Gtk.Adjustment.Gtk_Adjustment);
     
     procedure Gtk_New_Vscrollbar
       (Widget     : out Gtk_Scrollbar;
        Adjustment : in Gtk.Adjustment.Gtk_Adjustment);

Package Gtk.Drawing_Area
========================

     type Gtk_Drawing_Area_Record is new Gtk.Widget.Gtk_Widget_Record
       with private;
     type Gtk_Drawing_Area is access all Gtk_Drawing_Area_Record'Class;
     
     procedure Gtk_New (Widget : out Gtk_Drawing_Area);
     procedure Size
       (Darea  : access Gtk_Drawing_Area_Record;
        Width  : in Glib.Gint;
        Height : in Glib.Gint);

   You can get the `Gdk_Window' associated with a widget to draw in it
using the GDK primitives of `Gdk_Drawable' which is a `subtype' of
`Gdk_Window', see the GDK section.

   This window exists only when the widget is actually realized, e.g
after the call to `Realize' or `Show' of the `Gtk_Drawing_Area'.

   It is possible to draw in the initialization procedure after the
procedure `Show' or when the `Gtk.Main.Main' loop is running, on the
`"configure_event"' signal.

   A `Gtk_Drawing_Area' is a very low level object, in particular when
it is hidden by another window and then exposed, it is not redrawn
automatically. It is up to the application to handle the expose event,
by connecting a callback on the `"expose_event"' signal.

Package Gtk.Text
================

   To manipulate text.
     type Gtk_Text_Record is new
       Gtk.Editable.Gtk_Editable_Record with private;
     type Gtk_Text is access all Gtk_Text_Record'Class;

   End of line are marked by a `Ascii.LF'.  When the application
modifies the text (using, e.g `Insert'), it can first freeze it
(`Freeze') to prevent any change from the user and any automatic update
of the display, then unfreeze it (`Thaw') to allow the user to interact
again.

     procedure Gtk_New
       (Widget : out Gtk_Text;
        Hadj   : access Gtk.Adjustment.Gtk_Adjustment_Record'Class
          := Gtk.Adjustment.Null_Adjustment;
        Vadj   : access Gtk.Adjustment.Gtk_Adjustment_Record'Class
          := Gtk.Adjustment.Null_Adjustment);
     
     procedure Freeze (Text : access Gtk_Text_Record);
     
     procedure Thaw (Text : access Gtk_Text_Record);
     
     function Get_Hadj (Widget : access Gtk_Text_Record)
       return Gtk.Adjustment.Gtk_Adjustment;
     
     function Get_Vadj (Widget : access Gtk_Text_Record)
       return Gtk.Adjustment.Gtk_Adjustment;
     
     function Get_Length (Text : in Gtk_Text) return Guint;
     
     procedure Insert
       (Text   : access Gtk_Text_Record;
        Font   : in Gdk.Font.Gdk_Font'Class;
        Fore   : in Gdk.Color.Gdk_Color;
        Back   : in Gdk.Color.Gdk_Color;
        Chars  : in String;
        Length : in Gint);

   By default, the text shown is not modifiable by the user. To change
this, use the `Set_Editable' procedure:
     procedure Set_Editable
       (Text : access Gtk_Text_Record; Editable : in Boolean);

   To avoid cutting words at the end of a line:
     procedure Set_Word_Wrap
       (Text      : access Gtk_Text_Record;
        Word_Wrap : in Boolean);

   Also inherits primitives from `Gtk.Editable.Gtk_Editable':
   * Destroy a text section
          procedure Delete_Text
            (Editable  : access Gtk_Editable_Record;
             Start_Pos : in Gint;
             End_Pos   : in Gint);   --  e.g Glib.Gint (Get_Length (...))

   * Get the current postion of the cursor
          function Get_Current_Pos (Widget : access Gtk_Editable_Record)
            return Guint;

Package Gtk.Container
=====================

     type Gtk_Container_Record is new
       Gtk.Widget.Gtk_Widget_Record with private;
     type Gtk_Container is access all Gtk_Container_Record'Class;

   General notion that permits to create a hierarchical structure of
widgets, such as `Gtk_Box, Gtk_Table, Gtk_EventBox', ...

   To add/remove a widget in a `Gtk_Container':

     procedure Add
       (Container : access Gtk_Container_Record;
        Widget    : access Gtk.Widget.Gtk_Widget_Record'Class);
     
     procedure Remove
       (Container : access Gtk_Container_Record;
        Widget    : access Gtk.Widget.Gtk_Widget_Record'Class);

   The procedures `Pack_Start' and `Pack_End' of `Gtk_Box' and `Attach'
of `Gtk_Table' let you add widgets and specify their position.

   To set the width of the border around the `Gtk_Container':
     procedure Border_Width
       (Container    : access Gtk_Container_Record;
        Border_Width : in Gint);

Package Gtk.Table
=================

     type Gtk_Table_Record is new Gtk.Container.Gtk_Container_Record
       with private;
     type Gtk_Table is access all Gtk_Table_Record'Class;

   To group widgets in a table. The same widget can cover several boxes
of the table. The size of the boxes depends on what they contain.

     procedure Gtk_New
       (Widget      : out Gtk_Table;
        Rows        : in Glib.Gint;
        Columns     : in Glib.Gint;
        Homogeneous : in Boolean);

   If `Homogeneous' is True, all the boxes will have the same size,
determined by the largest widget and the longest widget.  Otherwise,
the width of a column (resp. heigh of a row) will be determined by the
largest widget of the column.

   To attach a widget to a table
     procedure Attach
       (Table         : access Gtk_Table_Record;
        Child         : access Gtk.Widget.Gtk_Widget_Record'Class;
        Left_Attach   : in Gint;
        Right_Attach  : in Gint;
        Top_Attach    : in Gint;
        Bottom_Attach : in Gint;
        Xoptions      : in Gtk_Attach_Options;
        Yoptions      : in Gtk_Attach_Options;
        Xpadding      : in Gint;
        Ypadding      : in Gint);
     
     procedure Attach_Defaults
       (Table         : access Gtk_Table_Record;
        Widget        : access Gtk.Widget.Gtk_Widget_Record'Class;
        Left_Attach   : in Gint;
        Right_Attach  : in Gint;
        Top_Attach    : in Gint;
        Bottom_Attach : in Gint);

   Attach the widget `Child' to the position indicated by `Left_Attach,
Right_Attach, Top_Attach' and `Bottom_Attach'.  These indexes start
from 0 to the number of column or rows specified at table creation. The
origin (0, 0) of the frontiers is located in upper left.

         0          1          2
        0+----------+----------+
         |          |          |
        1+----------+----------+
         |          |          |
        2+----------+----------+

   The values of `Xoptions' and `Yoptions' can be a logical OR of
several values:
   * [Gtk.Enums.Expand] The table will use all the remaining space in
     the  window.

   * [Gtk.Enums.Shrink] If the widget has less space than needed, it
     will  shrink instead of disappearing.

   * [Gtk.Enums.Fill] The widget takes the whole space that has been
     allocated  for it.

   `Xpadding' and `Ypadding' give the widths in pixels of the  free
space reserved around the widget.

   For the `Attach_Defaults' procedure, the default values of `Xoptions'
and `Yoptions' are equals to `Expand or Fill' and those of `Xpadding'
and `Ypadding' are 0.

Package Gtk.Scrolled_Window
===========================

     type Gtk_Scrolled_Window_Record is new Container.Gtk_Container_Record
       with private;
     type Gtk_Scrolled_Window is access all Gtk_Scrolled_Window_Record'Class;

   To create a scrollable zone in which you can put any kind of widget,
like e.g a table of buttons.  If the window is too small, all the
widgets won't be visible, but they will remain accessible using the
scrollbars.
     procedure Gtk_New
       (Scrolled_Window :    out Gtk_Scrolled_Window;
        Hadjustment     : access Adjustment.Gtk_Adjustment_Record'Class
          := Adjustment.Null_Adjustment;
        Vadjustment     : access Adjustment.Gtk_Adjustment_Record'Class
          := Adjustment.Null_Adjustment);

   Create a `Gtk_Scrolled_Window' by optionally specifying adjustment
rules.

   To get the adjustment rules (to attach scrollbars).
     function Get_Hadjustment
       (Scrolled_Window : access Gtk_Scrolled_Window_Record)
        return Adjustment.Gtk_Adjustment;
     
     function Get_Vadjustment
       (Scrolled_Window : access Gtk_Scrolled_Window_Record)
        return Adjustment.Gtk_Adjustment;

Package Gtk.Notebook
====================

     type Gtk_Notebook_Record is new Gtk.Container.Gtk_Container_Record
       with private;
     type Gtk_Notebook is access all Gtk_Notebook_Record'Class;

   The NoteBook Widget is a collection of PAGES that overlap each other,
each page containing different information.  This widget has become
more common lately in GUI programming, and it is a good way to show
blocks of similar information that warrant separation in their display.

Package Gtk.Box
===============

     type Gtk_Box_Record is new
       Gtk.Container.Gtk_Container_Record with private;
     type Gtk_Box is access all Gtk_Box_Record'Class;
     subtype Gtk_Vbox is Gtk_Box;
     subtype Gtk_Hbox is Gtk_Box;

   Horizontal (`Gtk_New_Hbox') and vertical (`Gtk_New_Vbox') boxes that
can contain several widgets.  you can add widgets from

   * the left to the right starting from the beginning (`Pack_Start')

   * the right to the left, starting from the end (`Pack_End')

     procedure Gtk_New_Vbox
       (Box         : in out Gtk_Box;
        Homogeneous : in  Boolean;
        Spacing     : in  Gint);
     procedure Initialize_Vbox
       (Box         : access Gtk_Box_Record'Class;
        Homogeneous : in  Boolean;
        Spacing     : in  Gint);
     
     procedure Gtk_New_Hbox
       (Box         : in out Gtk_Box;
        Homogeneous : in  Boolean;
        Spacing     : in  Gint);
     procedure Initialize_Hbox
       (Box         : access Gtk_Box_Record'Class;
        Homogeneous : in  Boolean;
        Spacing     : in  Gint);
     
     procedure Pack_Start
       (In_Box  : access Gtk_Box_Record;
        Child   : access Gtk.Widget.Gtk_Widget_Record'Class;
        Expand  : in Boolean := True;
        Fill    : in Boolean := True;
        Padding : in Gint    := 0);
     
     procedure Pack_End
       (In_Box  : access Gtk_Box_Record;
        Child   : access Gtk.Widget.Gtk_Widget_Record'Class;
        Expand  : in Boolean := True;
        Fill    : in Boolean := True;
        Padding : in Gint    := 0);

   *Note Package Gtk.Table::

Package Gtk.Button
==================

     type Gtk_Button_Record is new Bin.Gtk_Bin_Record with private;
     type Gtk_Button is access all Gtk_Button_Record'Class;

   A simple button with a label and signals (e.g `clicked').

Package Gtk.Toggle_Button
=========================

     type Gtk_Toggle_Button_Record is new Gtk.Button.Gtk_Button_Record
       with private;
     type Gtk_Toggle_Button is access all Gtk_Toggle_Button_Record'Class;

   Toggle buttons are very similar to normal buttons, except they will
always be in one of two states, alternated by a click. They may be
depressed, and when you click again, they will pop back up.  Click
again, and they will pop back down.

Package Gtk.Check_Button
========================

     type Gtk_Check_Button_Record is new
       Toggle_Button.Gtk_Toggle_Button_Record with private;
     type Gtk_Check_Button is access all Gtk_Check_Button_Record'Class;

   Check buttons inherit many properties and functions from the the
toggle buttons above, but look a little different.  Rather than being
buttons with text inside them, they are small squares with the text to
the right of them. These are often seen for toggling options on and off
in applications.

Package Gtk.Event_Box
=====================

     type Gtk_Event_Box_Record is new Gtk.Bin.Gtk_Bin_Record with private;
     type Gtk_Event_Box is access all Gtk_Event_Box_Record'Class;

   To associate a callback or clip a widget that is not able to do it,
like labels for example. Note that this container can have only one
child.

     procedure Gtk_New (Widget : out Gtk_Event_Box);

   This widget is a child of `Gtk_Container' and inherits in particular
of:

     procedure Add (Container : access Gtk_Container_Record;
                    Widget    : access Gtk.Widget.Gtk_Widget_Record'Class);

Package Gtk.Window
==================

     type Gtk_Window_Record is new Bin.Gtk_Bin_Record with private;
     type Gtk_Window is access all Gtk_Window_Record'Class;

   The base window, emits the signals `"destroy", "delete_event"'.

Package Gtk.File_Selection
==========================

     type Gtk_File_Selection_Record is new Gtk.Window.Gtk_Window_Record
       with private;
     type Gtk_File_Selection is access all Gtk_File_Selection_Record'Class;

   To select a file in the directories tree. Nothing special to know
about it, just use it!  There are three buttons `Ok, Cancel and Help'.
You can modify these buttons (e.g change the labels, connect callbacks,
...)  with the various `Get_..._Button' functions.

     procedure Gtk_New
       (File_Selection : out Gtk_File_Selection; Title : in String);

   To associate a callback with the buttons of the file selector:
     function Get_Ok_Button
       (File_Selection : access Gtk_File_Selection_Record)
        return Gtk.Button.Gtk_Button;
     
     function Get_Cancel_Button
       (File_Selection : access Gtk_File_Selection_Record)
        return Gtk.Button.Gtk_Button;

   To consult or set the filename:
     function Get_Filename
       (File_Selection : access Gtk_File_Selection_Record)
        return String;
     
     procedure Set_Filename
       (File_Selection : access Gtk_File_Selection_Record;
        Filename : in String);

   To hide the file manipulation buttons (destruction, ...):

     procedure Hide_Fileop_Buttons
       (File_Selection : access Gtk_File_Selection_Record);

Package Gtk.Enums
=================

   This package defines all the enumerated types used by the GTK
hierarchy.

Description of the GDK hierarchy
********************************

   GTK is based on a lower level layer called GDK that contains some
simple drawing and window primitives.

Package Gdk.Color
=================

   Color types and table of colors:
     type Gdk_Color is private;
     type Gdk_Colormap is new Root_Type with private;

   Allows one to get black and white colors by asking the
`Gdk_Colormap' of a widget:
     function White (Colormap : in Gdk_Colormap) return Gdk_Color;
     function Black (Colormap : in Gdk_Colormap) return Gdk_Color;
     Wrong_Color : exception;

   See for example `Get_Default_Colormap'.

   You can of course create your own colors (provided your screen can
display them), by calling the following functions :

     declare
        Color : Gdk_Color;
        Name  : String := "brown";  --  the name of the color to be created
     begin
        --  First, create a color from its name
        Color := Gdk.Color.Parse (Name);
        Gdk.Color.Alloc (Gtk.Widget.Get_Default_Colormap, Color);
     
        --  Or create a color from its values
        Gdk.Color.Set_Rgb (Color,
                           Red   => 20000,
                           Green => 20000,
                           Blue  => 65500);
        Gdk.Color.Alloc (Gtk.Widget.Get_Default_Colormap, Color);
     end;

Package Gdk.Point
=================

     type Gdk_Point is private;

   Used to describe polygons.

     type Gdk_Points_Array is array (Positive range <>) of Gdk_Point;
     
     function Get_X (Point : in Gdk_Point) return Glib.Gint16;
     function Get_Y (Point : in Gdk_Point) return Glib.Gint16;
     procedure Set_X (Point : in out Gdk_Point; X : Glib.Gint16);
     procedure Set_Y (Point : in out Gdk_Point; Y : Glib.Gint16);

Package Gdk.Window
==================

     type Gdk_Window is new Root_Type with private;

   To clear a window (e.g before drawing ):
     procedure Clear (Window : in out Gdk_Window);

Package Gdk.Drawable
====================

     subtype Gdk_Drawable is Gdk.Window.Gdk_Window;

        procedure Draw_Rectangle (Drawable : in Gdk_Drawable'Class;
                                  Gc       : in Gdk.GC.Gdk_GC'Class;
                                  Filled   : in Boolean := False;
                                  X        : in Gint;
                                  Y        : in Gint;
                                  Width    : in Gint;
                                  Height   : in Gint);
     
        procedure Draw_Point (Drawable : in Gdk_Drawable'Class;
                              Gc       : in Gdk.GC.Gdk_GC'Class;
                              X        : in Gint;
                              Y        : in Gint);
     
        procedure Draw_Line (Drawable : in Gdk_Drawable'Class;
     
        procedure Draw_Line (Drawable : in Gdk_Drawable'Class;
                             Gc       : in Gdk.GC.Gdk_GC'Class;
                             X1       : in Gint;
                             Y1       : in Gint;
                             X2       : in Gint;
                             Y2       : in Gint);
     
        procedure Draw_Arc (Drawable : in Gdk_Drawable'Class;
                            Gc       : in Gdk.GC.Gdk_GC'Class;
                            Filled   : in Boolean := False;
                            X        : in Gint;
                            Y        : in Gint;
                            Width    : in Gint;
                            Height   : in Gint;
                            Angle1   : in Gint;
                            Angle2   : in Gint);
     
        procedure Draw_Polygon (Drawable : in Gdk_Drawable'Class;
                                Gc       : in Gdk.GC.Gdk_GC'Class;
                                Filled   : in Boolean;
                                Points   : in Gdk.Point.Gdk_Points_Array);
        procedure Draw_Text
          (Drawable    : in Gdk_Drawable'Class;
           Font        : in Gdk.Font.Gdk_Font;
           Gc          : in Gdk.GC.Gdk_GC;
           X           : in Glib.Gint;
           Y           : in Glib.Gint;
           Text        : in String);

   for all the procedures (in particular `Draw_Arc'), the parameters
are:
   * [X, Y] Position of the point or of the upper left corner or the
     rectangle.

   * [Width, Height] Width and height of the rectangle or of the
     rectangle containing an ellipse.

   * [Angle1]  Starting angle of the arc in 1/64th degrees.

   * [Angle2]  Ending angle relative to Angle1 in 1/64th degrees.

   * [Font]  A font, that can be loaded using `Gdk.Font.Load'.
          For example:
             Gdk.Font.Load
               (Font, "-adobe-courier-medium-i-*-*-15-*-*-*-*-*-*-*");

Package Gdk.GC
==============

   A `Gdk_GC' is a graphic context that must be associated, during its
creation, with a `Gdk_Window', and which is needed for each drawing
primitive of `Gdk_Drawable'.  A `Gdk_GC' let you, for example, set the
colors to use for a drawing.

        type Gdk_GC is new Root_Type with private;
     
        procedure Gdk_New (GC     :    out Gdk_GC;
                           Window : in     Gdk.Window.Gdk_Window'Class);
     
        procedure Destroy (GC : in out Gdk_GC);
     
        procedure Set_Foreground (GC    : in out Gdk_GC;
                                  Color : in     Gdk.Color.Gdk_Color);
     
        procedure Set_Background (GC    : in out Gdk_GC;
                                  Color : in     Gdk.Color.Gdk_Color);
     
        procedure Set_Font (GC   : in out Gdk_GC;
                            Font : in     Gdk.Font.Gdk_Font'Class);

Package Gdk.Font
================

   A font describes the graphical aspect of the characters, their size,
kind, ....

   Under `X11', each font has a name of the form:
     "-adobe-courier-medium-i-*-*-15-*-*-*-*-*-*-*"

   The X command `xfontsel' lets you select a font and build its
associated name automatically.

        type Gdk_Font is new Root_Type with private;
     
        procedure Load
          (Font      :    out Gdk_Font;
           Font_Name : in     String);
     
        procedure Fontset_Load
          (Font         :   out Gdk_Font;
           Fontset_Name : in    String);
     
        function Id (Font : in Gdk_Font) return Gint;
     
        function "=" (Fonta, Fontb : in Gdk_Font) return Boolean;
     
        function String_Width
          (Font : in Gdk_Font;
           Str  : in String) return Gint;
     
        function Text_Width
          (Font : in Gdk_Font;
           Text : in String) return Gint;
     
        function Char_Width
          (Font : in Gdk_Font;
           Char : in Character) return Gint;
     
        function String_Measure
          (Font : in Gdk_Font;
           Str  : in String) return Gint;
     
        function Text_Measure
          (Font : in Gdk_Font;
           Text : in String) return Gint;
     
        function Char_Measure
          (Font : in Gdk_Font;
           Char : in Character) return Gint;

   `Width' gives the sum of the characters' widths, `Measure' gives a
value similar to `Width' except that it takes into account the
attributes of the font (e.g `italic').

Draw in a widget
================

   To select a drawing area, use a `Gtk_Drawing_Area' widget.  The
drawing procedures apply to the Gdk window (see `Gdk_Window' and
`Gdk_Drawable') of the `Gtk_Drawing_Area' widget via a graphic context
(see `Gtk_Gc').

   Typically the code will look like:

     with Glib;
     with Gdk.Window;
     with Gdk.Drawable;
     with Gdk.GC;
     with Gdk.Font;
     
     procedure Draw (Drawing : in out Gtk.Drawing_Area.Gtk_Drawing_Area) is
        Gdkw : Gdk.Window.Gdk_Window;
        GC   : Gdk.GC.Gdk_GC;
        Font : Gdk.Font.Gdk_Font;
        use type Glib.Gint;
     
     begin
        -- Get the Gdk window
     
        Gdkw := Gtk.Drawing_Area.Get_Window (Drawing) ;
     
        -- Clear the window
     
        GDK.Window.Clear (Gdkw) ;
     
        -- Create a graphic context associated with this window
     
        Gdk.GC.Gdk_New (GC, Gdkw);
     
        -- Draw a line in this window
     
        Gdk.Drawable.Draw_Line
          (Drawable => Gdkw,
           GC => GC,
           X1 =>   0, Y1 =>   0,
           X2 => 100, Y2 => 100);
     
        -- Draw an arc
     
        Gdk.Drawable.Draw_Arc
          (Drawable => Gdkw,
           Gc       => gc,
           Filled   => True,
           X        => 100,
           Y        => 100,
           Width    => 200,
           Height   => 100,
           Angle1   => 0 * 64,
           Angle2   => 270 * 64);
     
        -- Ask for a given font
     
        Gdk.Font.Load (Font, "-adobe-courier-medium-i-*-*-15-*-*-*-*-*-*-*");
        Gdk.Drawable.Draw_Text
          (Drawable    => Gdkw,
           Font        => Font,
           Gc          => gc,
           X           => 50,
           Y           => 50,
           Text        => "Hello World");
        Gdk.Font.Destroy (Font);
        Gdk.GC.Destroy (GC);
     end Draw;

Description of the Glib hierarchy
*********************************

   Glib is the low-level layer and provides various types such as
`Gint, Guint', ....

   It also provides access to lists and double-linked lists. Some
functions in GtkAda return lists of Widgets or lists of integer, so it
might be useful to know how to traverse the list.

   Here are the functions available (note that the packages in Glib are
generics that you need to instanciate first).

     function First (List : in out Glist);
     function Next (List : in Glist) return Glist;
     function Last (List : in Glist) return Glist;

   These three functions allow you to traverse the list: get the first
element, then loop while the current element is different from Last.
For instance, here is how you would get the selection in a `Gtk_List'
widget:

     declare
        use type Widget_List.Glist;
        Selection : Widget_List.Glist := Gtk.List.Get_Selection (Widget);
        Current   : Widget_List.Glist := Widget_List.First (Selection);
        Item      : Gtk_Widget;
     begin
        while Current /= Widget_List.Last (Selection) loop
            Item := Widget_List.Get_Data (Current);
            --  use Item however you want
            Current := Widget_List.Next (Current);
        end loop;
     end;

Resource files
**************

   Resource files let you parametrize the aspect of the widgets of a
GtkAda application without having to recompile it.

   A resource file needs to be loaded (`Gtk.Rc.Parse') BEFORE setting
the corresponding window.

   In this file, it is possible to specify the visual characteristics
of the widgets (colors, fonts, ...).  Under X, the `xfontsel' command
allows you to easily select a font.  The FontSelection widget is also a
simple way to select fonts.

   Here is an example of a resource file:
     # application.rc
     #
     # resource file for "Application"
     
     # Buttons style
     style "button"
     {
     # BackGround Colors
     #                  Red  Green  Blue
       bg[PRELIGHT] = { 0.0,  0.75, 0.0 } # Green when the mouse is on
                                          # the button
       bg[ACTIVE]   = { 0.75, 0.0,  0.0 } # Red on click
     # ForeGround Colors
     #                  Red  Green  Blue
       fg[PRELIGHT] = { 1.0,  1.0,  1.0 } # White when the mouse is on
                                          # the button
       fg[ACTIVE]   = { 1.0,  1.0,  1.0 } # White on click
     }
     
     # All the buttons will have the style "button"
     widget_class "*GtkButton*" style "button"
     
     # Text style
     style "text"
     {
       font = "-adobe-courier-medium-r-normal-*-15-*-*-*-*-*-*-*"
       text[NORMAL] = { 0.0, 0.0, 0.0 } # black
       fg[NORMAL]   = { 0.0, 0.0, 0.0 } # black
       base[NORMAL] = { 1.0, 1.0, 1.0 } # white : background color
     }
     
     # All Gtk_Text will have the "text" style
     widget_class "*GtkText" style "text"

Creating and Binding new widgets
********************************

   New since version 0.6, GtkAda has now a basic support for creating
new widgets directly in Ada (although you can't create your own signals
yet, we are still working on it).

   Since GtkAda has an object oriented conception (well, at least you
can program by extension), it is easy, if you want to associate your
own data with a widget, to create your own type. See the examples
below. You should also have a look at the `testgtk/'  directory.

   We provide a Perl script to help you create a binding to a C widget
(this is the script we have used ourselves).  This will not fully
automate the process, although it should really speed things up. You
will probably need less than 15 min to create a new binding once you
will get used to the way GtkAda works. Note that your C file should have
the same format as the one used by Gtk+ itself, as far as indentation
and style are concerned.

   Here are the steps to create a new binding:

   * Give the `generate.pl' script the C header file

   * The perl script should ask you for every field in the C structure
     if you want to create a function to make it accessible from Ada.
     Answer Y or N (the default value is N, just press ENTER).

          $ perl generate.pl ../include/gtk/gtkbutton.h > temporary
            Create a function for the field child (of type GtkWidget*) [n]?
            Create a function for the field in_button (of type guint) [n]?
            Create a function for the field button_down (of type guint) [n]?

   * If you answered yes to at least one of the above questions, create
     a new C file, and move the C part of the TEMPORARY file created by
     generate.pl to this C file.

   * Do a gnatchop on the TEMPORARY file created by generate.pl, after
     deleting the C part from above.

          $ gnatchop temporary

     This should create two Ada files (specification and body)

   * Edit these two files if needed (to change some parameters   from
     Gint to Boolean for instance). It can be a little bit tricky
     when one of your functions returns a GList* or a GSList*. Please
     have   a look at gtk-combo.ads for examples how to do this.

Threads
*******

   The 1.2 series of Gtk+ are now thread safe. The usage of tasks
inside programs using this toolkit should not cause any problem
provided that you protect your Gtk calls with Gdk.Threads.Enter/ Leave
and that your windowing system (e.g X) is thread-safe.

   We recommend however that you read the section related to this topic
in the GTK+ documentation.

How to report bugs
******************

   This library is still considered beta code, and it is thus likely
that you will  find bugs.  We  have tried to  test it as much  as
possible, essentially  by  converting  the  testgtk.c  file  found  in
the  gtk distribution.   We   have  been  able   to  rewrite  nearly
all  the tests. Please have a look at the  testgtk, which can give you
a lot of examples of how to use this toolkit.

   For more general questions about gtk itself, please ask your
questions to the  gtk  mailing list. The  authors of  this toolkit  are
far from being specialists of gtk, as it was one of our first projects
with gtk.

   There are two kinds of problems you can encounter:
   * If the gtk library itself was compiled with warnings turned on, you
     may get some  warnings messages,  mainly because of types problems.
     These warnings should not appear, as we have tried to be as type
     safe as possible  in this package. To know exactly where the
     problem is, compile your program with debug information, run gdb,
     and set a breakpoint on the function `g_log'. Then run your
     program as usual, using the `run' command. Then send us the result
     of the `where' command. Here is a summary:

          $ gnatmake -f -g <your_program_name> `gtkada-config`
          $ gdb <your_program_name>
          (gdb) break main
          (gdb) run
          (gdb) break g_log
          (gdb) continue
          ....
          (gdb) where

   * In  some  (hopefully) rare cases,   you can even get a
     segmentation fault within gtk.  That means there is definitly
     something wrong either in your program or in the toolkit.  Please
     check your program carefully, and if you think this is a problem
     in GtkAda itself, send us an e-mail.

   To report errors, if you are a supported user of GNAT, send a mail to
`mailto:report@gnat.com', otherwise send a mail to the authors
(`mailto:gtkada@ada.eu.org') explaining exactly what your are  doing,
what  is  the  expected  result  and  what  you  actually get. Please
include the required sources to reproduce the problem, in a  format
usable  by `gnatchop'  (basically, insert  all  the required sources at
the end of  the mail). Please  try to provide a  subset of your
sources as small as possible.

   Of course, we will  welcome any patch   you can provide, so  that
this toolkit is as useful as possible.

Object-oriented features
************************

   GtkAda has been designed from the beginning to provide a full Object
oriented layer over gtk+. This means that features such as type
extension, dynamic dispatching, ... are made available through the
standard Ada language.

   This section will describe both how things work and how you can
extend existing widgets or even create your own.

General description of the tagged types
=======================================

Why should I use object-oriented programing ?
---------------------------------------------

   Every widget in GtkAda is a tagged type, which has a number of
primitive subprograms, that are known by all its children.

   This means that, as opposed to what you see in C code, you don't have
(well most of the time you don't) to explictly cast types, and even
when you have to, Ada always makes sure that the conversion is valid.

   Thus your programs are much safer, and most errors are found at
compile time, as is usually the case with Ada.

   For instance, if you create a table, put some widgets in it, and
then, later in your program, try to access these widgets, then you do
not need to know beforehand what their type is, when and by whom they
were created, ... You simply ask for the children of the table, and you
get in return a tagged type that contains all the information you need.
You can even use dynamic dispatching without ever having to cast to a
known type.

   This makes GtkAda a very powerful tool for designing graphical
interfaces.

   If you think one of the standard widgets is nice, but would be even
better if it was drawing itself in a slighlty different way, of if it
could contain some other data that you need in your application, there
is a very simple way to do it: just create a new type that extends the
current one (see the section *Note Using tagged types to extend Gtk
widgets:: below.

   Maybe you want to create your own brand new widget, that knows how
to draw itself, how to react to events, ... and you want to be able to
reuse it anytime you need ? Once again, using the standard Ada
features, you can simply create a new tagged type and teach it how to
interact with the user.  See the section *Note Creating new widgets in
Ada:: below.

Type conversions from C widgets to Ada widgets
----------------------------------------------

   There are basically three kinds of widgets that you can use with
GtkAda:
   * Ada widgets: These are widgets that are written directly in Ada,
     using the object oriented features of GtkAda

   * Standard widgets: These are the widgets that are part of the
     standard gtk+ and GtkAda distributions. This include all the basic
     widgets you need to build advanced interfaces.

   * imported C widgets These are widgets that were created in C, and
     for which you (or someone else) created an Ada binding. This is
     most probably the kind of widgets you will have if you want to use
     third party widgets.

   GtkAda will always be able to find and/or create a valid tagged type
in the first case, no matter if you explicitly created the widget or if
it was created automatically by gtk+. For instance, if you created a
widget in Ada, put it in a table, and later on extracted it from the
table, then you will still have the same widget.

   The second case above is twofold: if the widget was explictly
created by you, or at least by GtkAda, then it will always be and
remain associated with a correct Ada type.

   However, if the widget was created implicitly (for instance every
time you create a Gtk_Button, a Gtk_Label is also created for the text
displayed), then GtkAda is not, by default, able to create the
corresponding Ada type. Instead, it will create a Gtk_Widget, and you
will thus have to do some Uncheck_Cast to convert it back to the type
you want and expect.

   In the third case (imported C widgets), GtkAda is not, by default,
able to create the corresponding Ada type.

   The solution we suggest to solve these two issues is to 'with' the
Gtk.Type_Conversion unit. In that case, every standard widget, no
matter who created them, will always be correctly converted to an
appropriate Ada type.  So, basically, if you put the following in your
main unit:

     with Gtk.Type_Conversion;
     
     begin
        Gtk.Main.Init;
        Gtk.Type_Conversion.Init;
        ...
     end

   then you can safely get the children of any widget (table, boxes,
...) and be sure you have the right Ada type. You won't need to
explictly convert your widget to something else.

   However, 'with'ing this unit means that your application will depend
on every package of GtkAda, which is a little bit heavier, and explains
why this is not the default. We do recommend to use it if it is not
extremely important for you whether your application depends on all the
packages of GtkAda.

   The case of imported C widgets is a little bit trickier. Since
GtkAda does not know anything about them when it is build, it can't
convert magically the C widgets to Ada widgets. This is your job to
teach GtkAda how to do the conversion.

   We thus provide a 'hook' function, that you need to modify. This
function is defined in the package Gtk.Type_Conversion. It is a
function that takes a string with the name of the C widget (ex/
"GtkButton"), and expects a newly allocated pointer in return. If you
don't know this type either, simply return null.

Converting your applications to the new tagged type scheme
==========================================================

   GtkAda 0.6 is an almost complete rewrite of GtkAda. Whereas widgets
used to be record types, they now are implemented as access types.
This change has two benefits:
   * It is now clearer, when you pass an object to a function or as
     an argument to a callback, that you are still working with the
     widget you created before.

   * Most important, it is now possible to extend existing types
     directly   in Ada (see the section below).

   Your existing code might have to be modified a little though (sorry
about that, this is for the better!).
   * Although `Gtk_New' now creates access types (and allocate memory
     for   them), you do not have to free this memory yourself. This is
      automatically taken care of by gtk itself, which is one of the
     strong points of the new scheme.

   * The only part of your code that is actually modified are the
     callbacks. The changes should be easy to handle (We did it   for
     testgtk itself :-).    When instanciating a callback generic, the
     first parameter should be   modified like this:

          package My_Cb is new Signal.Void_Callback (Gtk_Widget_Record);
                                                               ^^^^^^^

     Then you have to modify the spec of the subprogram iself:

          procedure My_Func (Button : access Gtk.Button.Gtk_Button_Record;
                             Data   : in Gint);

     Note that the first parameter is an anonymous access to a record
     type, and the second parameter is an "in" parameter.

   The last things that have changed in this new version of the toolkit
are some of the names of the parameters in the subprograms. This is
part of a major cleanup we are doing so that things can be more
homogeneous within GtkAda.

Using tagged types to extend Gtk widgets
========================================

   Since version 0.6 of this toolkit, it is possible to associate your
own data with existing widgets, simply by creating new types. This
section will show you a simple example, but you should rather read the
source code in testgtk/ where we used this feature instead of using
`user_data' as in the C version.

     type My_Button_Record is new Gtk_Button_Record with record
         --  whatever data you want to associate with your button
     end record;
     type My_Button is access all My_Button_Record'Class;

   With the above statements, your new type is defined. Every function
available for `Gtk_Button' is also available for `My_Button'.  Of
course, as with every tagged type in Ada, you can create your own
primitive functions, with the following prototype:

     procedure My_Primitive_Func (Myb : access My_Button_Record);

   To instanciate an object of type `My_Button' in your application, do
the following:

     declare
        Myb : My_Button;
     begin
        Myb := new My_Button_Record;
        Initialize (Myb);   --  from Gtk.Button
     end;

   The first line creates the Ada type, whereas the `Initialize' call
actually creates the C widget and associates it with the Ada type.

Creating new widgets in Ada
===========================

   With GtkAda, you can now create widgets directly in Ada. These new
widgets can be used directly, as if they were part of gtk itself.

   Creating new widgets is a way to create reuseable components. You can
apply to them the same functions as would for any other widget, such as
Show, Hide, ...

   This section will present how to create two types of widgets,
composite widgets and widgets created from scratch. Two examples are
provided with GtkAda, in the directories `examples/composite_widget' and
`examples/base_widget'. Please also refer to the gtk+ tutorial, that
describes the basic mechanisms that you need to know to create a widget
(even if the Ada code is really different from the C code...)

Creating composite widgets
--------------------------

   A composite widget is a widget that does not do much by itself. This
is more a collection of subwidgets, grouped into a more general entity.
For instance, among the standard widgets, `Gtk_File_Selection' and
`Gtk_Font_Selection' belong to this category.

   The good news is that there is nothing special to know. Just create a
new tagged type, that extends one of the standard widgets (or even
another of your own widgets), provide a `Gtk_New' function that
allocates memory for this widget, and call the `Initialize' function
that does the actual creation of the widget and the subwidgets.  There
is only one thing to do: `Initialize' should the call the parent
class's `Initialize' function, to create the underlying C widget.

   The example directory `examples/composite_widget' reimplements the
`Gtk_Dialog' widget as was written in C by the creators of gtk+.

Creating widgets from scratch
-----------------------------

   First, an important note: please do not read this if this is your
first time using GtkAda, or if you don't really understand the signal
mechanism.  Creating a nice and working widget really takes a lot of
messing with the low level signals.

   Creating a widget from scratch is what you want to do if your widget
should be drawn in a special way, should create and emit new signals,
...  The example we give in `examples/base_widget' is a small target, on
which the user can click, and that sends one of two signals "bullseye"
or "missed" depending on where the user has clicked.

   Once again, the only two functions that you must create are `Gtk_New'
and `Initialize'.  This time, `Initialize' has to do two things:

        Parent_Package.Initialize (Widget);
     
        --  The above line calls the Initialize function from the parent.
        --  This creates the underlying C widget, which we are going to
        --  modify with the following call:
     
        Gtk.Object.Initialize_Class_Record
            (Widget, Signals, Class_Record);
        --  This initializes the "class record" for the widget and
        --  creates the signals.

   In the above example, the new part is the second call. It takes three
arguments:
   * Widget This is the widget that you want to initialize

   * Signals This is an array of string access that contains the name
     of the signals you want to create. For instance, you could create
     Signals with
             Signals      : Gtk.Object.Signal_Array (0 .. 1) :=
               (0 => new String'("bullseye" & Ascii.NUL),
                1 => new String'("missed" & Ascii.NUL));
     This will create two signals, named "bullseye" and "missed", whose
     callbacks do not take any argument (apart from the usual user's
     data). This is the only restriction from GtkAda compared to gtk+:
     all the callbacks are created automatically, but you can not
     specify additionnal parameters that are sent automatically by
     GtkAda.

   * Class_Record Every widget in C is associated with two records. The
     first one, which exists only once per widget type, is the "class
     record". It contains the list of signals that are known by this
     widget type, the list of default callbacks for the signals, ...;
     the second record is an "instance record", which contains each
     instance specific data.  In GtkAda, the "instance record" is
     simply your tagged type and its fields.  The call to
     `Initialize_Class_Record' is provided to initialize the "class
     record". As we said, there should be only one such record per
     widget type. This parameter "Class_Record" will point to this
     records, once it is created, and will be reused for every
     instanciation of the widget.

   Then of course `Initialize' should set up some signal handlers for
the functions you want to redefine.  Three signals are especially
useful:

   * "size_request"

     This callback is passed one parameter, as in :
             procedure Size_Request
                (Widget      : access My_Widget_Record;
                 Requisition : in out Gtk.Widget.Gtk_Requisition);
     This function should modify Requisition to specify what would be
     the ideal size of the widget. This might not be the exact size
     that will be set, since some containers might decide to enlarge or
     to shrink it.

   * "size_allocate"

     This callback is called every time the widget is moved in its
     parent window, or is resize. It is passed one paramater, as in :
             procedure Size_Allocate
                (Widget     : access My_Widget_Record;
                 Allocation : in out Gtk.Widget.Gtk_Allocation)
     This function should take the responsability to move the widget,
     using for instance `Gdk.Window.Move_Resize'.

   * "expose_event"

     This callback is called every time the widget needs to be redrawn.
     It is passed one parameter, the area that is necessary to be
     redrawn (to speed things up, you don't need to redraw the whole
     widget, just this area).

Support for Glade, the Gtk GUI builder
**************************************

   GtkAda now comes with a support for the GUI builder Glade (this is
not the glade released with Gnat for distributed systems).  Not all
widgets are supported yet, but we eventually hope to have all of them.
If you really need one, it is easy to add the two required functions
... (and to send us patches...)

   We actually provide two versions: a dynamic one and a static one. In
both cases, you first need to get and install glade
(http://glade.pn.org).  Then start a new project (or edit an old one).
It is easy enough to use, simply select the widget you want to add to
your interface, and click!

   Starting from version 0.4.1 of Glade, you can directly create Ada
files from Glade by selection Ada95 as the language for your project.
By doing so, you will tell Glade to call gate internally when using the
"Write Source Code" functionality.

   * DGATE (Dynamic Glade Ada Translator and Evaluator) is the dynamic
     version of our support. This is an Ada program that takes the XML
     file in argument. It also provides default callbacks for your
     application, we recommand using it while you are trying to design
     your interface.

   * GATE is the static version of our support. This tool takes the XML
     file in argument and generates a set of Ada files that, when
     compiled, will recreate the interface you just designed with Glade.

   The most important file created by Gate is called
`callback_<project_name>.adb'.  It contains stubs for all the callbacks
you declared in Glade.

   Note that you can easily go back to Glade any time, modify your
interface, and have GATE re-generate a set of files. All your
modifications will be kept in the new files. For that, GATE creates a
directory `.gate/' in the current directory. Please do not delete it if
you want GATE to be able to keep your changes from one version to the
next.

   Also note that to be able to keep track of your modifications, gate
relies on `patch' and `diff' being available on your system.  If you
don't have a working set of `diff/patch', `configure' will simply
replace them by null operations.

   GATE and DGATE currently don't support all widgets and properties
available under Glade. To help you identify which widgets are not
supported, GATE will generate a comment in the `create_<widget>.adb'
file that looks like:

        --  WARNING: Unsupported widget GtkImage (image1)

   Which means that while generating the file, GATE detected an
unsupported widget (in this case GtkImage) whose name is image1.  If
you get such warnings, your file may or may not compile properly, but
you won't get the complete widget hierarchy at run time.

   Feel free to send us (see "How to report bugs") the XML file that
causes this problem. We don't guarantee a rapid fix for each particular
problem, but receiving real examples of missing functionnalities will
certainly help implementing them faster.

   Similarly, DGATE generates a warning to the standard output when
encountering an unsupported widget:

     GtkAda-WARNING **: Unsupported widget GtkImage (image1)

   Here is the list of widgets that are currently not supported by
GATE/DGATE.

   * Gtk_Accel_Label

   * Gtk_Color_Selection

   * Gtk_Ctree

   * Gtk_Curve

   * Gtk_Fixed

   * Gtk_Font_Selection

   * Gtk_Font_Selection_Dialog

   * Gtk_Gamma_Curve

   * Gtk_Handle_Box

   * Gtk_Image

   * Gtk_Invisible

   * Gtk_Layout

   * Gtk_Packer

   * Gtk_Pixmap

   * Gtk_Plug

   * Gtk_Preview_Info

   * Gtk_Radio_Menu_Item

   * Gtk_Socket

   * Gtk_Tearoff_Menu_Item

   * Gtk_Tips_Query

   * Gtk_Tooltips

A complete example
******************

   A window is created with 3 buttons that shows the 3 different types
of callbacks provided.  One interesting thing is that `Callbacks.Bye' is
connected three times: on the `"Quit"' button and two times on the main
window.

     with Gtk.Signal;
     with Gtk.Button;
     with Gtk.Window;
     
     package Callbacks is
     
        package Button_Callback is new Gtk.Signal.Void_Callback
          (Widget_Type => Gtk.Button.Gtk_Button_Record);
        procedure Increment (Widget : access Gtk.Button.Gtk_Button_Record);
     
        package Button_Message is new Gtk.Signal.Callback
          (Widget_Type => Gtk.Button.Gtk_Button_Record,
           Data_Type => String);
     
        procedure Message
          (Widget : access Gtk.Button.Gtk_Button_Record; Data : in String);
     
        package Window_Callback is new Gtk.Signal.Object_Callback
          (Widget_Type => Gtk.Window.Gtk_Window_Record);
     
        procedure Bye (Window : access Gtk.Window.Gtk_Window_Record);
     
     end Callbacks;
     
     with Gtk.Main;
     with Ada.Text_Io;
     
     package body Callbacks is
     
        Counter : Natural := 0;
     
        procedure Increment (Widget : access Gtk.Button.Gtk_Button_Record) is
        begin
           Counter := Counter + 1;
           Ada.Text_Io.Put_Line (Natural'Image (Counter));
        end Increment;
     
        procedure Message
          (Widget : access Gtk.Button.Gtk_Button_Record; Data : in String) is
        begin
           Ada.Text_Io.Put_Line (Data);
        end Message;
     
        procedure Bye (Window : access Gtk.Window.Gtk_Window_Record) is
        begin
           Gtk.Window.Destroy (Window);
           Gtk.Main.Main_Quit;
        end Bye;
     
     end Callbacks;
     
     with Gtk.Rc;
     with Gtk.Main;
     with Gtk.Enums;
     with Gtk.Window;
     with Gtk.Box;
     with Gtk.Label;
     with Gtk.Button;
     with Callbacks;
     with Glib;
     
     procedure Example is
     
        procedure Fix_Label
          (Box : access Gtk.Box.Gtk_Box_Record; Str : String)
        is
           Label : Gtk.Label.Gtk_Label;
        begin
           Gtk.Label.Gtk_New (Label => Label, Str => Str);
           Gtk.Box.Pack_Start
             (In_Box => Box, Child => Label, Expand => False, Fill => False);
        end Fix_Label;
     
        procedure Create_Box
          (W : access Gtk.Window.Gtk_Window_Record;
           Str : String)
        is
           Box    : Gtk.Box.Gtk_Box;
           Button : Gtk.Button.Gtk_Button;
           Cb_Id  : Glib.Guint;
     
        begin
           Gtk.Box.Gtk_New_Vbox
             (Widget => Box, Homogeneous => True, Spacing => 0);
           Gtk.Window.Add (Container => W, Widget => Box);
     
           Fix_Label (Box, Str);
     
           Gtk.Button.Gtk_New (Widget => Button, Label => "Increment");
           Gtk.Box.Pack_Start (In_Box => Box, Child => Button);
           Cb_Id := Callbacks.Button_Callback.Connect
             (Obj => Button,
              Name => "clicked",
              Func => Callbacks.Increment'Access);
     
           Gtk.Button.Gtk_New (Widget => Button, Label => "Message");
           Gtk.Box.Pack_Start (In_Box => Box, Child => Button);
           Cb_Id := Callbacks.Button_Message.Connect
             (Obj => Button,
              Name => "clicked",
              Func => Callbacks.Message'Access,
              Func_Data => "Button message clicked");
     
           Gtk.Button.Gtk_New (Widget => Button, Label => "Quit");
           Gtk.Box.Pack_Start (In_Box => Box, Child => Button);
           Cb_Id := Callbacks.Window_Callback.Connect
             (Obj => Button,
              Name => "clicked",
              Func => Callbacks.Bye'Access,
              Slot_Object => W);
        end Create_Box;
     
        procedure Window is
           Main_Window : Gtk.Window.Gtk_Window;
           Cb_Id : Glib.Guint;
     
        begin
           Gtk.Window.Gtk_New
             (Window => Main_Window, The_Type => Gtk.Enums.Window_Toplevel);
     
           --  Inherited from Gtk.Widget:
     
           Gtk.Window.Set_Title
             (Window => Main_Window, Title => "Some Title");
           Create_Box (Main_Window, "my box") ;
     
           --  Connect the Callbacks
     
           Cb_Id := Callbacks.Window_Callback.Connect
             (Obj => Main_Window,
              Name => "destroy",
              Func => Callbacks.Bye'Access,
              Slot_Object => Main_Window);
           Cb_Id := Callbacks.Window_Callback.Connect
             (Obj => Main_Window,
              Name => "delete_event",
              Func => Callbacks.Bye'Access,
              Slot_Object => Main_Window);
           Gtk.Window.Show_All (Main_Window);
        end Window;
     
     begin
        Gtk.Main.Set_Locale;
        Gtk.Main.Init;
        Gtk.Rc.Parse ("example.rc");
        Window;
        Gtk.Main.Main;
     end Example;

Bibliography
************

   We recommand the following documents. Most of them were written with
C in mind, but should be easily adapted most of the time after you read
the rest of this document.

   * [1] "Gtk+/Gome Application Development" - Havoc Pennington This
     book, by one of the main authors of the the GNOME environment,
     describes in detail some of the inner mechanism of gtk+, including
     the signal handling, and a complete description of all the widgets
     and all the events found in `Gdk.Event'.

     It is worth noting that this book has been published under the Open
     Publication License. You can get an electronic copy of it at
     `http://www.opencontent.org/'.

