HelloWorld Files Dissected

only for RuBoard - do not distribute or recompile

HelloWorld Files Dissected

Now you re going to take apart each of the files Glade created. First, start with the .c files to see how they fit together to make a complete program. After that, you will take a quick look at HelloWorld.glade to see how it is structured. Finally, you will get a quick word on autogen .sh.

main.c

Listing 5.3 shows the main.c file that s created by Glade when the Build button is clicked. If a main.c file already exists, Glade will not overwrite it (as stated in the initial comment). In this case, to allow for a clean and quick compile from the command line, lines 28 and 29 were commented out after Glade wrote the file.

Listing 5.3 HelloWorld s main.c
 01  /*  02  * Initial main.c file generated by Glade. Edit as required.  03  * Glade will not overwrite this file.  04  */  05  06 #ifdef HAVE_CONFIG_H  07 #  include <config.h>  08 #endif  09  10 #include <gtk/gtk.h>  11  12 #include "interface.h"  13 #include "support.h"  14  15 int  16 main (int argc, char *argv[])  17 { 18   GtkWidget *frm_main;  19  20 #ifdef ENABLE_NLS  21   bindtextdomain (PACKAGE, PACKAGE_LOCALE_DIR);  22   textdomain (PACKAGE);  23 #endif  24  25   gtk_set_locale ();  26   gtk_init (&argc, &argv);  27  28  /*add_pixmap_directory (PACKAGE_DATA_DIR "/pixmaps");  29  add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps");  30  */  31  /*  32  * The following code was added by Glade to create one of each component  33  * (except popup menus), just so that you see something after building  34  * the project. Delete any components that you don't want shown initially.  35  */  36  frm_main = create_frm_main ();  37  gtk_widget_show (frm_main);  38 39  gtk_main ();  40  return 0; 

As you can see, lines 1 “4 are comments about how Glade uses this file. Note that if you add another form or other top-level widget, you will have to either remove this form and let Glade re-create it or manually edit the new parts .

On line 6, config.h has to do with library configuration information. Line 10 compiles in the GTK+ files, and lines 12 and 13 include the interface and support files for this project. Line 15 starts main() , and line 18 declares our main form. ENABLE_NLS has to do with internationalization of text strings, as does gtk_set_locale().

Line 26 initializes the GTK+ system, and lines 28 and 29 have to do with the project if compiled by autogen.sh . Lines 32 “34 contain more comment code generated by Glade, and line 36 creates frm_main with a call to create_frm_main , which is in interface.c . Line 37 makes frm_main visible, and line 39 sends the application into the main gtk loop, waiting for signals emitted from the widgets. Lastly, line 40 returns 0, indicating the program terminated normally.

interface.c

interface.c is the file created by Glade that holds the code needed to instantiate the windows and widgets you ve created using Glade. Its normal mode of operation is to have a create_xxx() function call to create the windows you specify, and then call those create_xxx() functions from main.c and return a pointer to the newly instantiated window.

Listing 5.4 HelloWorld s interface.c
 01 /*  02  * DO NOT EDIT THIS FILE - it is generated by Glade.  03  */  04 #ifdef HAVE_CONFIG_H  05 #  include <config.h>  06 #endif  07  08 #include <sys/types.h>  09 #include <sys/stat.h>  10 #include <unistd.h>  11 #include <string.h>  12  13 #include <gdk/gdkkeysyms.h>  14 #include <gtk/gtk.h>  15  16 #include "callbacks.h"  17 #include "interface.h"  18 #include "support.h"  19  20 GtkWidget*  21 create_frm_main (void)  22 { 23   GtkWidget *frm_main;  24   GtkWidget *cmd_main;  25  26   frm_main = gtk_window_new (GTK_WINDOW_TOPLEVEL);  27   gtk_object_set_data (GTK_OBJECT (frm_main), "frm_main", frm_main);  28   gtk_window_set_title (GTK_WINDOW (frm_main), _("HelloWorld App"));  29  30   cmd_main = gtk_button_new_with_label (_("Hello World!\nClick to close."));  31   gtk_widget_ref (cmd_main);  32   gtk_object_set_data_full (GTK_OBJECT (frm_main), "cmd_main", cmd_main,  33                             (GtkDestroyNotify) gtk_widget_unref);  34   gtk_widget_show (cmd_main);  35   gtk_container_add (GTK_CONTAINER (frm_main), cmd_main);  36  37   gtk_signal_connect (GTK_OBJECT (cmd_main), "clicked",  38                       GTK_SIGNAL_FUNC (on_cmd_main_clicked),  39                       NULL);  40  41   return frm_main;  42 } 

Lines 1 “3 are generated by Glade. If you open HelloWorld.glade from Glade and click the Build button, this file will be overwritten.

have_config_h has already been covered (see Line 6 of Listing 5.3, as well as the commentary afterward). The include for sys/types.h has to do with primitive data type definitions, and stat.h deals with file characteristics. unistd.h has symbolic constants, and string.h deals with string handling functionality. gdkkeysyms.h contains key mapping definitions. gtk.h has already been covered also. Lines 16 “18 get the functions necessary for create_frm_main to work.

Line 20 declares the return type from create_frm_main to be a GtkWidget type. Line 23 declares a second variable named frm_main. In spite of the fact that it is named the same, it will only be used within this function. The last line (line 42) returns this local frm_main , and main.c puts it into our global frm_main . As you can see from lines 23 and 24, you only need two widgets. Line 26 s gtk_window_new has already been covered (see main.c in Listing 5.3).

Line 27 contains the gtk_object_set_data() function. This function allows GTK+ to associate any amount of information with an object. Line 28 sets the title that will appear in the title bar of frm_main . Line 30 instantiates a new command button into cmd_main , and the gtk_object_set_data_full() function associates the cmd_main widget with the frm_main widget and sets a notification when the frm_main object is destroyed .

Line 34 makes frm_main visible, and line 37 connects the clicked event of cmd_main to the function (in callbacks.c ) on_cmd_main_clicked() . (This is the function to which you had to add gtk_main_quit() to properly close the application.)

support.c

Glade creates the file support.c to provide utility functions for use in your GTK+ program. The function lookup_widget() deserves special attention because it allows you to give the window and the name of the child widget you are seeking, and it will return a pointer to that child. This is very helpful when you are referencing widgets in different windows.

Listing 5.5 HelloWorld s support.c
 001 /*  002  * DO NOT EDIT THIS FILE - it is generated by Glade.  003  */  004  005 #ifdef HAVE_CONFIG_H  006 #  include <config.h>  007 #endif  008  009 #include <sys/types.h>  010 #include <sys/stat.h>  011 #include <unistd.h>  012 #include <string.h>  013  014 #include <gtk/gtk.h>  015  016 #include "support.h"  017  018  /* This is an internally used function to see whether a pixmap file exists. */  019 static gchar* check_file_exists        (const gchar     *directory,  020                                        const gchar     *filename);  021  022  /* This is an internally used function to create pixmaps. */  023 static GtkWidget* create_dummy_pixmap  (GtkWidget       *widget);  024  025 GtkWidget*  026 lookup_widget                          (GtkWidget       *widget,  027                                         const gchar     *widget_name)  028 { 029   GtkWidget *parent, *found_widget;  030  031   for (;;)  032     { 033      if (GTK_IS_MENU (widget))  034         parent = gtk_menu_get_attach_widget (GTK_MENU (widget));  035       else  036         parent = widget->parent;  037       if (parent == NULL)  038         break;  039       widget = parent;  040     }  041  042   found_widget = (GtkWidget*) gtk_object_get_data (GTK_OBJECT (widget),  043                                                    widget_name);  044   if (!found_widget)  045     g_warning ("Widget not found: %s", widget_name);  046   return found_widget;  047 }  048  049  /* This is a dummy pixmap you use when a pixmap can't be found. */  050 static char * *dummy_pixmap_xpm[] = { 051  /* columns rows colors chars-per-pixel */  052 "1 1 1 1",  053 "  c None",  054  /* pixels */  055 " "  056 };  057  058  /* This is an internally used function to create pixmaps. */  059 static GtkWidget*  060 create_dummy_pixmap                    (GtkWidget       *widget)  061 { 062   GdkColormap *colormap;  063   GdkPixmap *gdkpixmap;  064   GdkBitmap *mask;  065   GtkWidget *pixmap;  066  067   colormap = gtk_widget_get_colormap (widget);  068   gdkpixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap, &mask,  069                                                      NULL, dummy_pixmap_xpm);  070   if (gdkpixmap == NULL)  071     g_error ("Couldn't create replacement pixmap.");  072   pixmap = gtk_pixmap_new (gdkpixmap, mask);  073   gdk_pixmap_unref (gdkpixmap);  074   gdk_bitmap_unref (mask);  075   return pixmap;  076 }  077  078 static GList *pixmaps_directories = NULL;  079  080  /* Use this function to set the directory containing installed pixmaps. */  081 void  082 add_pixmap_directory                   (const gchar     *directory)  083 { 084   pixmaps_directories = g_list_prepend (pixmaps_directories,  085                                         g_strdup (directory));  086 }  087  088  /* This is an internally used function to create pixmaps. */  089 GtkWidget*  090 create_pixmap                          (GtkWidget       *widget,  091                                         const gchar     *filename)  092 { 093   gchar *found_filename = NULL;  094   GdkColormap *colormap;    095   GdkPixmap *gdkpixmap;  096   GdkBitmap *mask;  097   GtkWidget *pixmap;  098   GList *elem;  099  100  /* You first try any pixmap directories set by the application.  */  101   elem = pixmaps_directories;  102  while (elem)  103    { 104       found_filename = check_file_exists ((gchar*)elem->data, filename);  105       if (found_filename)  106         break;  107       elem = elem->next;  108    }  109  110  /* If you haven't found the pixmap, try the source directory.  */  111   if (!found_filename)  112     { 113       found_filename = check_file_exists ("../pixmaps", filename);  114     }  115  116   if (!found_filename)  117     { 118       g_warning (_("Couldn't find pixmap file: %s"), filename);  119       return create_dummy_pixmap (widget);  120     }  121  122   colormap = gtk_widget_get_colormap (widget);  123   gdkpixmap = gdk_pixmap_colormap_create_from_xpm (NULL, colormap, &mask,  124                                                    NULL, found_filename);  125   if (gdkpixmap == NULL)  126     { 127       g_warning (_("Error loading pixmap file: %s"), found_filename);  128       g_free (found_filename);  129       return create_dummy_pixmap (widget);  130     }  131   g_free (found_filename);  132   pixmap = gtk_pixmap_new (gdkpixmap, mask);  133   gdk_pixmap_unref (gdkpixmap);  134   gdk_bitmap_unref (mask);  135   return pixmap;  136 }  137  138  /* This is an internally used function to see whether a pixmap file exists. */  139 gchar*  140 check_file_exists                      (const gchar     *directory,  141                                         const gchar     *filename)  142 { 143   gchar *full_filename;  144   struct stat s;  145   gint status;  146  147   full_filename = (gchar*) g_malloc (strlen (directory) + 1  148                                      + strlen (filename) + 1);  149   strcpy (full_filename, directory);  150   strcat (full_filename, G_DIR_SEPARATOR_S);  151   strcat (full_filename, filename);  152  153   status = stat (full_filename, &s);  154   if (status == 0 && S_ISREG (s.st_mode))  155     return full_filename;  156   g_free (full_filename);  157   return NULL;  158 } 

Lines 1 through 16 were covered previously in Listings 5.3 and 5.4 and their commentaries. Lines 18 through 23 are function prototypes for functions that come later in the file. Line 25 starts the lookup_widget function, which you will find to be extremely useful. It takes two parameters: The first is normally the top-level window, and the second is normally the name of a child widget within the top-level window parameter. Note that the child widget is passed in as a string, not a widget object. The purpose of this is to allow the project to have only the top-level windows as global variables , but to still allow access to any of the child widgets via the lookup_widget function. A full demonstration will follow at the end of this chapter. This file is smart, well-implemented, and solid from a software engineering standpoint.

The rest of the file contains some self-explanatory functions.

callbacks.c

Finally, you come to callbacks.c . Glade creates this file with empty functions relating to the signals you specified from the Properties window when you were using Glade. Glade will not overwrite the functions you create when or if you reopen Glade and edit your project. However, I have noticed that occasionally, it may create the same function twice after editing an existing project.

Listing 5.6 HelloWorld s callbacks.c
 01 #ifdef HAVE_CONFIG_H  02 # include <config.h>  03 #endif  04  05 #include <gtk/gtk.h>  06  07 #include "callbacks.h"  08 #include "interface.h"  09 #include "support.h"  10  11  12 void    13 on_cmd_main_clicked                    (GtkButton       *button,  14                                         gpointer         user_data)  15 { 16    gtk_main_quit();  17 } 

Line 16 was added as the last step for completing this program. Other than that, this is a straightforward file. It has one added callback on the clicked signal of cmd_main .

HelloWorld.glade

The file HelloWorld.glade is the Glade project file. It contains all the information needed to call up the project in Glade for editing. It stores the information in XML.

Listing 5.7 HelloWorld.glade
 01 <?xml version="1.0"?>  02 <GTK-Interface>  03  04 <project>  05   <name>HelloWorld</name>  06   <program_name>helloworld</program_name>  07   <directory></directory>  08   <source_directory>src</source_directory>  09   <pixmaps_directory>pixmaps</pixmaps_directory>  10   <language>C</language>  11   <gnome_support>False</gnome_support>  12   <gettext_support>True</gettext_support>  13   <use_widget_names>False</use_widget_names>  14   <output_main_file>True</output_main_file>  15   <output_support_files>True</output_support_files>  16   <output_build_files>True</output_build_files>  17   <backup_source_files>True</backup_source_files>  18   <main_source_file>interface.c</main_source_file>  19   <main_header_file>interface.h</main_header_file>  20   <handler_source_file>callbacks.c</handler_source_file>  21   <handler_header_file>callbacks.h</handler_header_file>  22   <support_source_file>support.c</support_source_file>  23   <support_header_file>support.h</support_header_file>  24   <translatable_strings_file></translatable_strings_file>  25 </project>  26  27 <widget>  28   <class>GtkWindow</class>  29   <name>frm_main</name>  30   <title>HelloWorld</title>  31  <type>GTK_WINDOW_TOPLEVEL</type>  32   <position>GTK_WIN_POS_NONE</position>  33  <modal>False</modal>  34   <allow_shrink>False</allow_shrink>  35   <allow_grow>True</allow_grow>  36   <auto_shrink>False</auto_shrink>  37  38   <widget>  39     <class>GtkButton</class>  40     <name>cmd_main</name>  41     <can_focus>True</can_focus>  42     <signal>  43       <name>clicked</name>  44       <handler>on_cmd_main_clicked</handler>  45       <last_modification_time>Wed, 06 Sep 2000 15:41:32  GMT</last_modification_time>  46      </signal>  47      <label>HelloWorld  48  Click to Close.</label>  49    </widget>  50  </widget>  51   52  </GTK-Interface> 

As you can see, this file is in XML. For those of you who don t know what XML is, here is a short explanation. By looking at the file, you can tell it is similar to HTML. (For those of you who don t know HTML, sorry, but I have to start somewhere You still should be able to pick up the main points.) The difference is that in HTML, the tags are defined for you, whereas in XML you define not only the data, but the tags as well. Look at lines 27 through 29 in Listing 5.7. Line 27, <widget> , defines a widget object. Line 29 tells the name of the object defined on line 27; the tag <name> is followed by the data frm_main , followed by the closing tag </name> . Line 50 closes out the widget object started on line 27 with the </widget> tag. Notice that a sub-widget is defined between lines 38 and 49. In this manner, an entire tree of disparate object types can be defined; to read a file like this, all you need is an XML parser. You don t need to know anything about the data, what type it is, what structure it is in, and so on.That is the strength of XML.

As to Listing 5.7, once you understand XML, it is rather self-explanatory.

only for RuBoard - do not distribute or recompile


MySQL Building User Interfaces
MySQL: Building User Interfaces (Landmark)
ISBN: 073571049X
EAN: 2147483647
Year: 2001
Pages: 119

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net