This is gtkada_ug.info, produced by makeinfo version 4.5 from gtkada_ug.texi. INFO-DIR-SECTION User Interface Toolkit START-INFO-DIR-ENTRY * GtkAda_Ug: (gtkada_ug). Ada95 graphical tookit based on GTK+ (User's Guide) END-INFO-DIR-ENTRY  File: gtkada_ug.info, Node: Top, Next: Introduction, Prev: (dir), Up: (dir) GtkAda User's Guide ******************* GtkAda User's Guide GtkAda, the Ada 95 graphical toolkit Version 2.4.0 Date: 2004/07/15 22:23:44 Copyright (C) 1998-2000, Emmanuel Briot, Joel Brobecker, Arnaud Charlet Copyright (C) 2000-2003, ACT-Europe 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. * Menu: * Introduction:: * Getting started with GtkAda:: * Hierarchical composition of a window:: * Signal handling:: * Starting an application with GtkAda:: * Resource files:: * Memory management:: * Tasking with GtkAda:: * Object-oriented features:: * Support for Glade the Gtk GUI builder:: * Binding new widgets:: * Debugging GtkAda applications:: * How to report bugs:: * Bibliography:: --- The Detailed Node Listing --- Getting started with GtkAda * How to build and install GtkAda:: * Organization of the GtkAda package:: * How to compile an application with GtkAda:: * Architecture of the toolkit:: * Widgets Hierarchy:: Signal handling * Predefined signals:: * Connecting signals:: * Handling user data:: Object-oriented features * Using tagged types to extend Gtk widgets:: * Creating new widgets in Ada::  File: gtkada_ug.info, Node: Introduction, Next: Getting started with GtkAda, Prev: Top, Up: Top Introduction: What is GtkAda ? ****************************** GtkAda is a high-level portable graphical toolkit, based on the gtk+ toolkit, one of the official GNU toolkits. It makes it easy to create portable user interfaces for multiple platforms, including most platforms that have a X11 server and Win32 platforms. Although it is based on a C library, GtkAda uses some advanced Ada95 features like tagged types, generic packages, access to subprograms, exceptions, etc... to make it easier to use and design interfaces. For efficiency reasons, it does not use controlled types, but takes care of all the memory management for you in other ways. As a result, this library provides a secure, easy to use and extensible toolkit. Compared to the C library, GtkAda provides type safety (especially in the callbacks area), and object-oriented programming. As opposed to common knowledge, it requires less type casting than with in C. Its efficiency is about the same as the C library through the use of inline subprograms. GtkAda comes with a complete integration to the graphical interface builder `Glade'(1). This makes it even easier to develop interfaces, since you just have to click to create a window and all the dialogs. Ada code can then be generated with a single click. GtkAda also has a full support for OpenGL, and comes with a very thin binding to the OpenGL (`Mesa') libraries. You can thus create graphical applications that display 3D graphics, and display them in a GtkAda window, as with any other 2D graphics. This manual does not document OpenGL at all, see any book on OpenGL, or the specification that came with your OpenGL library, for more information. The following Internet sites will always contain the latest public packages for `GtkAda', `gtk+' and `Glade'. `http://libre.act-europe.fr/GtkAda' `http://www.gtk.org' `http://glade.gnome.org' The scheme used for GtkAda's version numbers is the following: the major version number is the same as for the underlying gtk+ library (e.g 1.2 or 1.3). Thus, stable versions of GtkAda will have even major numbers, and development versions (potentially less stable, although we are trying to make sure that no big problem exists in those versions) will have odd version numbers. The minor version numbers depends on GtkAda's release number. This documentation is distributed with GtkAda version 2.4.0. At this stage, every widget found in gtk+ 2.2 has been implemented, and the test program found in the gtk release has been fully coded in Ada (have a look at the `testgtk/' directory in the distribution). This toolkit was tested on the following systems: * GNU Linux/x86 * Solaris/sparc * Tru64 * HP/UX * NT 4.0 * Windows 2000 * Windows XP with the latest version of the `GNAT' compiler, developed and supported by Ada Core Technologies (see `http://www.gnat.com'). 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 version of GtkAda is known to be compatible with `gtk+' 2.2.1 through 2.4.4. This release is no longer compatible with older versions of gtk+. This version of GtkAda is compatible with `Glade' version 2.0.0. Due to some modification in the output format of Glade, this release will not work with older versions. It is also not guaranteed to work with more recent versions. This document does not describe all the widgets available in GtkAda, nor does it try to explain all the subprograms. The GtkAda Reference Manual provides this documentation instead, as well as the GtkAda sources spec files themselves, whose extension is `.ads'. No complete example is provided in this documentation. Instead, please refer to the examples that you can find in the `testgtk/' and `examples/' directory in the GtkAda distribution, since these are more up-to-date (and more extensive). They are heavily commented, and are likely to contain a lot of information that you might find interesting. If you are interested in getting support for GtkAda (including priority bug fixes, early releases, help in using the toolkit, help in designing your interface, on site consulting...), please contact ACT Europe (`mailto:sales@act-europe.fr') or Ada Core Technologies (`mailto:sales@gnat.com'). ---------- Footnotes ---------- (1) Glade was written by Damon Chaplin  File: gtkada_ug.info, Node: Getting started with GtkAda, Next: Hierarchical composition of a window, Prev: Introduction, Up: Top Getting started with GtkAda *************************** This chapter describes how to start a new GtkAda application. It explains the basic features of the toolkit, and shows how to compile and run your application. It also gives a brief overview of the extensive widget hierarchy available in GtkAda. * Menu: * How to build and install GtkAda:: * Organization of the GtkAda package:: * How to compile an application with GtkAda:: * Architecture of the toolkit:: * Widgets Hierarchy::  File: gtkada_ug.info, Node: How to build and install GtkAda, Next: Organization of the GtkAda package, Up: Getting started with GtkAda How to build and install GtkAda =============================== This section explains how to build and install GtkAda on your machine. It is Unix-oriented, since GtkAda is distributed in binary format on Windows machines, and comes with all the dependent packages, including the gtk+ libraries and `Glade'. If you are a Windows-user, you should skip this section. On Unix systems, you first need to install the glib and gtk+ libraries. Download the compatible packages from the gtk+ web site (, compile and install it. When compiling glib, make sure that the support for multithreading is enabled (this is the default, and can be enforced with the `--enable-threads' and `--with-threads' command line switches. Change your PATH environment variable so that the script `gtk-config', which indicates where gtk+ was installed and what libraries it needs is automatically found by GtkAda. You will no longer need this script once GtkAda is installed, unless you develop part of your application in C. OpenGL support will not be activated in GtkAda unless you already have the OpenGL libraries on your systems. You can for instance look at Mesa, which is free implementation. Optionally, you can also install the `Glade' interface builder. Get the compatible package from the Glade web site, compile and install it. The official version already knows about Ada (at least enough to call GtkAda's own programs), so no patch is needed. You can finally download the latest version of GtkAda from the web site. Untar and uncompress the package, then simply do the following steps: > ./configure > make install As usual with the `configure' script, you can specify where you want to install the GtkAda libraries by using the `--prefix' switch. If you have some OpenGL libraries installed on your system, you can make sure that `configure' finds them by specifying the `--with-GL-prefix' switch on the command line. `configure' should be able to automatically detect the libraries however. You must then make sure that the system will be able to find the dynamic libraries at run time if your application uses them. Typically, you would do one of the following: * run `ldconfig' if you installed GtkAda in one of the standard location and you are super-user on your machine * edit `/etc/ld.conf' if you are super-user but did not install GtkAda in one of the standard location. Add the path that contains libgtkada.so (by default `/usr/local/lib' or `$prefix/lib'. * modify your `LD_LIBRARY_PATH' environment variable if you are not super-user. You should simply add the path to libgtkada.  File: gtkada_ug.info, Node: Organization of the GtkAda package, Next: How to compile an application with GtkAda, Prev: How to build and install GtkAda, Up: Getting started with GtkAda Organization of the GtkAda package ================================== In addition to the full sources, the GtkAda package contains a lot of heavily commented examples. If you haven't been through those examples, we really recommend that you look at them and try to understand them, since they contain some examples of code that you might find interesting for your own application. * `testgtk/' directory: This directory contains an application that tests all the widgets in GtkAda. It gives you a quick overview of what can be found in the toolkit, as well as some detailed information on the widgets and their parameters. Each demo is associated with contextual help pointing to aspects worth studying. It also contains an OpenGL demo, if GtkAda was compiled with support for OpenGL. This program is far more extensive that its C counterpart, and the GtkAda team has added a lot of new examples. * `examples/' directory: This directory contains some small examples, unrelated to testgtk. For instance, this is where you will find some sample XML files for `Gate' and `Dgate', as well as some new widgets created directly in Ada, as examples of how to create your own callback marshallers. On the whole these examples are a little more complex than testgtk but, since they focus on demonstrating a precise concept, they are still quite easy to understand. * `docs/' directory: It contains the html, info, text and TeX versions of the documentation you are currently reading. Note that the documentation is divided into two subdirectories, one containing the user guide, which you are currently reading, the other containing the reference manual, which gives detailed information on all the widgets found in GtkAda. The docs directory also contains a subdirectory with some slides that were used to present GtkAda at various shows.  File: gtkada_ug.info, Node: How to compile an application with GtkAda, Next: Architecture of the toolkit, Prev: Organization of the GtkAda package, Up: Getting started with GtkAda How to compile an application with GtkAda ========================================= This section explains how you can compile your own applications. The procedure is system-dependent, and thus is divided into two subsections. Unix systems ------------ On Unix systems, a script called `gtkada-config' is automatically created when you build GtkAda. This script is copied in a subdirectory `bin/' in the installation directory. The easiest and recommended way to build a GtkAda application is to use the `gnatmake' program distributed with GNAT, that takes care of all the dependencies for you. Use the `gtkada-config' to specify where GtkAda and gtk+ libraries have been installed. > gnatmake `gtkada-config` Note the use of back-ticks around gtkada-config, which force the shell to evaluate the script and put the output on the command line. However, on complex systems, gnatmake might not be enough. Users frequently like to create `Makefile's. The script `gtkada-config' remains useful in that case, since you can call it from your Makefile (same syntax as above with the back-ticks) to create variables like FLAGS and LIBS. See the switches of `gtkada-config' below for more information. The script `gtkada-config' understands the following command line switches (chosen to be compatible with the ones set by `gtk-config'): * `--cflags': Output only the compiler flags, i.e the include directories where the GtkAda spec files are found. This should be used if you only want to compile your files, but do not want to bind or link them. * `--libs': Output only the switches for the linker. This lists the directories where all the GtkAda, gtk+, and dependant libraries are found. For instance, if GtkAda was compiled with support for OpenGL, the OpenGL libraries will automatically be present. * `--static': Forces linking with the static gtkada library. This option will still use the dynamic gtk+ libraries. Windows systems --------------- Things are somewhat easier on Windows systems. You don't have access to the `gtkada-config' script. On the other hang you also don't have to specify which libraries to use or where to find them. The only thing you should specify on the `gnatmake' command line is where the GtkAda spec files are found, as in: > gnatmake -Ic:\gtkada\include\gtkada if GtkAda was installed under `c:\gtkada'.  File: gtkada_ug.info, Node: Architecture of the toolkit, Next: Widgets Hierarchy, Prev: How to compile an application with GtkAda, Up: Getting started with GtkAda Architecture of the toolkit =========================== The gtk+ toolkit has been designed from the beginning to be portable. It is made of three libraries, `gtk', `gdk' and `glib'. `Glib' is a non-graphical library, that includes support for lists, h-tables, threads, etc... It is a highly optimized, platform-independent library. Since most of its contents are already available in Ada (or in the `GNAT.*' hierarchy in the GNAT distribution), GtkAda does not include a binding to it, except for a few required packages. These are the `Glib.*' packages in the GtkAda distribution. `Gdk' is the platform-dependent part of gtk+. Its implementation is completely different on win32 systems and X11 systems, although the interface is of course the same. It provides a set of functions to draw lines, rectangles and pixmaps on the screen, manipulate colors, etc... It has a complete equivalent in GtkAda, through the `Gdk.*' packages. `Gtk' is the top level library. It is platform independent, and does all its drawing through calls to Gdk. This is where the high-level widgets are defined. It also includes support for callbacks. Its equivalent in the GtkAda libraries are the `Gtk.*' packages. It is made of a fully object-oriented hierarchy of widgets (see *Note Widgets Hierarchy::). Since your application only calls GtkAda, it is fully portable, and can be recompiled as-is on other platforms. +---------------------------------------------+ | Your Application | +---------------------------------------------+ | GtkAda | | +-----------------------------+ | | GTK | | +-------+-----------------------------+ | | GDK | +-------+--------------+--+-------------------+ | GLIB | | X-Window / Win32 | +----------------------+ +-------------------+ Although the packages have been evolving a lot since the first versions of GtkAda, the specs are stabilizing now. We will try as much as possible to provide backward compatibility whenever possible. Since GtkAda is based on gtk+ we have tried to stay as close to it as possible while using high-level features of the Ada95 language. It is thus relatively easy to convert external examples from C to Ada. 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 * Because of a clash between Ada keywords and widget names, there are two exceptions to the above general rule: Gtk.GEntry.Gtk_Entry Gtk.GRange.Gtk_Range * The function names are the same as in C, ignoring the leading `gtk_' and the widget name, e.g gtk_misc_set_padding => Gtk.Misc.Set_Padding gtk_toggle_button_set_state => Gtk.Toggle_Button.Set_State * Most enum types have been grouped in the `gtk-enums.ads' file * Some features have been implemented as generic packages. These are the timeout functions (see Gtk.Main.Timeout), the idle functions (see Gtk.Main.Idle), and the data that can be attached to any object (see Gtk.Object.User_Data). Type safety is ensured through these generic packages. * Callbacks were the most difficult thing to interface with. These are extremely powerful and versatile, since the callbacks can have any number of arguments, can return values, or not,etc... These are once again implemented as generic packages, that require more explanation (*note Signal handling::). WARNING: all the generic packages allocate some memory for internal structures, and call internal functions. 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. WARNING Before any other call to the GtkAda library is performed, `Gtk.Main.Init' must be invoked first. Most of the time, this procedure is invoked from the main procedure of the application, in which case no use of GtkAda can be done during the application elaboration.  File: gtkada_ug.info, Node: Widgets Hierarchy, Prev: Architecture of the toolkit, Up: Getting started with GtkAda Widgets Hierarchy ================= All widgets in `GtkAda' are implemented as tagged types. They all have a common ancestor, called `Gtk.Object.Gtk_Object'. All visual objects have a common ancestor called `Gtk.Widget.Gtk_Widget'. The following table describes the list of objects and their inheritance tree. As usual with tagged types, all the primitive subprograms defined for a type are also known for all of its children. This is a very powerful way to create new widgets, as will be explained in *Note Creating new widgets in Ada::. Although gtk+ was written in C its design is object-oriented, and thus GtkAda has the same structure. The following rules have been applied to convert from C names to Ada names: a widget `Gtk_XXX' is defined in the Ada package `Gtk.XXX', in the file `gtk-xxx.ads'. This follows the GNAT convention for file names. For instance, the `Gtk_Text' widget is defined in the package `Gtk.Text', in the file `gtk-text.ads'. Note also that most of the documentation for GtkAda is found in the spec files themselves. It is important to be familiar with this hierarchy. It is then easier to know how to build and organize your windows. Most widgets are demonstrated in the `testgtk/' directory in the GtkAda distribution. Gtk_Object +-- Gtk_Data | +-- Gtk_Tooltips | \__ Gtk_Adjustment \__ Gtk_Widget @i{(Visual widgets)} +-- Gtk_Calendar +-- Gtk_Container @i{(Widgets that have children)} | +-- Gtk_Bin @i{(Widgets that have a single child)} | | +-- Gtk_Alignment | | +-- Gtk_Button @i{(Widgets that you can click)} | | | +-- Gtk_Option_Menu | | | +-- Gtk_Toggle_Button | | | | \__ Gtk_Check_Button | | | | \__ Gtk_Radio_Button | | +-- Gtk_Event_Box | | +-- Gtk_Frame | | | \__ Gtk_Aspect_Frame | | +-- Gtk_Handle_Box | | +-- Gtk_Invisible | | +-- Gtk_Item | | | +-- Gtk_List_Item | | | +-- Gtk_Menu_Item | | | | +-- Gtk_Check_Menu_Item | | | | | \__ Gtk_Radio_Menu_Item | | | | \__ Gtk_Tearoff_Menu_Item | | | \__ Gtk_Tree_Item | | +-- Gtk_Viewport | | \__ Gtk_Window @i{(Have an independent window)} | | +-- Gtk_Color_Selection_Dialog | | +-- Gtk_Dialog | | | \__ Gtk_Input_Dialog | | +-- Gtk_File_Selection | | +-- Gtk_Font_Selection_Dialog | | \__ Gtk_Plug | +-- Gtk_Box @i{(Widgets that have one or more children)} | | +-- Gtk_Button_Box | | | +-- Gtk_Vbutton_Box | | | \__ Gtk_Hbutton_Box | | +-- Gtk_Color_Selection | | +-- Gtk_Combo | | +-- Gtk_Gamma_Curve | | \__ Gtk_Status_Bar | +-- Gtk_Clist | | \__ Gtk_Ctree | +-- Gtk_Fixed | +-- Gtk_Layout | +-- Gtk_List | +-- Gtk_Menu_Shell | | +-- Gtk_Menu | | \__ Gtk_Menu_Bar | +-- Gtk_Notebook | | \__ Gtk_Font_Selection | +-- Gtk_Packer | +-- Gtk_Paned | +-- Gtk_Scrolled_Window | +-- Gtk_Socket | +-- Gtk_Toolbar | +-- Gtk_Table | \__ Gtk_Tree +-- Gtk_Drawing_Area | \__ Gtk_Curve +-- Gtk_Editable | +-- Gtk_Entry | | \__ Gtk_Spin_Button | \__ Gtk_Text +-- Gtk_Misc | +-- Gtk_Arrow | +-- Gtk_Image | +-- Gtk_Label | | +-- Gtk_Accel_Label | | \__ Gtk_Tips_Query | \__ Gtk_Pixmap +-- Gtk_Preview +-- Gtk_Progress | \__ Gtk_Progress_Bar +-- Gtk_Range | +-- Gtk_Scale | \__ Gtk_Scrollbar +-- Gtk_Ruler \__ Gtk_Separator *Hierarchy of widgets in GtkAda*  File: gtkada_ug.info, Node: Hierarchical composition of a window, Next: Signal handling, Prev: Getting started with GtkAda, Up: Top Hierarchical composition of a window ************************************ Interfaces in GtkAda are built in layers, as in Motif. For instance, a typical dialog is basically a Gtk_Window, that in turn contains a Gtk_Box, itself divided into two boxes and a Gtk_Separator, and so on. Altough this may seem more complicated than setting absolute positions for children, this is the simplest way to automatically handle the resizing of windows. Each container that creates a layer knows how it should behave when it is resized, and how it should move its children. Thus almost everything is handled automatically, and you don't have to do anything to support resizing. If you really insist on moving the children to a specific position, look at the `Gtk_Fixed' widget and its demo in `testgtk/'. But you really should not use this container, since you will then have to do everything by hand. All the containers are demonstrated in `testgtk/', in the GtkAda distribution. This should help you understand all the parameters associated with the containers. It is very important to master these containers, since using the appropriate containers will make building interfaces a lot easier. If you look at the widget hierarchy (*note Widgets Hierarchy::), you can see that a Gtk_Window inherits from Gtk_Bin, and thus can have only one child. In most cases, the child of a Gtk_Window will thus be a Gtk_Box, which can have any number of children. Some widgets in GtkAda itself are built using this strategy, from the very basic `Gtk_Button' to the more advanced `Gtk_File_Selection'. For example, by default a Gtk_Button contains a Gtk_Label, which displays the text of the button (like "OK" or "Cancel"). However, it is easy to put a pixmap in a button instead. When you create the button, do not specify any label. Thus, no child will be added, and you can give it your own. See `testgtk/create_pixmap.adb' for an example on how to do that.  File: gtkada_ug.info, Node: Signal handling, Next: Starting an application with GtkAda, Prev: Hierarchical composition of a window, Up: Top Signal handling *************** In GtkAda, the interaction between the interface and the core application is done via signals. Most user actions on the graphical application trigger some signals to be `emitted'. A signal is a message that an object wants to broadcast. It is identified by its name, and each one is associated with certain events which happen during the widget's lifetime. For instance, when the user clicks on a Gtk_Button, a "clicked" signal is emitted by that button. More examples of signals can be found in the GtkAda reference manual. It is possible to cause the application to react to such events by `connecting' to a signal a special procedure called a `handler' or `callback'. This handler will be called every time that signal is emitted, giving the application a chance to do any processing it needs. More than one handler can be connected to the same signal on the same object; the handlers are invoked in the order they were connected. * Menu: * Predefined signals:: * Connecting signals:: * Handling user data::  File: gtkada_ug.info, Node: Predefined signals, Next: Connecting signals, Up: Signal handling Predefined signals ================== Widgets, depending on their type, may define zero or more different signals. The signals defined for the parent widget are also automatically inherited; thus every widget answers many signals. The easiest way to find out which signals can be emitted by a widget is to look at the GtkAda reference manual. Every widget will be documented there. The GtkAda RM explains when particular signals are emitted, and the general form that their handlers should have (although you can always add a `User_Data' if you wish, see below). You can also look directly at the C header files distributed with the gtk+ library. Each widget is described in its own C file and has two C structures associated with it. One of them is the "class" structure, which contains a series of pointers to functions. Each of these functions has the same name as the signal name. 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, respectively called `"pressed"', `"released"', ... The profile of the handler can also be deduced from those pointers: The handler has the same arguments, plus an optional `User_Data' parameter that can be used to pass any kind of data to the handler. When the `User_Data' parameter is used, the value of this data is specified when connecting the handler to the signal. It is then given back to the handler when the signal is raised. Therefore, the profile of a handler should look like: procedure Pressed_Handler (Button : access Gtk_Button_Record'Class; User_Data : ...); The callback does not need to use all the arguments. It is legal to use a procedure that "drops" some of the last arguments. There is one special case, however: if, at connection time, you decided to use `User_Data', your callback must handle it. This is checked by the compiler. Any number of arguments can be dropped as long as those arguments are the last ones in the list and you keep the first one. For instance, the signal "button_press_event" normally can be connected to a handler with any of the following profiles: -- with a user_data argument procedure Handler (Widget : access Gtk_Widget_Record'Class; Event : Gdk.Event.Gdk_Event; User_Data : ...); procedure Handler (Widget : access Gtk_Widget_Record'Class; User_Data : ...); -- without a user_data argument procedure Handler (Widget : access Gtk_Widget_Record'Class; Event : Gdk.Event.Gdk_Event); procedure Handler (Widget : access Gtk_Widget_Record'Class); Beware that adding new arguments is not possible, since no value would be provided for them. When connecting a handler, GtkAda will not always verify that your handler does not have more arguments than expected, so caution is recommended (it only does so if you use the `Gtk.Marshallers' package, see below).  File: gtkada_ug.info, Node: Connecting signals, Next: Handling user data, Prev: Predefined signals, Up: Signal handling Connecting signals ================== All the signal handling work is performed by using the services provided by the `Gtk.Handlers' package. This package is self-documented, so please read the documentation for this package either in the GtkAda Reference Manual or in the specs themselves. The rest of this section assumes that you have this documentation handy. A short, annotated example of connecting signals follows; a complete example can be found in create_file_selection.adb (inside the testgtk/ directory). In our example, an application opens a file selector to allow the user to select a file. GtkAda provides a high-level widget called Gtk_File_Selection which can be used in this case: declare Window : Gtk_File_Selection; begin Gtk.File_Selection.Gtk_New (Window, Title => "Select a file"); end; When the "OK" button is pressed, the application needs to retrieve the selected file and then close the dialog. The only information that the handler for the button press needs is which widget to operate upon. This can be achieved by the following handler: procedure OK (Files : access Gtk_File_Selection_Record'Class) is begin Ada.Text_IO.Put_Line ("Selected " & Get_Filename (Files)); -- Prints the name of the selected file. Destroy (Files); -- Destroys the file selector dialog end Ok; We now need to connect the object we created in the first part with the new callback we just defined. `Gtk.Handlers' defines four types of generic packages, depending on the arguments one expects in the callback and whether the callback returns a value or not. Note that you can not use an arbitrary list of arguments; this depends on the signal, as explained in the previous section. In our example, since the callback does not return any value and does not handle any `User_Data' (that is, we don't pass it extra data, which will be specified at connection time), the appropriate package to use is `Gtk.Handlers.Callback'. We thus instantiate that package. Remember that generic package instantiations in GtkAda must be present in memory at all times, since they take care of freeing allocated memory when finished. GtkAda generic package instantiations must therefore always be performed at the library level, and not inside any inner block. package Files_Cb is new Handlers.Callback (Gtk_File_Selection_Record); The `Files_Cb' package now provides a set of Connect subprograms that can be used to establish a tie between a widget and a handler. It also provides a set of other subprograms which you can use to emit the signals manually, although most of the time, the signals are simply emitted internally by GtkAda. We will not discuss the Emit_By_Name subprograms here. The general form of handler, as used in `Gtk.Handlers', expects some handlers that take two or three arguments: the widget on which the signal was applied, an array of all the extra arguments sent internally by GtkAda, and possibly some user data given when the connection was made. This is the most general form of handler and it covers all the possible cases. However, it also expects the user to manually extract the needed values from the array of arguments. This is not always the most convenient solution. This is why GtkAda provides a second package related to signals, `Gtk.Marshallers'. The `Gtk.Marshallers' package provides a set of functions that can be used as callbacks directly for GtkAda, and that will call your application's handlers after extracting the required values from the array of arguments. Although this might sound somewhat complicated, in practice it simplifies the task of connecting signals. In fact, the techniques employed are similar to what is done internally by gtk+ in C. Because of the similarity of techniques, there is no overhead involved in using `Gtk.Marshallers' with Ada over the C code in gtk+. A set of functions `To_Marshaller' is found in every generic package in `Gtk.Handlers'. They each take a single argument, the name of the function you want to call, and return a handler that can be used directly in `Connect'. The connection is then done with the following piece of code. Note that this can be done just after creating the widget, in the same block. As soon as it is created, a widget is ready to accept connections (although no signals will be emitted before the widget is shown on the screen). Note that we use `To_Marshaller' since our handler does not accept the array of arguments as a parameter, and we use the special `Object_Connect' procedure. This means that the parameter to our callback (Files) will be the Slot_Object given in Object_Connect, instead of being the button itself. Files_Cb.Object_Connect (Get_Ok_Button (Window), -- The object to connect to the handler "clicked", -- The name of the signal Files_Cb.To_Marshaller (Ok'Access), -- The signal handler Slot_Object => Window);  File: gtkada_ug.info, Node: Handling user data, Prev: Connecting signals, Up: Signal handling Handling user data ================== As described above, it is possible to define some data that is that passed to the callback when it is called. This data is called user_data, and is passed to the `Connect' or `Object_Connect' subprograms. GtkAda will automatically free any memory it has allocated internally to store these user data. For instance, if you instanciated the generic package `User_Callback' with a String, it means that you want to be able to have a callback of the form: procedure My_Callback (Widget : access Gtk_Widget_Record'Class; User_Data : String); and connect it with a call similar to: Connect (Button, "Clicked", To_Marshaller (My_Callback'Access), User_Data => "any string"); GtkAda needs to allocate some memory to store the string (an unconstrained type). However, this memory is automatically freed when the callback is destroyed. There are a few subtleties in the use of user_data, most importantly when the user data is itself a widget. The following four examples do exactly the same thing, ie create two buttons, and clicking on the first one will destroy the second one. They all work fine the first time, while the two buttons exist. However, some of them will fail if you press on the first button a second time. The code for this example can be found in the distribution, in the `examples/user_data' directory. The examples below do not include the creation of the main window, or of the buttons themselves, to emphasize the important part. First case: simple user data ---------------------------- This code will fail: when `Button2' has been destroyed, the Ada type still points to some random memory, and the second call to `Destroy' will fail with a Storage_Error. package User_Callback is new Gtk.Handlers.User_Callback (Gtk_Widget_Record, Gtk_Widget); procedure My_Destroy2 (Button : access Gtk_Widget_Record'Class; Data : Gtk_Widget) is begin Destroy (Data); end My_Destroy2; begin User_Callback.Connect (Button1, "clicked", User_Callback.To_Marshaller (My_Destroy2'Access), Gtk_Widget (Button2)); end; Second case: using Object_Connect instead ----------------------------------------- One of the solutions to fix the above problem is to use `Object_Connect' instead of `Connect'. In that case, GtkAda automatically takes care of disconnecting the callback when either of the two widgets is destroyed. procedure My_Destroy (Button : access Gtk_Widget_Record'Class) is begin Destroy (Button); end My_Destroy; begin Widget_Callback.Object_Connect (Button1, "clicked", Widget_Callback.To_Marshaller (My_Destroy'Access), Button2); end; Third case: manually disconnecting the callback ----------------------------------------------- Using `Object_Connect' is not always possible. In that case, one of the possibilities is to store the `Id' of the callback, and properly disconnect it when appropriate. This is the most complex method, and very often is not applicable, since you cannot know for sure when the callback is no longer needed. type My_Data3 is record Button, Object : Gtk_Widget; Id : Handler_Id; end record; type My_Data3_Access is access My_Data3; package User_Callback3 is new Gtk.Handlers.User_Callback (Gtk_Widget_Record, My_Data3_Access); procedure My_Destroy3 (Button : access Gtk_Widget_Record'Class; Data : My_Data3_Access) is begin Destroy (Data.Button); Disconnect (Data.Object, Data.Id); end My_Destroy3; Id : Handler_Id; begin Data3 := new My_Data3' (Object => Gtk_Widget (Button1), Button => Gtk_Widget (Button2), Id => (Null_Signal_Id, null)); Id := User_Callback3.Connect (Button1, "clicked", User_Callback3.To_Marshaller (My_Destroy3'Access), Data3); Data3.Id := Id; end; Fourth case: setting a watch on a specific widget ------------------------------------------------- GtkAda provides a function `Add_Watch', that will automatically disconnect a callback when a given widget is destroyed. This is the function used internally by `Object_Connect'. In the example below, the callback is automatically disconnected whenever `Button2' is destroyed. procedure My_Destroy2 (Button : access Gtk_Widget_Record'Class; Data : Gtk_Widget) is begin Destroy (Data); end My_Destroy2; Id : Handler_Id; begin Id := User_Callback.Connect (Button1, "clicked", User_Callback.To_Marshaller (My_Destroy2'Access), Gtk_Widget (Button2)); Add_Watch (Id, Button2); end;  File: gtkada_ug.info, Node: Starting an application with GtkAda, Next: Resource files, Prev: Signal handling, Up: Top Starting 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. Note that this part is optional. 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;  File: gtkada_ug.info, Node: Resource files, Next: Memory management, Prev: Starting an application with GtkAda, Up: Top Resource files ************** Resource files let you parametrize aspects of the widgets in 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"  File: gtkada_ug.info, Node: Memory management, Next: Tasking with GtkAda, Prev: Resource files, Up: Top Memory management ***************** GtkAda takes care of almost all the memory management for you. Here is a brief overview of how this works, you'll have to check the sources if you want more detailed information. Gtk+ (the C library) does its own memory management through reference counting, i.e. any widget is destroyed when it is no longer referenced anywhere in the application. In GtkAda itself, a "user_data" is associated with each object allocated by a `Gtk_New' procedure. A "destroy" callback is also associated, to be called when the object to which the user_data belongs is destroyed. Thus, every time a C object is destroyed, the equivalent Ada structure is also destroyed (see Gtk.Free_User_Data). Concerning widgets containing children, every container holds a reference to its children, whose reference counting is thus different from 0 (and generally 1). When the container is destroyed, the reference of all its children and grand-children is decremented, and they are destroyed in turn if needed. So the deallocation of a widget hierarchy is also performed automatically.  File: gtkada_ug.info, Node: Tasking with GtkAda, Next: Object-oriented features, Prev: Memory management, Up: Top Tasking with GtkAda ******************* Note that Gtk+ under Windows does not interact properly with threads, so the only safe approach under this operating system is to perform all your Gtk+ calls in the same task. Under other platforms, the Glib library can be used in a task-safe mode by calling Gdk.Thread.G_Init and Gdk.Thread.Init before making any other Glib/Gdk calls. In this mode Gdk automatically locks all internal data structures as needed. This does not mean that two tasks can simultaneously access, for example, a single hash table, but they can access two different hash tables simultaneously. If two different tasks need to access the same hash table, the application is responsible for locking itself (e.g by using protected objects). When Gdk is initialized to be task-safe, GtkAda is task aware. There is a single global lock that you must acquire with Gdk.Threads.Enter before making any Gdk/Gtk call, and which you must release with Gdk.Threads.Leave afterwards. Thus, Gtk.Main.Main should be called with the lock acquired (see example below), ensuring that all the functions executed in the task that started the main loop do not need to protect themselves again. Beware that the GtkAda main loop (Gtk.Main.Main) can only be be run inside one specific task. In other words, you cannot call Gtk.Main.Main from any task other than the one that started the outer level main loop. Note that Gdk.Threads assumes that you are using a tasking run time that maps Ada tasks to native threads. A minimal main program for a tasking GtkAda application looks like: with Gdk.Threads; with Gtk.Main; with Gtk.Enums; use Gtk.Enums; with Gtk.Window; use Gtk.Window; procedure GtkAda_With_Tasks is Window : Gtk_Window; begin Gdk.Threads.G_Init; Gdk.Threads.Init; Gtk.Main.Init; Gtk_New (Window, Window_Toplevel); Show (Window); Gdk.Threads.Enter; Gtk.Main.Main; Gdk.Threads.Leave; end GtkAda_With_Tasks; Callbacks require a bit of attention. Callbacks from GtkAda (signals) are made within the GtkAda lock. However, callbacks from Glib (timeouts, IO callbacks, and idle functions) are made outside of the GtkAda lock. So, within a signal handler you do not need to call Gdk.Threads.Enter, but within the other types of callbacks, you do.  File: gtkada_ug.info, Node: Object-oriented features, Next: Support for Glade the Gtk GUI builder, Prev: Tasking with GtkAda, Up: Top 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. * Menu: * General description of the tagged types:: * Using tagged types to extend Gtk widgets:: * Creating new widgets in Ada::