[gtkada] Using libglade2 with GtkAda 2.0.0
Ludovic Brenta
ludovic.brenta at insalien.org
Sun Feb 16 18:30:14 CET 2003
Le dim 16/02/2003 à 12:38, Arnaud Charlet a écrit :
> We also have plans to provide a fully integrated GUI builder/IDE/code
> generator, ala delphi. In this environment, being able to 'see' the generated
> code and to modify it has clearly advantages. So this explains why we are
> not pushing to use libglade, which is inherently less safe than generated
> code, since everything is done dynamically (interpreted), similarly to
> what tcl/tk does.
That's good news. In the mean time, I think libglade would probably fit
the requirement for a fast GUI prototyping tool. You can change the GUI
without recompiling anything and still have your application react to
user input.
> If you (and/or other people) would be kind enough to investigate what is
> needed and send patches to this list, we will be very happy to integrate
> them.
I think the following patch does just that. Could you review it? I'm
new to GtkAda, and to Ada for that matter. I've also attached my
working hello world (compile with gnatmake hello_world
`gtkada-config`). Also note that the format of glade files has changed;
the attached file is really a glade 2 file. One can convert a file
created by glade 0.6.4 to glade 2 format using 'libglade-convert' wich
is part of libglade2.
-------------- next part --------------
? gtkada-libglade2.patch
? gtkada.adp
? testgtk/opengl/view_gl.adb
Index: aclocal.m4
===================================================================
RCS file: /anoncvs/GtkAda/aclocal.m4,v
retrieving revision 1.39
diff -u -r1.39 aclocal.m4
--- aclocal.m4 8 Jul 2002 14:34:12 -0000 1.39
+++ aclocal.m4 16 Feb 2003 17:18:11 -0000
@@ -599,30 +599,26 @@
#############################################################
#
-# Checking for libglade
+# Checking for libglade2
#
#############################################################
AC_DEFUN(AM_CHECK_LIBGLADE,
[
- AC_PATH_PROG(LIBGLADE_CONFIG, libglade-config, no)
+ AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
- if test "$LIBGLADE_CONFIG" = "no" ; then
+ if test "$PKG_CONFIG" = "no" ; then
HAVE_LIBGLADE="False"
LIBGLADE_CFLAGS=""
LIBGLADE_LIBS=""
- LIBGLADE_STATIC_LIBS=""
else
HAVE_LIBGLADE="True"
- LIBGLADE_PREFIX=`$LIBGLADE_CONFIG --prefix`
- LIBGLADE_CFLAGS=`$LIBGLADE_CONFIG --cflags`
- LIBGLADE_LIBS="-L$LIBGLADE_PREFIX/lib -lglade -lxml"
- LIBGLADE_STATIC_LIBS="$LIBGLADE_PREFIX/lib/libglade.a $LIBGLADE_PREFIX/lib/libxml.a"
+ LIBGLADE_CFLAGS=`$PKG_CONFIG --cflags libglade-2.0`
+ LIBGLADE_LIBS="`$PKG_CONFIG --libs libglade-2.0`
fi
AC_SUBST(LIBGLADE_CFLAGS)
AC_SUBST(LIBGLADE_LIBS)
- AC_SUBST(LIBGLADE_STATIC_LIBS)
AC_SUBST(HAVE_LIBGLADE)
])
Index: configure
===================================================================
RCS file: /anoncvs/GtkAda/configure,v
retrieving revision 1.62
diff -u -r1.62 configure
--- configure 8 Jul 2002 14:34:12 -0000 1.62
+++ configure 16 Feb 2003 17:18:16 -0000
@@ -91,7 +91,7 @@
#############################################################
#
-# Checking for libglade
+# Checking for libglade2
#
#############################################################
@@ -2168,21 +2168,21 @@
-# try to find libglade if present
+# try to find libglade2 if present
- # Extract the first word of "libglade-config", so it can be a program name with args.
-set dummy libglade-config; ac_word=$2
+ # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:2177: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_path_LIBGLADE_CONFIG'+set}'`\" = set"; then
+if eval "test \"`echo '$''{'ac_cv_path_PKG_CONFIG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
- case "$LIBGLADE_CONFIG" in
+ case "$PKG_CONFIG" in
/*)
- ac_cv_path_LIBGLADE_CONFIG="$LIBGLADE_CONFIG" # Let the user override the test with a path.
+ ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
;;
?:/*)
- ac_cv_path_LIBGLADE_CONFIG="$LIBGLADE_CONFIG" # Let the user override the test with a dos path.
+ ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a dos path.
;;
*)
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
@@ -2190,34 +2190,31 @@
for ac_dir in $ac_dummy; do
test -z "$ac_dir" && ac_dir=.
if test -f $ac_dir/$ac_word; then
- ac_cv_path_LIBGLADE_CONFIG="$ac_dir/$ac_word"
+ ac_cv_path_PKG_CONFIG="$ac_dir/$ac_word"
break
fi
done
IFS="$ac_save_ifs"
- test -z "$ac_cv_path_LIBGLADE_CONFIG" && ac_cv_path_LIBGLADE_CONFIG="no"
+ test -z "$ac_cv_path_PKG_CONFIG" && ac_cv_path_PKG_CONFIG="no"
;;
esac
fi
-LIBGLADE_CONFIG="$ac_cv_path_LIBGLADE_CONFIG"
-if test -n "$LIBGLADE_CONFIG"; then
- echo "$ac_t""$LIBGLADE_CONFIG" 1>&6
+PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
+if test -n "$PKG_CONFIG"; then
+ echo "$ac_t""$PKG_CONFIG" 1>&6
else
echo "$ac_t""no" 1>&6
fi
- if test "$LIBGLADE_CONFIG" = "no" ; then
+ if test "$PKG_CONFIG" = "no" ; then
HAVE_LIBGLADE="False"
LIBGLADE_CFLAGS=""
LIBGLADE_LIBS=""
- LIBGLADE_STATIC_LIBS=""
else
HAVE_LIBGLADE="True"
- LIBGLADE_PREFIX=`$LIBGLADE_CONFIG --prefix`
- LIBGLADE_CFLAGS=`$LIBGLADE_CONFIG --cflags`
- LIBGLADE_LIBS="-L$LIBGLADE_PREFIX/lib -lglade -lxml"
- LIBGLADE_STATIC_LIBS="$LIBGLADE_PREFIX/lib/libglade.a $LIBGLADE_PREFIX/lib/libxml.a"
+ LIBGLADE_CFLAGS=`$PKG_CONFIG --cflags libglade-2.0`
+ LIBGLADE_LIBS=`$PKG_CONFIG --libs libglade-2.0`
fi
@@ -2450,10 +2447,9 @@
s%@GL_LIBS@%$GL_LIBS%g
s%@GL_CFLAGS@%$GL_CFLAGS%g
s%@HAVE_OPENGL@%$HAVE_OPENGL%g
-s%@LIBGLADE_CONFIG@%$LIBGLADE_CONFIG%g
+s%@PKG_CONFIG@%$PKG_CONFIG%g
s%@LIBGLADE_CFLAGS@%$LIBGLADE_CFLAGS%g
s%@LIBGLADE_LIBS@%$LIBGLADE_LIBS%g
-s%@LIBGLADE_STATIC_LIBS@%$LIBGLADE_STATIC_LIBS%g
s%@HAVE_LIBGLADE@%$HAVE_LIBGLADE%g
s%@GNOME_CFLAGS@%$GNOME_CFLAGS%g
s%@GNOME_LIBS@%$GNOME_LIBS%g
Index: src/glade/glade-xml.adb
===================================================================
RCS file: /anoncvs/GtkAda/src/glade/glade-xml.adb,v
retrieving revision 1.5
diff -u -r1.5 glade-xml.adb
--- src/glade/glade-xml.adb 1 Jul 2002 08:07:35 -0000 1.5
+++ src/glade/glade-xml.adb 16 Feb 2003 17:18:33 -0000
@@ -54,37 +54,6 @@
return Convert (Internal (Get_Object (XML), Name & ASCII.NUL));
end Get_Widget;
- -----------------------------
- -- Get_Widget_By_Long_Name --
- -----------------------------
-
- function Get_Widget_By_Long_Name
- (XML : access Glade_XML_Record;
- Longname : String) return Gtk_Widget
- is
- function Internal
- (XML : System.Address;
- Name : String) return System.Address;
- pragma Import (C, Internal, "glade_xml_get_widget_by_long_name");
-
- begin
- return Convert (Internal (Get_Object (XML), Longname & ASCII.NUL));
- end Get_Widget_By_Long_Name;
-
- --------------------------
- -- Get_Widget_Long_Name --
- --------------------------
-
- function Get_Widget_Long_Name
- (Widget : access Gtk_Widget_Record'Class) return String
- is
- function Internal (Widget : System.Address) return chars_ptr;
- pragma Import (C, Internal, "glade_get_widget_long_name");
-
- begin
- return Value (Internal (Get_Object (Widget)));
- end Get_Widget_Long_Name;
-
---------------------
-- Get_Widget_Name --
---------------------
@@ -99,6 +68,22 @@
return Value (Internal (Get_Object (Widget)));
end Get_Widget_Name;
+ -----------------------
+ -- Get_Widget_Prefix --
+ -----------------------
+
+ function Get_Widget_Prefix
+ (XML : access Glade_XML_Record;
+ Name : String) return Gtk.Widget.Widget_List.GList
+ is
+ function Internal
+ (XML : System.Address;
+ Name : String) return Gtk.Widget.Widget_List.GList;
+ pragma Import (C, Internal, "glade_xml_get_widget_prefix");
+ begin
+ return Internal (Get_Object (XML), Name & ASCII.NUL);
+ end Get_Widget_Prefix;
+
---------------------
-- Get_Widget_Tree --
---------------------
@@ -133,15 +118,15 @@
-- Gtk_New_From_Memory --
-------------------------
- procedure Gtk_New_From_Memory
+ procedure Gtk_New_From_Buffer
(XML : out Glade_XML;
Buffer : String;
Root : String := "";
Domain : String := "") is
begin
XML := new Glade_XML_Record;
- Initialize_From_Memory (XML, Buffer, Root, Domain);
- end Gtk_New_From_Memory;
+ Initialize_From_Buffer (XML, Buffer, Root, Domain);
+ end Gtk_New_From_Buffer;
----------------
-- Initialize --
@@ -155,36 +140,36 @@
is
function Internal
(Fname : String;
- Root : System.Address) return System.Address;
- pragma Import (C, Internal, "glade_xml_new");
-
- function Internal2
- (Fname : String;
Root : System.Address;
- Domain : String) return System.Address;
- pragma Import (C, Internal2, "glade_xml_new_with_domain");
+ Domain : System.Address) return System.Address;
+ pragma Import (C, Internal, "glade_xml_new");
Str1 : aliased constant String := Root & ASCII.NUL;
- Addr1 : System.Address := Str1'Address;
+ Root_Address : System.Address := Str1'Address;
+
+ Str2 : aliased constant String := Domain & ASCII.NUL;
+ Domain_Address : System.Address := Str2'Address;
begin
if Root = "" then
- Addr1 := System.Null_Address;
+ Root_Address := System.Null_Address;
end if;
if Domain = "" then
- Set_Object (XML, Internal (Fname & ASCII.NUL, Addr1));
- else
- Set_Object
- (XML, Internal2 (Fname & ASCII.NUL, Addr1, Domain & ASCII.NUL));
+ Domain_Address := System.Null_Address;
end if;
+
+ Set_Object (XML,
+ Internal (Fname & ASCII.NUL,
+ Root_Address,
+ Domain_address));
end Initialize;
----------------------------
-- Initialize_From_Memory --
----------------------------
- procedure Initialize_From_Memory
+ procedure Initialize_From_Buffer
(XML : access Glade_XML_Record'Class;
Buffer : String;
Root : String := "";
@@ -195,7 +180,7 @@
Size : Integer;
Root : System.Address;
Domain : System.Address) return System.Address;
- pragma Import (C, Internal, "glade_xml_new_from_memory");
+ pragma Import (C, Internal, "glade_xml_new_from_buffer");
Str1 : aliased constant String := Root & ASCII.NUL;
Addr1 : System.Address := Str1'Address;
@@ -212,7 +197,7 @@
end if;
Set_Object (XML, Internal (Buffer, Buffer'Length, Addr1, Addr2));
- end Initialize_From_Memory;
+ end Initialize_From_Buffer;
-------------------
-- Relative_File --
@@ -234,9 +219,15 @@
-- Set_Custom_Handler --
------------------------
- procedure Set_Custom_Handler (Handler : Custom_Widget_Handler) is
+ procedure Set_Custom_Handler
+ (Handler : Custom_Widget_Handler;
+ User_Data : System.Address)
+ is
+ procedure Internal
+ (Handler : Custom_Widget_Handler; User_Data : System.Address);
+ pragma Import (C, Internal, "glade_set_custom_handler");
begin
- raise Program_Error;
+ Internal (Handler, User_Data);
end Set_Custom_Handler;
------------------------
Index: src/glade/glade-xml.ads
===================================================================
RCS file: /anoncvs/GtkAda/src/glade/glade-xml.ads,v
retrieving revision 1.2
diff -u -r1.2 glade-xml.ads
--- src/glade/glade-xml.ads 3 Jan 2002 09:38:15 -0000 1.2
+++ src/glade/glade-xml.ads 16 Feb 2003 17:18:33 -0000
@@ -49,20 +49,31 @@
Fname : String;
Root : String := "";
Domain : String := "");
- -- Create a new Glade_XML.
- -- Fname is the file name of the XML file to load into XML.
- -- Root if not null is the root widget to start from.
- -- Domain if not null is the international domain to use for string
- -- translation. @pxref{Package_Gtkada.Intl} for more information.
+ -- Creates a new GladeXML object (and the corresponding widgets)
+ -- from the XML file fname. Optionally it will only build the
+ -- interface from the widget node Root (if it is not empty). This
+ -- feature is useful if you only want to build say a toolbar or
+ -- menu from the XML file, but not the window it is embedded
+ -- in. Note also that the XML parse tree is cached to speed up
+ -- creating another GladeXML object for the same file.
+ --
+ -- Domain, if not null, is the international domain to use for
+ -- string translation. @pxref{Package_Gtkada.Intl} for more
+ -- information.
- procedure Gtk_New_From_Memory
+
+ procedure Gtk_New_From_Buffer
(XML : out Glade_XML;
Buffer : String;
Root : String := "";
Domain : String := "");
- -- Create a new Glade_XML.
- -- Similar to previous procedure, but the XML contents are read from memory
- -- directly.
+ -- Creates a new GladeXML object (and the corresponding widgets)
+ -- from the buffer Buffer. Optionally it will only build the
+ -- interface from the widget node Root (if it is not empty). This
+ -- feature is useful if you only want to build say a toolbar or
+ -- menu from the XML document, but not the window it is embedded
+ -- in.
+
procedure Initialize
(XML : access Glade_XML_Record'Class;
@@ -72,7 +83,7 @@
-- Internal initialization function.
-- See the section "Creating your own widgets" in the documentation.
- procedure Initialize_From_Memory
+ procedure Initialize_From_Buffer
(XML : access Glade_XML_Record'Class;
Buffer : String;
Root : String := "";
@@ -88,34 +99,59 @@
Handlername : String;
Func : System.Address;
User_Data : System.Address);
+ -- In the glade interface descriptions, signal handlers are
+ -- specified for widgets by name. This function allows you to
+ -- connect an Ada subprogram to all signals in the GladeXML file
+ -- with the given signal handler name.
+
procedure Signal_Autoconnect (XML : access Glade_XML_Record);
- -- Use gmodule to connect signals automatically.
- -- Basically a symbol with the name of the signal handler is searched for,
- -- and that is connected to the associated symbols. So setting
- -- gtk_main_quit as a signal handler for the destroy signal of a window
- -- will do what you expect.
+ -- This function is a variation of Signal_Connect. It uses
+ -- gmodule's introspective features (by opening the module NULL)
+ -- to look at the application's symbol table. From here it tries
+ -- to match the signal handler names given in the interface
+ -- description with symbols in the application and connects the
+ -- signals.
+ --
+ -- Note that this function will not work correctly if gmodule is
+ -- not supported on the platform.
+ --
+ -- Note from Ludovic Brenta: because of the compiler's mangling of
+ -- subprogram names, this feature will not generally work when the
+ -- handlers are Ada subprograms. You can make it work by
+ -- exporting the Ada subprograms with the C convention.
+
function Get_Widget
(XML : access Glade_XML_Record; Name : String) return Gtk_Widget;
+ -- This function is used to get the Gtk_Widget corresponding to
+ -- name in the interface description. You would use this if you
+ -- have to do anything to the widget after loading.
+
- -- function Get_Widget_Prefix
- -- (XML : access Glade_XML_Record; Name : String) return GList; ???
+ function Get_Widget_Prefix
+ (XML : access Glade_XML_Record; Name : String)
+ return Gtk.Widget.Widget_List.GList;
+ -- This function is used to get a list of Gtk_Widgets with names
+ -- that start with the string name in the interface
+ -- description. You would use this if you have to do something to
+ -- all of these widgets after loading.
- function Get_Widget_By_Long_Name
- (XML : access Glade_XML_Record; Longname : String) return Gtk_Widget;
function Relative_File
(XML : access Glade_XML_Record; Filename : String) return String;
+ -- This function resolves a relative pathname, using the directory
+ -- of the XML file as a base. If the pathname is absolute, then
+ -- the original filename is returned.
function Get_Widget_Name
(Widget : access Gtk_Widget_Record'Class) return String;
- function Get_Widget_Long_Name
- (Widget : access Gtk_Widget_Record'Class) return String;
-
function Get_Widget_Tree
(Widget : access Gtk_Widget_Record'Class) return Glade_XML;
+ -- This function is used to get the GladeXML object that built
+ -- this widget.
+
type Custom_Widget_Handler is access function
(XML : access Glade_XML_Record'Class;
@@ -125,9 +161,17 @@
String2 : String;
Int1 : Glib.Gint;
Int2 : Glib.Gint) return Gtk_Widget;
- -- Interface for changing the custom widget handling
+ -- A pointer to a function that creates custom widgets.
+
+ procedure Set_Custom_Handler
+ (Handler : Custom_Widget_Handler;
+ User_Data : System.Address);
+ -- Calling this procedure allows you to override the default
+ -- behaviour when a Custom widget is found in an interface. This
+ -- could be used by a language binding to call some other
+ -- function, or to limit what functions can be called to create
+ -- custom widgets.
- procedure Set_Custom_Handler (Handler : Custom_Widget_Handler);
private
type Glade_XML_Record is new Glib.Object.GObject_Record with null record;
Index: src/glade/glade.adb
===================================================================
RCS file: /anoncvs/GtkAda/src/glade/glade.adb,v
retrieving revision 1.1
diff -u -r1.1 glade.adb
--- src/glade/glade.adb 4 Jan 2001 11:10:13 -0000 1.1
+++ src/glade/glade.adb 16 Feb 2003 17:18:33 -0000
@@ -29,16 +29,19 @@
package body Glade is
- -----------------
- -- Load_Module --
- -----------------
+ procedure Require (Library : String) is
+ procedure Internal (Library : String);
+ pragma Import (C, Internal, "glade_require");
+ begin
+ Internal (Library & ASCII.NUL);
+ end Require;
- procedure Load_Module (Module : String) is
- procedure Internal (Module : String);
- pragma Import (C, Internal, "glade_load_module");
+ procedure Provide (Library : String) is
+ procedure Internal (Library : String);
+ pragma Import (C, Internal, "glade_provide");
begin
- Internal (Module & ASCII.NUL);
- end Load_Module;
+ Internal (Library & ASCII.NUL);
+ end Provide;
end Glade;
Index: src/glade/glade.ads
===================================================================
RCS file: /anoncvs/GtkAda/src/glade/glade.ads,v
retrieving revision 1.1
diff -u -r1.1 glade.ads
--- src/glade/glade.ads 4 Jan 2001 11:10:14 -0000 1.1
+++ src/glade/glade.ads 16 Feb 2003 17:18:34 -0000
@@ -40,7 +40,14 @@
pragma Linker_Options ("-lgtkada_glade");
procedure Init;
- -- must be called before use of libglade
+ -- It used to be necessary to call this procedure before creating
+ -- GladeXML objects. This is now no longer the case, as libglade
+ -- will be initialised on demand now. Calling Init manually will
+ -- not cause any problems though.
+ --
+ -- Note from Ludovic Brenta: if you call this procedure, you must
+ -- call it after Gtk.Main.Init.
+
procedure Gnome_Init;
-- This is defined in libglade-gnome.
@@ -52,11 +59,16 @@
-- It should be used instead of Glade_Init if you want to use the GNOME
-- widget set with included Bonobo controls with libglade.
- procedure Load_Module (Module : String);
- -- Load the named dynamic module.
- -- Basically it is loaded, and the glade_init_module function is called.
- -- This function should do any library initialisation and call
- -- glade_register_widgets.
+ procedure Require (Library : String);
+ -- Ensure that a required library is available. If it is not
+ -- already available, libglade will attempt to dynamically load a
+ -- module that contains the handlers for that library.
+
+ procedure Provide (Library : String);
+ -- This procedure should be called by a module to assert that it
+ -- provides wrappers for a particular library. This should be
+ -- called by the register_widgets() function of a libglade module
+ -- so that it isn't loaded twice, for instance.
private
pragma Import (C, Init, "glade_init");
-------------- next part --------------
A non-text attachment was scrubbed...
Name: hello_world.glade
Type: application/x-glade
Size: 6643 bytes
Desc: not available
Url : /pipermail/gtkada/attachments/20030216/805b3bf9/attachment.bin
-------------- next part --------------
-- Trying a hello workd with GtkAda.
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with System;
with Glade;
with Glade.XML;
with Gtk.Main;
with Gtk.Widget; use Gtk.Widget;
procedure Hello_World is
User_Interface : Glade.XML.Glade_XML;
type User_Data is record
One : Unbounded_String;
Two : Integer;
end record;
procedure On_Exit (Widget : access Gtk_Widget_Record'Class;
My_User_Data : access User_Data) is
begin
Put_Line ("On_Exit called with user_data: ");
Put_Line ("One='" & To_String (My_User_Data.One) &
"', Two=" & Integer'Image (My_User_Data.Two));
Gtk.Main.Gtk_Exit (Error_Code => 0);
end On_Exit;
procedure On_Button_2_Clicked (Widget : access Gtk_Widget_Record'Class;
My_User_Data : access User_Data) is
begin
Ada.Text_IO.Put_Line ("Button 2 clicked.");
Put_Line ("One='" & To_String (My_User_Data.One) &
"', Two=" & Integer'Image (My_User_Data.Two));
end On_Button_2_Clicked;
procedure On_Button_3_Clicked (Widget : access Gtk_Widget_Record'Class;
My_User_Data : access User_Data) is
begin
Ada.Text_IO.Put_Line ("Button 3 clicked.");
Put_Line ("One='" & To_String (My_User_Data.One) &
"', Two=" & Integer'Image (My_User_Data.Two));
end On_Button_3_Clicked;
My_User_Data : aliased User_Data :=
(To_Unbounded_String("What do you get when you multiply six by seven?"), 42);
begin
Gtk.Main.Init;
Glade.Init;
Glade.XML.Gtk_New (User_Interface, "hello_world.glade");
Glade.XML.Signal_Connect (User_Interface,
Handlername => "on_exit",
Func => On_Exit'Address,
User_Data => My_User_Data'Address);
Glade.XML.Signal_Connect (User_Interface,
Handlername => "on_button2_clicked",
Func => On_Button_2_Clicked'Address,
User_Data => My_User_Data'Address);
Glade.XML.Signal_Connect (User_Interface,
Handlername => "on_button3_clicked",
Func => On_Button_3_Clicked'Address,
User_Data => My_User_Data'Address);
Gtk.Main.Main;
end Hello_World;
More information about the gtkada
mailing list